/**
 * Exclusive Closet BD — Version 10 visual freeze.
 * Loaded after the historical child-theme sheet; selectors are scoped to the
 * ecb-v10 body class so the module can be rolled back without data changes.
 */

:root {
	--v10-ink: #1A1310;
	--v10-ink-soft: #4A3B31;
	--v10-muted: #9A897B;
	--v10-accent: #B8873B;
	--v10-accent-hi: #D2A45C;
	--v10-red: #E4001E;   /* the logo's red */
	--ecb-stock-ok: #186032;   /* healthy stock; each layer restates it for its ground */
	--v10-page: #FBF8F4;
	--v10-paper: #FFFDFA;
	--v10-wash: #F4EDE3;
	--v10-rule: #E4DBCF;
	--v10-dark: #17100D;
	--v10-dark-soft: #241812;
	--v10-shell: 1320px;
	/* Noto Sans Bengali sits in both stacks for the reason the token block
	   further down already gives: its @font-face carries a unicode-range that
	   matches Bengali codepoints only, so it cannot change how a single Latin
	   character renders — but without it every word of Bangla on the site, and
	   the ৳ sign with it, fell through to whatever the device happened to have.
	   The V9 tokens were fixed for this long ago; the V10 pair was missed. */
	--v10-body: "Rubik", "Noto Sans Bengali", "Avenir Next", "Segoe UI", sans-serif;
	--v10-display: "Cormorant Garamond", "Tiro Bangla", "Noto Sans Bengali", Georgia, serif;
	--v10-ease: cubic-bezier(.22, .61, .36, 1);
}

html.ecb-v10-locked,
html.ecb-v10-locked body { overflow: hidden; }

body.ecb-v10 {
	background: var(--v10-page);
	color: var(--v10-ink);
	font-family: var(--v10-body);
	font-weight: 400;
	-webkit-font-smoothing: antialiased;
}

body.ecb-v10 a { color: inherit; }

/* …except a link that is dressed as a button.

   The rule above is (0,1,2) — `body` + `.ecb-v10` + `a`. Every `.ecb-btn`
   variant in style.css is a single class at (0,1,0), so `color: inherit` beat
   all of them and every button took the body text colour instead of its own.
   In dark that is a light colour on a dark button and looks correct by pure
   accident; in light it made "Shop all" #453B33 on #5A1231 — 1.4:1, a solid
   block with a word buried in it.

   Restated here at (0,2,0) so the buttons carry their own colour again, and on
   the V10 palette while we are at it: the burgundy these still used is the one
   the shop asked to be rid of, and it is the last of it on a customer-facing
   control. */
body.ecb-v10 .ecb-btn {
	background-color: var(--v10-dark);
	border-color: var(--v10-dark);
	color: #FFFFFF;
}

body.ecb-v10 .ecb-btn:hover,
body.ecb-v10 .ecb-btn:focus-visible {
	background-color: var(--v10-accent);
	border-color: var(--v10-accent);
	color: #FFFFFF;
}

/* The quiet one beside it: outlined, ink on the page. */
body.ecb-v10 .ecb-btn--ghost {
	background-color: transparent;
	border-color: var(--v10-dark);
	color: var(--v10-ink);
}

body.ecb-v10 .ecb-btn--ghost:hover,
body.ecb-v10 .ecb-btn--ghost:focus-visible {
	background-color: var(--v10-dark);
	border-color: var(--v10-dark);
	color: #FFFFFF;
}

/* On a dark band the pair invert, or they disappear into it. */
body.ecb-v10 .ecb-btn--light {
	background-color: #FFFFFF;
	border-color: #FFFFFF;
	color: var(--v10-dark);
}

body.ecb-v10 .ecb-btn--light:hover,
body.ecb-v10 .ecb-btn--light:focus-visible {
	background-color: var(--v10-accent-hi);
	border-color: var(--v10-accent-hi);
	color: var(--v10-dark);
}
body.ecb-v10 :where(a, button, input, select, textarea, summary):focus-visible {
	outline: 2px solid var(--v10-accent);
	outline-offset: 3px;
}

.ecb-v10-shell {
	width: min(100%, var(--v10-shell));
	margin-inline: auto;
	padding-inline: 40px;
}

.ecb-v10-eyebrow {
	margin: 0;
	color: var(--v10-accent);
	font: 500 10.5px/1.4 var(--v10-body);
	letter-spacing: .24em;
	text-transform: uppercase;
}

/* The custom shell owns presentation; Blocksy remains available as rollback. */
body.ecb-v10 #header,
body.ecb-v10 .ct-footer,
body.ecb-v10 .ecb-dock,
body.ecb-v10 .ecb-fab,
body.ecb-v10 .ecb-footstrip { display: none !important; }

body.ecb-v10 .site-main { min-height: 45vh; }
body.ecb-v10 .entry-content { margin-top: 0; }
body.ecb-v10.home .site-main > .hero-section,
body.ecb-v10.home .entry-header,
body.ecb-v10.home .page-title,
body.ecb-v10-contact-page .site-main > .hero-section,
body.ecb-v10-contact-page .entry-header { display: none; }

.ecb-v10-skip {
	position: fixed;
	z-index: 100000;
	top: 8px;
	left: 8px;
	padding: 10px 14px;
	background: var(--v10-paper);
	color: var(--v10-ink);
	transform: translateY(-150%);
	transition: transform 160ms ease;
}
.ecb-v10-skip:focus { transform: none; }

/* --------------------------------------------------------------------------
   Header
   -------------------------------------------------------------------------- */
.ecb-v10-header {
	position: sticky;
	z-index: 9000;
	top: 0;
	width: 100%;
	/* Solid. The header has no backdrop blur, so a fractional alpha only lets
	   the page show through it — see the dark sheet, where the same 3-4% was
	   letting a section heading be read straight through the nav bar. */
	background: #FBF8F4;
	box-shadow: 0 0 0 transparent;
	transition: box-shadow 260ms ease;
}
.admin-bar .ecb-v10-header { top: 32px; }
.ecb-v10-header.is-scrolled { box-shadow: 0 12px 34px rgba(23, 16, 13, .09); }
.ecb-v10-announcement {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 14px;
	min-height: 42px;
	padding: 8px 16px;
	background: var(--v10-dark);
	color: #EFE4D4;
	font-size: 11.5px;
	letter-spacing: .16em;
	text-align: center;
	text-transform: uppercase;
	overflow: hidden;
	transition: max-height 260ms var(--v10-ease), min-height 260ms var(--v10-ease), padding 260ms var(--v10-ease), opacity 180ms ease;
}
.ecb-v10-announcement i { width: 3px; height: 3px; flex: 0 0 3px; border-radius: 50%; background: var(--v10-accent); }
.ecb-v10-announcement strong { color: var(--v10-accent-hi); font-weight: 500; }
.ecb-v10-headmain {
	max-height: 90px;
	border-bottom: 1px solid #EDE4D8;
	overflow: hidden;
	transition: max-height 260ms var(--v10-ease), opacity 200ms ease;
}
.ecb-v10-headmain__inner { display: flex; align-items: center; min-height: 90px; gap: 30px; }
.ecb-v10-logo { display: inline-flex; flex: 0 0 auto; text-decoration: none; }
.ecb-v10-brand { display: inline-flex; align-items: center; gap: 12px; }
.ecb-v10-brand > img { display: block; width: auto; height: 44px; object-fit: contain; }
.ecb-v10-brand__words { display: block; white-space: nowrap; }
.ecb-v10-brand__words > span {
	display: block;
	font: 400 18px/1 var(--v10-display);
	letter-spacing: .15em;
	text-transform: uppercase;
}
.ecb-v10-brand__words small {
	display: block;
	margin-top: 6px;
	color: var(--v10-accent);
	font: 500 8px/1 var(--v10-body);
	letter-spacing: .42em;
	text-transform: uppercase;
}
.ecb-v10-topnav { display: flex; align-items: center; gap: 25px; margin-right: auto; }
.ecb-v10-topnav a,
.ecb-v10-actions > a,
.ecb-v10-signin {
	position: relative;
	font-size: 11.5px;
	letter-spacing: .14em;
	text-decoration: none;
	text-transform: uppercase;
}
.ecb-v10-topnav a::after {
	position: absolute;
	left: 0;
	right: 100%;
	bottom: -9px;
	height: 1px;
	background: var(--v10-accent);
	content: "";
	transition: right 240ms var(--v10-ease);
}
.ecb-v10-topnav a:hover::after,
.ecb-v10-topnav a:focus-visible::after { right: 0; }
.ecb-v10-topnav .is-sale { color: var(--v10-red); font-weight: 600; }
.ecb-v10-actions { display: flex; align-items: center; gap: 13px; }
.ecb-v10-signin { margin-right: 7px; }
.ecb-v10-iconbtn {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 42px;
	height: 42px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: var(--v10-ink);
	cursor: pointer;
	transition: color 220ms ease, background 220ms ease;
}
.ecb-v10-iconbtn:hover { background: var(--v10-wash); color: var(--v10-accent); }
.ecb-v10-bag__count {
	position: absolute;
	top: 1px;
	right: 0;
	display: grid;
	place-items: center;
	min-width: 18px;
	height: 18px;
	padding-inline: 3px;
	border-radius: 9px;
	background: var(--v10-accent);
	color: #fff;
	font-size: 10.5px;
	letter-spacing: 0;
}
.ecb-v10-mobile-only { display: none; }
.ecb-v10-catnav { position: relative; border-bottom: 1px solid #EDE4D8; background: var(--v10-page); }
.ecb-v10-catnav > .ecb-v10-shell > ul { display: flex; align-items: center; justify-content: center; gap: 38px; min-height: 48px; margin: 0; padding: 0; list-style: none; }
.ecb-v10-catnav > .ecb-v10-shell > ul > li { position: relative; align-self: stretch; display: flex; align-items: center; }
.ecb-v10-catnav a { text-decoration: none; }
.ecb-v10-catnav > .ecb-v10-shell > ul > li > a {
	position: relative;
	display: flex;
	align-items: center;
	height: 100%;
	font-size: 11.5px;
	font-weight: 500;
	letter-spacing: .14em;
	text-transform: uppercase;
}
.ecb-v10-catnav > .ecb-v10-shell > ul > li > a::after {
	position: absolute;
	left: 50%;
	right: 50%;
	bottom: 0;
	height: 2px;
	background: var(--v10-accent);
	content: "";
	transition: left 260ms var(--v10-ease), right 260ms var(--v10-ease);
}
.ecb-v10-catnav > .ecb-v10-shell > ul > li:hover > a::after,
.ecb-v10-catnav > .ecb-v10-shell > ul > li:focus-within > a::after,
.ecb-v10-catnav > .ecb-v10-shell > ul > li.is-current > a::after { left: 0; right: 0; }
/* One line at a time: while another heading is hovered, tapped or focused, the
   current heading's line gives way instead of showing two blue lines together. */
.ecb-v10-catnav > .ecb-v10-shell > ul:has(> li:not(.is-current):is(:hover, :focus-within)) > li.is-current > a::after { left: 50%; right: 50%; }
.ecb-v10-dropdown,
.ecb-v10-flyout {
	position: absolute;
	z-index: 100;
	top: 100%;
	left: 50%;
	width: 270px;
	margin: 0;
	padding: 10px 0;
	border: 1px solid var(--v10-rule);
	background: var(--v10-paper);
	box-shadow: 0 18px 46px rgba(23, 16, 13, .14);
	list-style: none;
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transform: translate(-50%, -8px);
	transition: opacity 220ms ease, transform 280ms var(--v10-ease), visibility 0s linear 280ms;
}
.ecb-v10-catnav li:hover > .ecb-v10-dropdown,
.ecb-v10-catnav li:focus-within > .ecb-v10-dropdown { opacity: 1; visibility: visible; pointer-events: auto; transform: translate(-50%, 0); transition-delay: 0s; }
.ecb-v10-dropdown li { position: relative; margin: 0; }
.ecb-v10-dropdown li > a,
.ecb-v10-flyout li > a {
	display: flex;
	align-items: center;
	justify-content: space-between;
	min-height: 42px;
	padding: 8px 18px;
	color: var(--v10-ink-soft);
	font-size: 13px;
	letter-spacing: .01em;
	transition: padding-left 220ms var(--v10-ease), color 180ms ease, background 180ms ease;
}
.ecb-v10-dropdown li > a:hover,
.ecb-v10-dropdown li > a:focus-visible,
.ecb-v10-flyout li > a:hover,
.ecb-v10-flyout li > a:focus-visible { padding-left: 23px; background: #F7EEDD; color: var(--v10-ink); }
.ecb-v10-flyout { top: -11px; left: calc(100% + 1px); transform: translate(-8px, 0); }
.ecb-v10-menu__branch:hover > .ecb-v10-flyout,
.ecb-v10-menu__branch:focus-within > .ecb-v10-flyout { opacity: 1; visibility: visible; pointer-events: auto; transform: translate(0, 0); transition-delay: 0s; }
.ecb-v10-header.is-condensed .ecb-v10-announcement {
	max-height: 0; min-height: 0; padding-block: 0; opacity: 0;
}

/* --------------------------------------------------------------------------
   Drawer and search modal
   -------------------------------------------------------------------------- */
.ecb-v10-drawer,
.ecb-v10-search { position: fixed; z-index: 20000; inset: 0; opacity: 0; visibility: hidden; transition: opacity 240ms ease, visibility 0s linear 260ms; }
.ecb-v10-drawer.is-open,
.ecb-v10-search.is-open { opacity: 1; visibility: visible; transition-delay: 0s; }
.ecb-v10-drawer__scrim,
.ecb-v10-search__scrim { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; background: rgba(23, 16, 13, .72); cursor: default; }
.ecb-v10-drawer__panel {
	position: absolute;
	top: 0;
	bottom: 0;
	left: 0;
	width: min(90vw, 390px);
	padding: 22px;
	background: var(--v10-dark-soft);
	color: #EFE4D4;
	overflow-y: auto;
	transform: translateX(-100%);
	transition: transform 320ms var(--v10-ease);
}
.ecb-v10-drawer.is-open .ecb-v10-drawer__panel { transform: translateX(0); }
.ecb-v10-drawer .ecb-v10-brand__words > span { color: #fff; }
.ecb-v10-drawer__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 24px; }
.ecb-v10-drawer__head button { width: 44px; height: 44px; border: 1px solid rgba(255,255,255,.22); background: transparent; color: #fff; font-size: 26px; cursor: pointer; }
.ecb-v10-drawer details { border-top: 1px solid rgba(255,255,255,.12); }
.ecb-v10-drawer summary,
.ecb-v10-drawer__direct { display: flex; align-items: center; justify-content: space-between; min-height: 52px; color: #EFE4D4; font-size: 12px; letter-spacing: .16em; text-decoration: none; text-transform: uppercase; cursor: pointer; list-style: none; }
.ecb-v10-drawer summary::-webkit-details-marker { display: none; }
.ecb-v10-drawer summary span { color: var(--v10-accent-hi); font-size: 20px; transition: transform 200ms ease; }
.ecb-v10-drawer details[open] summary span { transform: rotate(45deg); }
.ecb-v10-drawer details > div { padding: 0 0 14px 14px; }
.ecb-v10-drawer details a { display: block; padding: 9px 0; color: #B6A697; font-size: 13px; text-decoration: none; }
.ecb-v10-drawer details a:hover { color: var(--v10-accent-hi); }
.ecb-v10-drawer__foot { display: flex; gap: 20px; margin-top: 28px; padding-top: 20px; border-top: 1px solid rgba(255,255,255,.12); }
.ecb-v10-drawer__foot a { color: var(--v10-accent-hi); font-size: 12px; letter-spacing: .12em; text-decoration: none; text-transform: uppercase; }
.ecb-v10-search { display: grid; place-items: center; padding: 20px; }
/* Same trap as .ecb-live-viewers: `display: grid` above outranks the browser's
   own [hidden] rule, so the closed overlay was still laid out across the whole
   viewport — invisible only because of the `visibility: hidden` it shares with
   the drawer. Safe to remove properly: the script unhides on one frame and adds
   .is-open on the next, which is exactly what a display change needs for the
   fade to still run. */
.ecb-v10-search[hidden] { display: none; }
.ecb-v10-search__dialog {
	position: relative;
	z-index: 1;
	width: min(100%, 660px);
	padding: 52px;
	background: var(--v10-paper);
	box-shadow: 0 30px 80px rgba(23,16,13,.28);
	transform: translateY(18px) scale(.98);
	transition: transform 300ms var(--v10-ease);
}
.ecb-v10-search.is-open .ecb-v10-search__dialog { transform: none; }
.ecb-v10-search__dialog h2 { margin: 10px 0 24px; font: 400 42px/1.1 var(--v10-display); }
.ecb-v10-search__dialog form { display: grid; grid-template-columns: 1fr auto; }
.ecb-v10-search__dialog input { min-width: 0; height: 54px; padding: 0 18px; border: 1px solid var(--v10-rule); background: #fff; font: 400 14px var(--v10-body); }
.ecb-v10-search__dialog form button { min-width: 128px; border: 0; background: var(--v10-dark); color: #fff; font: 500 11px var(--v10-body); letter-spacing: .16em; text-transform: uppercase; }
.ecb-v10-search__close { position: absolute; top: 14px; right: 14px; width: 42px; height: 42px; border: 0; background: transparent; color: var(--v10-ink); font-size: 28px; cursor: pointer; }

/* --------------------------------------------------------------------------
   Shared headings and buttons
   -------------------------------------------------------------------------- */
/* Vertical rhythm, in one place.

   The page was built on 96px section padding, which is a magazine measure: it
   suits a spread where each section is a destination. A shop is read by
   scrolling, and at 96px top and bottom the reader crosses 192px of nothing
   between one row of products and the next — most of a laptop screen spent on
   paper. Pulled to 64px, which still separates the sections clearly and puts
   roughly one more band of product on screen at every scroll position.

   Changing these two values moves the whole page, so the spacing stays even.
   Nothing below should hard-code a section gap again. */
:root {
	--v10-section-y: 64px;   /* top and bottom of every band */
	--v10-head-gap: 30px;    /* heading block to the content under it */
}

.ecb-v10-section { padding: var(--v10-section-y) 0; background: var(--v10-page); }

/* Two bands on the same ground stack their padding into one long empty strip —
   128px on a computer between As Seen On and Customer Stories, 92px on a phone,
   measured 11 Sep 2026. The second band keeps half its top padding instead.
   Category by Occasion -> All Categories counts as the same ground: #FCFBF9
   against #FFFFFF does not read as an edge. ecb-dc.css does the same for every
   seam, because in the dark theme every band is transparent. */
.ecb-v10-section + .ecb-v10-categories,
.ecb-v10-seenon + .ecb-v10-stories { padding-top: calc(var(--v10-section-y) / 2); }
.ecb-v10-sectionhead { margin-bottom: var(--v10-head-gap); text-align: center; }
.ecb-v10-sectionhead h2 { margin: 10px 0 0; color: var(--v10-ink); font: 400 clamp(34px, 3vw, 44px)/1.08 var(--v10-display); letter-spacing: -.01em; text-transform: none; }
.ecb-v10-sectionhead.is-row { display: flex; align-items: end; justify-content: space-between; gap: 24px; text-align: left; }
.ecb-v10-sectionhead.is-row > a { padding-bottom: 5px; border-bottom: 1px solid var(--v10-accent); color: var(--v10-accent); font-size: 11px; letter-spacing: .16em; text-decoration: none; text-transform: uppercase; }
.ecb-v10-button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 50px;
	padding: 0 32px;
	border: 1px solid currentColor;
	font: 500 11.5px/1 var(--v10-body);
	letter-spacing: .16em;
	text-decoration: none;
	text-transform: uppercase;
	transition: background 220ms ease, color 220ms ease, border-color 220ms ease;
}
.ecb-v10-button.is-light { border-color: var(--v10-paper); background: var(--v10-paper); color: var(--v10-dark); }
.ecb-v10-button.is-light:hover { border-color: var(--v10-accent-hi); background: var(--v10-accent-hi); }
.ecb-v10-button.is-ghost { border-color: rgba(255,255,255,.55); background: rgba(255,255,255,.04); color: #fff; }
.ecb-v10-button.is-ghost:hover { border-color: #fff; background: rgba(255,255,255,.12); }
.ecb-v10-button.is-dark { border-color: var(--v10-dark); background: var(--v10-dark); color: #fff; }
.ecb-v10-button.is-dark:hover { border-color: var(--v10-accent); background: var(--v10-accent); }
.ecb-v10-center { margin-top: 28px; text-align: center; }
.ecb-v10-carousel-buttons { display: flex; gap: 9px; }
.ecb-v10-carousel-buttons button { width: 48px; height: 48px; border: 1px solid var(--v10-rule); background: var(--v10-paper); color: var(--v10-ink); font-size: 18px; cursor: pointer; transition: border-color 180ms ease, color 180ms ease; }
.ecb-v10-carousel-buttons button:hover { border-color: var(--v10-accent); color: var(--v10-accent); }

/* --------------------------------------------------------------------------
   Homepage
   -------------------------------------------------------------------------- */
.ecb-v10-home,
.ecb-v10-contact { width: 100vw; margin-left: calc(50% - 50vw); }
.ecb-v10-hero { position: relative; height: 640px; overflow: hidden; background: var(--v10-dark); color: #fff; }
.ecb-v10-hero__slide { position: absolute; inset: 0; opacity: 0; pointer-events: none; transition: opacity 1100ms var(--v10-ease); }
.ecb-v10-hero__slide.is-active { z-index: 1; opacity: 1; pointer-events: auto; }
.ecb-v10-hero__slide > img { width: 100%; height: 100%; object-fit: cover; filter: saturate(1.04) contrast(1.03); transform: scale(1); transition: transform 7000ms linear; }
.ecb-v10-hero__slide.is-active > img { transform: scale(1.05); }
.ecb-v10-hero__scrim { position: absolute; inset: 0; background: linear-gradient(100deg, rgba(20,12,10,.9) 0%, rgba(28,17,13,.63) 27%, rgba(35,22,17,.15) 54%, transparent 72%); }
.ecb-v10-hero__inner { position: absolute; z-index: 2; inset: 0; display: flex; align-items: center; }
.ecb-v10-hero__copy { width: min(580px, 58vw); opacity: 0; transform: translateY(24px); transition: opacity 700ms ease 180ms, transform 700ms var(--v10-ease) 180ms; }
.is-active .ecb-v10-hero__copy { opacity: 1; transform: none; }
.ecb-v10-hero__copy h1,
.ecb-v10-hero__copy h2 { margin: 15px 0 0; color: #fff; font: 400 clamp(52px, 5vw, 70px)/.98 var(--v10-display); letter-spacing: -.02em; }
.ecb-v10-hero__copy h1 em,
.ecb-v10-hero__copy h2 em { display: block; color: var(--v10-accent-hi); font-weight: 400; }
.ecb-v10-hero__copy > p:not(.ecb-v10-eyebrow) { max-width: 450px; margin: 22px 0 0; color: rgba(255,255,255,.82); font-size: 15px; line-height: 1.7; }
.ecb-v10-hero__copy > div { display: flex; gap: 13px; margin-top: 32px; }
.ecb-v10-hero__arrow { position: absolute; z-index: 3; top: 50%; width: 52px; height: 52px; border: 1px solid rgba(255,255,255,.38); background: rgba(23,16,13,.26); color: #fff; font: 300 34px/1 var(--v10-body); cursor: pointer; transform: translateY(-50%); transition: background 180ms ease; }
.ecb-v10-hero__arrow:hover { background: rgba(255,255,255,.18); }
.ecb-v10-hero__arrow.is-prev { left: 25px; }
.ecb-v10-hero__arrow.is-next { right: 25px; }
.ecb-v10-hero__dots { position: absolute; z-index: 3; left: 50%; bottom: 24px; display: flex; gap: 4px; transform: translateX(-50%); }
.ecb-v10-hero__dots button { position: relative; width: 44px; height: 44px; padding: 0; border: 0; background: transparent; cursor: pointer; }
.ecb-v10-hero__dots button::after { position: absolute; top: 50%; left: 50%; width: 14px; height: 2px; background: rgba(255,255,255,.45); content: ""; transform: translate(-50%, -50%); transition: width 300ms ease, background 300ms ease; }
.ecb-v10-hero__dots button.is-active::after { width: 34px; background: var(--v10-accent-hi); }
.ecb-v10-trust { display: grid; grid-template-columns: repeat(4, 1fr); margin: 0; border-bottom: 1px solid var(--v10-rule); background: var(--v10-wash); }
.ecb-v10-trust a { min-height: 96px; padding: 24px 30px; border-right: 1px solid var(--v10-rule); text-align: center; text-decoration: none; transition: background 220ms ease, transform 220ms var(--v10-ease); }
.ecb-v10-trust a:last-child { border-right: 0; }
.ecb-v10-trust a:hover { background: #EFE5D6; transform: translateY(-2px); }
.ecb-v10-trust b,
.ecb-v10-trust span { display: block; }
.ecb-v10-trust b { font: 500 11px/1.4 var(--v10-body); letter-spacing: .16em; text-transform: uppercase; }
.ecb-v10-trust span { margin-top: 7px; color: var(--v10-muted); font-size: 12.5px; }
.ecb-v10-occasion-grid { display: grid; grid-template-columns: 1fr 1.18fr 1fr; grid-template-rows: repeat(2, 300px); gap: 20px; }
.ecb-v10-occasion { position: relative; display: block; overflow: hidden; background: var(--v10-wash); }
.ecb-v10-occasion:nth-child(1) { grid-area: 1 / 1; }
.ecb-v10-occasion:nth-child(2) { grid-area: 1 / 2 / 3 / 3; }
.ecb-v10-occasion:nth-child(3) { grid-area: 1 / 3; }
.ecb-v10-occasion:nth-child(4) { grid-area: 2 / 1; }
.ecb-v10-occasion:nth-child(5) { grid-area: 2 / 3; }
.ecb-v10-occasion img { width: 100%; height: 100%; object-fit: cover; transition: transform 800ms var(--v10-ease); }
.ecb-v10-occasion::after { position: absolute; inset: 42% 0 0; background: linear-gradient(to top, rgba(23,16,13,.82), transparent); content: ""; }
.ecb-v10-occasion span { position: absolute; z-index: 1; left: 25px; bottom: 23px; color: #fff; font-size: 16px; letter-spacing: .2em; text-transform: uppercase; }
.ecb-v10-occasion:hover img { transform: scale(1.06); }
.ecb-v10-categories { background: var(--v10-paper); }
.ecb-v10-categoryrail,
.ecb-v10-lookrail { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(230px, 1fr); gap: 20px; overflow-x: auto; overscroll-behavior-inline: contain; scroll-snap-type: inline mandatory; scrollbar-width: thin; }
.ecb-v10-categoryrail > a { scroll-snap-align: start; text-align: center; text-decoration: none; }
.ecb-v10-categoryrail > a > span { display: block; aspect-ratio: 4/5; overflow: hidden; background: var(--v10-wash); }
.ecb-v10-categoryrail img { width: 100%; height: 100%; object-fit: cover; transition: transform 700ms var(--v10-ease); }
.ecb-v10-categoryrail b { display: block; margin-top: 15px; font: 400 19px/1.2 var(--v10-display); }
.ecb-v10-categoryrail a:hover img { transform: scale(1.05); }
.ecb-v10-trending { background: var(--v10-dark); color: #fff; }
.ecb-v10-trending .ecb-v10-sectionhead h2 { color: #fff; }
.ecb-v10-trending .ecb-v10-carousel-buttons button { border-color: rgba(255,255,255,.28); background: rgba(255,255,255,.06); color: #fff; }
.ecb-v10-lookrail { grid-auto-columns: minmax(250px, 1fr); scrollbar-color: var(--v10-accent) rgba(255,255,255,.12); }
.ecb-v10-look { position: relative; height: 560px; overflow: hidden; scroll-snap-align: start; background: var(--v10-dark-soft); }
.ecb-v10-look > img { width: 100%; height: 100%; object-fit: cover; transition: transform 6000ms linear; }
/* A card may carry a clip. It covers its own poster and fades in only while
   the card is running, so a rail of four does not play four videos at once.
   No z-index: it is absolutely positioned and the img is not, so it already
   paints above it, and staying out of the stacking order leaves the ::after
   scrim and the caption exactly where they were. */
.ecb-v10-look__clip { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 420ms var(--v10-ease); }
.ecb-v10-look.is-active .ecb-v10-look__clip { opacity: 1; }
/* Linked cards are anchors now; they must not pick up link underlines. */
a.ecb-v10-look { display: block; color: inherit; text-decoration: none; }
.ecb-v10-look::after { position: absolute; inset: 0; background: linear-gradient(to top, rgba(23,16,13,.82), rgba(23,16,13,.08) 52%, rgba(23,16,13,.22)); content: ""; pointer-events: none; }
.ecb-v10-look__play { position: absolute; z-index: 2; top: 50%; left: 50%; display: grid; place-items: center; width: 62px; height: 62px; padding-left: 4px; border: 1px solid rgba(255,255,255,.66); border-radius: 50%; background: rgba(23,16,13,.34); color: #fff; transform: translate(-50%, -50%); transition: opacity 250ms ease; }
.ecb-v10-look > div { position: absolute; z-index: 2; right: 20px; bottom: 22px; left: 20px; }
.ecb-v10-look > div b,
.ecb-v10-look > div span { display: block; }
.ecb-v10-look > div b { font-size: 14px; letter-spacing: .04em; }
.ecb-v10-look > div span { margin-top: 4px; color: rgba(255,255,255,.67); font-size: 12px; }
.ecb-v10-look > div i { display: block; width: 0; height: 2px; margin-top: 14px; background: var(--v10-accent-hi); transition: width 200ms ease; }
.ecb-v10-look.is-active > img { transform: scale(1.09); }
.ecb-v10-look.is-active .ecb-v10-look__play { opacity: 0; transform: translate(-50%, -50%) scale(.84); }
.ecb-v10-look.is-active .ecb-v10-look__play::after { animation: none; }
.ecb-v10-look.is-active > div i { width: 100%; transition-duration: 6000ms; transition-timing-function: linear; }
.ecb-v10-trending__note { margin: 20px 0 0; color: rgba(255,255,255,.48); font-size: 11.5px; }

/* Before the card takes over, the control answers the cursor on its own. */
@media (hover: hover) {
	.ecb-v10-look:hover .ecb-v10-look__play,
	.ecb-v10-look:focus-visible .ecb-v10-look__play {
		background: rgba(23, 16, 13, .4);
		border-color: #fff;
	}
}

/* Product cards shared by homepage and archives. */
.ecb-v10-products { display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 22px; }
.ecb-v10-product { min-width: 0; }

/* The moving row.

   Four across, but laid out as columns that overflow rather than as a grid that
   wraps — so the row keeps going sideways and the browser gives us swiping,
   momentum and snapping for nothing. `scroll-snap-type: inline mandatory` is
   what makes an auto-advance land cleanly on a card instead of halfway across
   one, and it is also what stops a flicked finger leaving the row askew. */
.ecb-v10-products.is-rail {
	grid-template-columns: none;
	grid-auto-flow: column;
	grid-auto-columns: calc((100% - 66px) / 4);
	overflow-x: auto;
	overscroll-behavior-inline: contain;
	scroll-snap-type: inline mandatory;
	scrollbar-width: none;                /* the dots and arrows are the control */
	padding-bottom: 4px;
}

/* Snap is suspended while the script drives the scroll. Mandatory snap
   re-settles the rail on every scroll event, so it and a per-frame animation
   pull against each other and the row judders. Restored the moment the glide
   ends, so a flicked finger still lands on a card. */
.ecb-v10-products.is-rail.is-gliding,
.ecb-v10-categoryrail.is-gliding,
.ecb-v10-lookrail.is-gliding { scroll-snap-type: none; }

.ecb-v10-products.is-rail::-webkit-scrollbar { display: none; }
.ecb-v10-products.is-rail > .ecb-v10-product { scroll-snap-align: start; }
.ecb-v10-products.is-rail:focus-visible { outline: 2px solid var(--v10-accent); outline-offset: 6px; }

.ecb-v10-picks__head-actions { display: flex; align-items: center; gap: 20px; }
.ecb-v10-picks__head-actions > a { padding-bottom: 5px; border-bottom: 1px solid var(--v10-accent); color: var(--v10-accent); font-size: 11px; letter-spacing: .16em; text-decoration: none; text-transform: uppercase; white-space: nowrap; }

/* Dots, as on the hero: a short bar that stretches when it is the current one,
   which reads at a glance without asking anyone to count circles. */
.ecb-v10-dots { display: flex; justify-content: center; gap: 4px; margin-top: 22px; }
.ecb-v10-dots:empty { display: none; }
.ecb-v10-dots__dot { position: relative; width: 34px; height: 34px; padding: 0; border: 0; background: transparent; cursor: pointer; }
/* The off state sits on the hairline token in most of this sheet, which here
   measured 1.23:1 against the page — a control nobody can see is not a control.
   The muted token at half strength lands around 2.4:1: present enough to read
   as a row of buttons, quiet enough that the active bar still leads. */
.ecb-v10-dots__dot::after { position: absolute; top: 50%; left: 50%; width: 14px; height: 2px; background: var(--v10-muted); opacity: .5; content: ""; transform: translate(-50%,-50%); transition: width 300ms var(--v10-ease), background 300ms ease, opacity 300ms ease; }
.ecb-v10-dots__dot:hover::after { opacity: .8; }
.ecb-v10-dots__dot.is-active::after { width: 30px; background: var(--v10-accent); opacity: 1; }
.ecb-v10-dots__dot:focus-visible { outline: 2px solid var(--v10-accent); outline-offset: -4px; }
.ecb-v10-product__media { position: relative; aspect-ratio: 4/5; overflow: hidden; background: var(--v10-wash); }
.ecb-v10-product__media > a { display: block; width: 100%; height: 100%; }
.ecb-v10-product__image { width: 100% !important; height: 100% !important; margin: 0 !important; object-fit: cover; transition: transform 800ms var(--v10-ease); }
.ecb-v10-product__view { position: absolute; right: 0; bottom: 0; left: 0; display: flex; align-items: center; justify-content: space-between; min-height: 46px; padding: 0 16px; background: rgba(23,16,13,.9); color: #fff; font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase; transform: translateY(100%); transition: transform 260ms var(--v10-ease); }
.ecb-v10-product:hover .ecb-v10-product__image { transform: scale(1.055); }
.ecb-v10-product:hover .ecb-v10-product__view { transform: none; }
.ecb-v10-product__sale,
.ecb-v10-product__stock { position: absolute; z-index: 3; top: 12px; left: 12px; padding: 6px 9px; color: #fff; font-size: 11px; font-weight: 500; letter-spacing: .12em; text-transform: uppercase; }
.ecb-v10-product__sale { background: var(--v10-red); }
.ecb-v10-product__stock { background: var(--v10-dark); }
.ecb-v10-product__sale + .ecb-v10-product__stock { top: 42px; }
.ecb-v10-product .ecb-heart { top: 11px; right: 11px; }
.ecb-v10-product__body { position: relative; padding-top: 15px; }
.ecb-v10-product__eyebrow { margin: 0; color: var(--v10-muted); font-size: 10px; letter-spacing: .15em; text-transform: uppercase; }
.ecb-v10-product h3 { margin: 6px 0 0; font: 400 18px/1.3 var(--v10-display); }
.ecb-v10-product h3 a { text-decoration: none; }
/* The owner tapped the category and the price and nothing happened — only the
   name's own letters were a link. The name's link now stretches over the whole
   text block, so one link (one tab stop, one announcement) covers all of it.
   It needs z-index 1: the struck-out old price is drawn at opacity .7, which
   painted it above the link, and a tap on it did nothing. The colour
   swatches get z-index 2 so their tooltips still answer a tap. */
.ecb-v10-product h3 a::after { position: absolute; z-index: 1; inset: 0; content: ""; }
.ecb-v10-product__price { display: flex; align-items: baseline; gap: 9px; margin-top: 7px; font-size: 14px; }
.ecb-v10-product__price ins { color: var(--v10-red); text-decoration: none; }
.ecb-v10-product__price del { color: var(--v10-muted); font-size: 12px; }
.ecb-v10-product__swatches { display: flex; align-items: center; gap: 6px; min-height: 29px; margin-top: 8px; }
.ecb-v10-product__swatches > span { position: relative; z-index: 2; width: 17px; height: 17px; border: 1px solid #CFC7BD; background: var(--swatch); box-shadow: inset 0 0 0 2px var(--v10-paper); cursor: help; }
.ecb-v10-product__swatches i { position: absolute; z-index: 4; bottom: calc(100% + 8px); left: 50%; padding: 6px 8px; background: var(--v10-dark); color: #fff; font: normal 10px/1 var(--v10-body); white-space: nowrap; opacity: 0; pointer-events: none; transform: translate(-50%, 4px); transition: opacity 150ms ease, transform 150ms ease; }
.ecb-v10-product__swatches > span:hover i,
.ecb-v10-product__swatches > span:focus-visible i { opacity: 1; transform: translate(-50%, 0); }
.ecb-v10-arrivals { background: var(--v10-wash); }
.ecb-v10-arrival-grid { display: grid; grid-template-columns: 1.2fr 1fr 1fr; gap: 22px; align-items: start; }
.ecb-v10-arrival-grid .is-feature { grid-row: span 2; }
.ecb-v10-lookbook { background: var(--v10-paper); }
.ecb-v10-lookbook .ecb-v10-shell > div:last-child { display: grid; grid-template-columns: 1.5fr 1fr; grid-template-rows: repeat(2, 300px); gap: 20px; }
.ecb-v10-lookbook figure { margin: 0; overflow: hidden; background: var(--v10-wash); }
.ecb-v10-lookbook figure:first-child { grid-row: 1 / 3; }
.ecb-v10-lookbook img { width: 100%; height: 100%; object-fit: cover; transition: transform 900ms var(--v10-ease); }
.ecb-v10-lookbook figure:hover img { transform: scale(1.04); }
.ecb-v10-instagram { padding: 58px 20px; background: #EFE5D6; text-align: center; }
.ecb-v10-instagram h2 { margin: 10px 0; font: 400 46px/1.08 var(--v10-display); }
.ecb-v10-instagram p:not(.ecb-v10-eyebrow) { margin: 0 auto 25px; color: var(--v10-ink-soft); }
/* Instagram Diaries with a picture behind it (Appearance -> Homepage). Built like
   the wedding band — full-bleed picture, the same dark veil, white type — so the
   two read as one family. Without a picture none of this applies and the band
   keeps its cream ground. */
.ecb-v10-instagram.has-photo { position: relative; overflow: hidden; background: #17100D; color: #fff; }
.ecb-v10-instagram__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.ecb-v10-instagram.has-photo::after { position: absolute; inset: 0; background: rgba(23,16,13,.58); content: ""; }
.ecb-v10-instagram.has-photo > .ecb-v10-shell { position: relative; z-index: 1; }
.ecb-v10-instagram.has-photo h2 { color: #fff; }
.ecb-v10-instagram.has-photo p:not(.ecb-v10-eyebrow) { color: rgba(255,255,255,.82); }
.ecb-v10-wedding { position: relative; display: grid; min-height: 580px; place-items: center; overflow: hidden; color: #fff; text-align: center; }
.ecb-v10-wedding > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.ecb-v10-wedding::after { position: absolute; inset: 0; background: rgba(23,16,13,.58); content: ""; }
.ecb-v10-wedding > div { position: relative; z-index: 1; }
.ecb-v10-wedding h2 { max-width: 760px; margin: 12px auto; color: #fff; font: 400 clamp(48px, 6vw, 76px)/.98 var(--v10-display); }
.ecb-v10-wedding p:not(.ecb-v10-eyebrow) { margin: 0 0 28px; color: rgba(255,255,255,.78); }
/* --------------------------------------------------------------------------
   As Seen On

   A grid, not a rail. There are two or three of these and they are the loudest
   proof the shop has; putting them on a track would hide half of them behind a
   swipe nobody is told to make. Customer Stories under it is the rail, because
   there are many and they are read one at a time.
   -------------------------------------------------------------------------- */
.ecb-v10-seenon__grid {
	display: grid;
	/* Capped, not stretched. With `1fr` and two entries each card took half the
	   shell — 609px wide with a 759px portrait above it, a wall rather than a
	   row, and taller than the whole Customer Stories band under it. Held to
	   320px the portrait lands near 400px, the same weight as a product card,
	   and a third or fourth name simply joins the line instead of shrinking it. */
	grid-template-columns: repeat(auto-fit, minmax(230px, 320px));
	justify-content: center;
	/* Each card keeps its own height. Stretched to the row, an entry with no
	   picture became a tall empty box beside a portrait — the band read as
	   broken rather than as one name still waiting for its photograph. */
	align-items: start;
	gap: 22px;
}

.ecb-v10-seenon__card {
	margin: 0;
	border: 1px solid var(--v10-rule);
	background: var(--v10-paper);
	box-shadow: 0 14px 40px rgba(23, 16, 13, .06);
}

.ecb-v10-seenon__media {
	overflow: hidden;
	aspect-ratio: 4 / 5;
	background: var(--v10-page);
}

.ecb-v10-seenon__img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.ecb-v10-seenon__card figcaption {
	padding: 22px 24px 26px;
	text-align: center;
}

.ecb-v10-seenon__card b {
	display: block;
	font-size: 13px;
	letter-spacing: .12em;
	text-transform: uppercase;
}

.ecb-v10-seenon__card span {
	display: block;
	margin-top: 6px;
	color: var(--v10-muted);
	font-size: 12px;
}

/* "Show the whole picture" — the frame keeps its shape and the photograph sits
   inside it rather than being cut to fit. The ground is the page colour so the
   letterboxing reads as mount board, not as a loading error. Wide photographs
   of couples and groups need this; cropping them to a tall frame takes off
   somebody's head. */
.ecb-v10-story.is-whole .ecb-v10-story__media,
.ecb-v10-seenon__card.is-whole .ecb-v10-seenon__media { background: var(--v10-page); }

.ecb-v10-story.is-whole .ecb-v10-story__img,
.ecb-v10-seenon__card.is-whole .ecb-v10-seenon__img { object-fit: contain; }

/* Nothing to zoom into when the whole picture is already showing — growing it
   would just push the edges out of the frame. */
@media (hover: hover) {
	.ecb-v10-story.is-whole:hover .ecb-v10-story__img,
	.ecb-v10-story.is-whole:focus-within .ecb-v10-story__img,
	.ecb-v10-seenon__card.is-whole:hover .ecb-v10-seenon__img { transform: none; }
}

/* "See the post" / "Read it on Facebook".
   
   Quiet by default and underlined on hover rather than the other way round: the
   claim is the point, the link is the receipt. One rule covers both bands
   because they are the same control doing the same job. */
/* Scoped through `body.ecb-v10` to match `body.ecb-v10 a { color: inherit }`
   further up this sheet — (0,2,1). A bare class is (0,1,0) and lost the colour
   silently, leaving the link the same brown as the caption it sits under. */
body.ecb-v10 .ecb-v10-seenon__link,
body.ecb-v10 .ecb-v10-story__link {
	display: inline-block;
	margin-top: 12px;
	color: var(--v10-accent);
	font-size: 11px;
	letter-spacing: .1em;
	text-transform: uppercase;
	text-decoration: none;
	border-bottom: 1px solid transparent;
	transition: border-color 180ms ease;
}

body.ecb-v10 .ecb-v10-seenon__link:focus-visible,
body.ecb-v10 .ecb-v10-story__link:focus-visible {
	outline: 2px solid var(--v10-accent);
	outline-offset: 3px;
}

@media (hover: hover) {
	body.ecb-v10 .ecb-v10-seenon__link:hover,
	body.ecb-v10 .ecb-v10-story__link:hover { border-bottom-color: var(--v10-accent); }
}

@media (prefers-reduced-motion: reduce) {
	body.ecb-v10 .ecb-v10-seenon__link,
	body.ecb-v10 .ecb-v10-story__link { transition: none; }
}
/* Same 600ms lean as the story portraits, and behind the same guard: on a touch
   screen `:hover` latches after a tap and the picture would stay zoomed. */
@media (hover: hover) {
	.ecb-v10-seenon__img { transition: transform 900ms var(--v10-ease); }
	.ecb-v10-seenon__card.has-photo:hover .ecb-v10-seenon__img { transform: scale(1.14); }
}

@media (prefers-reduced-motion: reduce) {
	.ecb-v10-seenon__img { transition: none; }
	.ecb-v10-seenon__card.has-photo:hover .ecb-v10-seenon__img { transform: none; }
}

@media (max-width: 767px) {
	.ecb-v10-seenon__grid { grid-template-columns: 1fr; gap: 14px; }
}
/* --------------------------------------------------------------------------
   Customer Stories

   A scroll-snap track rather than a transform carousel. Three reasons, in the
   order they matter to this shop: a phone gets native momentum scrolling and
   the rubber-band edge it already expects; with JavaScript off or still loading
   every story is reachable by dragging, so the band is never a dead row of one;
   and the browser owns the animation, so it stays smooth on the older Androids
   most of these customers are on.

   `initStories()` adds arrows, dots and the gentle autoplay on top. Everything
   it adds is enhancement — nothing here needs it to be readable.
   -------------------------------------------------------------------------- */
.ecb-v10-storyrail {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: calc(50% - 11px);
	gap: 22px;
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
	scroll-padding: 0;
	/* The rail is dragged, not read through a scrollbar; the dots say where
	   you are. Firefox and WebKit need telling separately. */
	scrollbar-width: none;
	-ms-overflow-style: none;
}

.ecb-v10-storyrail::-webkit-scrollbar { display: none; }

.ecb-v10-story {
	scroll-snap-align: start;
	display: flex;
	min-width: 0;
	border: 1px solid var(--v10-rule);
	background: var(--v10-paper);
	box-shadow: 0 14px 40px rgba(23, 16, 13, .06);
}

/* A story with a photograph reads as a portrait beside the words; one without
   is a quote card. Same component, so the rail never looks half-built while
   the shop is still collecting pictures. */
.ecb-v10-story__media {
	flex: 0 0 42%;
	overflow: hidden;
	background: var(--v10-page);
}

.ecb-v10-story__img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* The picture leans in when a cursor rests on the card. Slow on purpose —
   600ms reads as the photograph settling closer, where the 200ms used on
   buttons would read as a twitch. The frame already clips (overflow hidden
   above), so the crop grows into the card rather than over it.

   Behind `hover: hover` for the reason the whole corner stack is: on a touch
   screen `:hover` latches after a tap and the photo would simply stay zoomed
   until something else was tapped. */
@media (hover: hover) {
	/* 900ms rather than 600, and 1.14 rather than 1.07. The earlier pair was so
	   restrained the picture looked like it had shifted rather than opened up.
	   Slower and further reads as the photograph coming towards you — the long
	   duration is what keeps it calm at that distance. */
	.ecb-v10-story__img { transition: transform 900ms var(--v10-ease); }
	.ecb-v10-story.has-photo:hover .ecb-v10-story__img,
	.ecb-v10-story.has-photo:focus-within .ecb-v10-story__img { transform: scale(1.14); }
}

@media (prefers-reduced-motion: reduce) {
	.ecb-v10-story__img { transition: none; }
	.ecb-v10-story.has-photo:hover .ecb-v10-story__img,
	.ecb-v10-story.has-photo:focus-within .ecb-v10-story__img { transform: none; }
}

.ecb-v10-story__body {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding: 34px 32px;
}

.ecb-v10-story:not(.has-photo) .ecb-v10-story__body { text-align: center; align-items: center; }

/* The opening mark is decoration, so it is aria-hidden in the markup and kept
   well clear of the text rather than sitting behind it.

   Scoped through the rail on purpose. The mark is a <span>, and the meta line
   below is styled as `.ecb-v10-storyrail span` — (0,1,1), which outranks a
   lone class — so an unscoped rule here lost silently and the mark rendered
   as 12px of muted brown instead of the display glyph it is meant to be. */
.ecb-v10-storyrail .ecb-v10-story__mark {
	display: block;
	margin: 0 0 -18px;
	color: var(--v10-accent);
	opacity: .28;
	font: 400 66px/1 var(--v10-display);
}

.ecb-v10-storyrail blockquote {
	margin: 0 0 22px;
	/* Blocksy hangs a 4px accent bar and a 1.5em indent off every blockquote
	   (`blockquote:where(…)` in main.min.css — `:where()` adds nothing, so it is
	   only 0,0,1 and this rule clears it). That bar is the parent theme's design
	   language, not this one: the card already frames the quote and the mark
	   above it already says quotation. Left in, it printed a dark rule down the
	   middle of a centred card. */
	padding: 0;
	border: 0;
	font: 400 21px/1.5 var(--v10-display);
	color: var(--v10-ink);
	/* Ten lines at most. Every card in the row is as tall as the tallest, and
	   one 853-character review beside a photo made all nine 1057px tall — the
	   short quote cards became a few lines floating in an empty box (owner,
	   18 Sep 2026). Only that one review is cut; its "Read it on Facebook"
	   link carries the rest, and the full text stays in the markup. */
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 10;
	line-clamp: 10;
	overflow: hidden;
}

.ecb-v10-storyrail b,
.ecb-v10-storyrail span { display: block; }
.ecb-v10-storyrail b { font-size: 13px; letter-spacing: .12em; text-transform: uppercase; }
.ecb-v10-storyrail span { margin-top: 5px; color: var(--v10-muted); font-size: 12px; }

/* The rail is driven by the shared initAutoRail(), which suspends snapping
   while it animates — without this the snap engine fights the per-frame
   scrollLeft and the row judders. Same reason as the three rails at ~line 564. */
.ecb-v10-storyrail.is-gliding { scroll-snap-type: none; }

@media (max-width: 767px) {
	/* One story at a time, with a sliver of the next showing so the rail
	   reads as something you can push. */
	/* One card is seen at a time here, so each keeps its own height. Stretched
	   to the tallest photo card, a quote-only card was 1340px of white. */
	.ecb-v10-storyrail { grid-auto-columns: 88%; gap: 14px; align-items: start; }
	.ecb-v10-story { flex-direction: column; }
	.ecb-v10-story__media { flex: 0 0 auto; aspect-ratio: 4 / 5; }
	.ecb-v10-story__body { padding: 26px 22px 30px; }
	.ecb-v10-storyrail blockquote { font-size: 19px; }
	.ecb-v10-storyrail .ecb-v10-story__mark { font-size: 54px; margin-bottom: -14px; }
}

@media (prefers-reduced-motion: reduce) {
	.ecb-v10-storyrail { scroll-behavior: auto; }
}

/* --------------------------------------------------------------------------
   Contact
   -------------------------------------------------------------------------- */
.ecb-v10-pagehero { position: relative; display: flex; align-items: end; min-height: 360px; overflow: hidden; color: #fff; }
.ecb-v10-pagehero > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.ecb-v10-pagehero::after { position: absolute; inset: 0; background: linear-gradient(90deg, rgba(23,16,13,.9), rgba(23,16,13,.4), rgba(23,16,13,.12)); content: ""; }
.ecb-v10-pagehero > div { position: relative; z-index: 1; padding-block: 54px; }
.ecb-v10-pagehero h1 { margin: 10px 0; color: #fff; font: 400 clamp(42px, 5vw, 64px)/1 var(--v10-display); }
.ecb-v10-pagehero p:not(.ecb-v10-eyebrow) { max-width: 560px; margin: 0; color: rgba(255,255,255,.78); }
.ecb-v10-contact-actions { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.ecb-v10-contact-actions > * { display: flex; align-items: center; gap: 16px; min-height: 112px; padding: 24px; border: 1px solid var(--v10-rule); background: var(--v10-paper); color: var(--v10-ink); text-align: left; text-decoration: none; cursor: pointer; transition: border-color 180ms ease, transform 220ms var(--v10-ease), box-shadow 220ms ease; }
.ecb-v10-contact-actions > *:hover { border-color: var(--v10-accent); box-shadow: 0 16px 38px rgba(23,16,13,.08); transform: translateY(-2px); }
.ecb-v10-contact-actions > * > span { display: grid; flex: 0 0 46px; width: 46px; height: 46px; place-items: center; border: 1px solid var(--v10-rule); border-radius: 50%; color: var(--v10-accent); }
.ecb-v10-contact-actions > * > div { flex: 1; }
.ecb-v10-contact-actions b,
.ecb-v10-contact-actions small { display: block; }
.ecb-v10-contact-actions b { font: 400 20px/1.2 var(--v10-display); }
.ecb-v10-contact-actions small { margin-top: 5px; color: var(--v10-muted); font-size: 12px; }
.ecb-v10-contact-actions i { color: var(--v10-accent); font-style: normal; }
.ecb-v10-findus { padding: var(--v10-section-y) 0; background: var(--v10-wash); }
.ecb-v10-findus__grid { display: grid; grid-template-columns: minmax(280px,.72fr) minmax(0,1.28fr); gap: 50px; align-items: center; }
.ecb-v10-findus h2,
.ecb-v10-reach h2 { margin: 10px 0 18px; font: 400 42px/1.08 var(--v10-display); }
.ecb-v10-findus p:not(.ecb-v10-eyebrow) { color: var(--v10-ink-soft); line-height: 1.7; }
.ecb-v10-findus__landmark { padding-left: 14px; border-left: 2px solid var(--v10-accent); }
.ecb-v10-findus .ecb-v10-button { margin-top: 16px; }
.ecb-v10-map { min-height: 480px; border: 1px solid var(--v10-rule); background: #E7DED2; }
.ecb-v10-map iframe { display: block; width: 100%; height: 480px; border: 0; }
.ecb-v10-reach { display: grid; grid-template-columns: repeat(2, 1fr); gap: 22px; }
.ecb-v10-reach > div { padding: 38px; border: 1px solid var(--v10-rule); background: var(--v10-paper); }
.ecb-v10-reach a { display: block; width: fit-content; margin-top: 9px; color: var(--v10-ink-soft); text-decoration: none; }
.ecb-v10-reach a:hover { color: var(--v10-accent); }

/* --------------------------------------------------------------------------
   WooCommerce: catalogue and product
   -------------------------------------------------------------------------- */
body.ecb-v10.woocommerce-page .site-main,
body.ecb-v10.search .site-main,
body.ecb-v10.error404 .site-main { padding-block: 32px 60px; }

/* Blocksy pads every inner page's content container with
   --theme-content-vertical-spacing — 60px, 50px below its tablet breakpoint,
   set on :root — above AND below the content. Stacked on .site-main's own
   padding and each page's first section, it opened 130-170px before the first
   thing a visitor came for (empty cart 168px, About 213px to its heading) and
   about 200px above the footer, measured 11 Sep 2026. The homepage already
   drops the top half (style.css §44); every page is tightened here. */
body.ecb-v10 { --theme-content-vertical-spacing: 32px; }

@media (max-width: 689px) {
	body.ecb-v10 { --theme-content-vertical-spacing: 24px; }
}

/* A page title is followed by a first section that brings its own 80px — the
   title's 40px margin already separates them. About, Order Tracking and the
   policy pages all open this way. */
body.ecb-v10 .hero-section + .entry-content > .ecb-section:first-child { padding-top: 24px; }

/* ecb-catalogue.js hides the numbered pager once "Load more" takes over, with
   the hidden attribute. Blocksy styles nav.ct-pagination as display: grid,
   which beats the attribute — so the pager stayed on screen under the button. */
.ct-pagination[hidden],
.woocommerce-pagination[hidden] { display: none; }

/* The empty cart said it twice: WooCommerce's notice ("Your cart is currently
   empty.") and, under it, functions.php's fuller block with category links
   ("Your cart is empty for now."). Only the page's own copy is hidden — the
   header mini-carts are outside .site-main and keep WooCommerce's short line,
   which is the right length in a dropdown. */
body.woocommerce-cart .site-main .wc-empty-cart-message { display: none; }

/* With the notice gone the empty cart still opened 188px below the header: the
   (visually empty) page-title area kept its 40px margin, and the block itself
   added 48px on top of the section's own padding. */
body.woocommerce-cart .site-main .hero-section { margin-bottom: 0; }
body.woocommerce-cart .site-main .ecb-empty { margin-top: 0; }
/* WooCommerce's "Return to shop" sat flush left under a centred block. */
body.woocommerce-cart .site-main .return-to-shop { text-align: center; }
body.ecb-v10.woocommerce-page .ct-container,
body.ecb-v10.search .ct-container,
body.ecb-v10.error404 .ct-container { width: min(100%, var(--v10-shell)); padding-inline: 40px; }
body.ecb-v10 :where(.woocommerce, .ct-woo-card-actions) button:not(.show-password-input),
body.ecb-v10 :where(.woocommerce, .ct-woo-card-actions) .button,
body.ecb-v10 :where(.woocommerce, .ct-woo-card-actions) input[type="submit"] {
	min-height: 48px;
	border-radius: 0;
	background: var(--v10-dark);
	color: #fff;
	font: 500 11px/1 var(--v10-body);
	letter-spacing: .14em;
	text-transform: uppercase;
}
body.ecb-v10 .woocommerce :where(input.input-text, textarea, select) { min-height: 48px; border: 1px solid var(--v10-rule); border-radius: 0; background: var(--v10-paper); font-family: var(--v10-body); }
body.ecb-v10 .woocommerce .woocommerce-breadcrumb { margin-bottom: 28px; color: var(--v10-muted); font-size: 11px; letter-spacing: .08em; text-transform: uppercase; }
body.ecb-v10 .ecb-v9-pagehero { min-height: 320px; background: var(--v10-dark); }
body.ecb-v10 .ecb-v9-pagehero__scrim { background: linear-gradient(90deg, rgba(23,16,13,.92), rgba(36,24,18,.55), rgba(36,24,18,.14)); }
body.ecb-v10 .ecb-v9-pagehero__title { font-family: var(--v10-display); font-size: clamp(42px,5vw,62px); font-weight: 400; }
body.ecb-v10 .ecb-v9-cathead,
body.ecb-v10 .ecb-subnav,
body.ecb-v10 .ecb-filters { border-color: var(--v10-rule); background: var(--v10-paper); }
body.ecb-v10 .ecb-subnav a.is-active,
body.ecb-v10 .ecb-subnav a:hover { border-color: var(--v10-dark); background: var(--v10-dark); color: #fff; }
body.ecb-v10 .woocommerce ul.products { display: grid; grid-template-columns: repeat(4,minmax(0,1fr)); gap: 30px 20px; }
body.ecb-v10 .woocommerce ul.products::before,
body.ecb-v10 .woocommerce ul.products::after { display: none; }
body.ecb-v10 .woocommerce ul.products li.product { width: auto !important; margin: 0 !important; }
body.ecb-v10 .woocommerce ul.products li.product .ct-media-container { aspect-ratio: 4/5; overflow: hidden; background: var(--v10-wash); }
body.ecb-v10 .woocommerce ul.products li.product img { width: 100%; height: 100%; object-fit: cover; transition: transform 800ms var(--v10-ease); }
body.ecb-v10 .woocommerce ul.products li.product:hover img { transform: scale(1.055); }
body.ecb-v10 .woocommerce ul.products li.product .woocommerce-loop-product__title { margin-top: 13px; font: 400 18px/1.3 var(--v10-display); }
body.ecb-v10 .woocommerce ul.products li.product .price { color: var(--v10-ink); font-size: 14px; }
body.ecb-v10 .woocommerce ul.products li.product .price ins { color: var(--v10-red); text-decoration: none; }
body.ecb-v10 .woocommerce ul.products li.product .button { display: none !important; }
/* Load more.

   Centred under the grid, quiet enough that it does not compete with the
   products above it. The count sits over the button because "Showing 24 of 96"
   is the thing that tells someone whether pressing it is worth their time. */
.ecb-loadmore {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 14px;
	margin-top: 44px;
	text-align: center;
}

/* This block is printed hidden and unhidden by the script, and `display: flex`
   above would otherwise beat the browser's own [hidden] rule and show it to
   everyone — including the visitor whose script never loaded, who would get a
   button that does nothing. Same trap as the live-viewer line further down. */
.ecb-loadmore[hidden] {
	display: none;
}

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

.ecb-loadmore__btn {
	min-height: 50px;
	padding: 0 42px;
	border: 1px solid var(--v10-dark);
	background: transparent;
	color: var(--v10-ink);
	font: 500 11.5px/1 var(--v10-body);
	letter-spacing: .16em;
	text-transform: uppercase;
	cursor: pointer;
	transition: background 220ms ease, color 220ms ease, border-color 220ms ease;
}

.ecb-loadmore__btn:hover:not(:disabled),
.ecb-loadmore__btn:focus-visible:not(:disabled) {
	border-color: var(--v10-dark);
	background: var(--v10-dark);
	color: #fff;
}

.ecb-loadmore__btn:disabled { opacity: .55; cursor: progress; }

body.ecb-v10 .woocommerce nav.woocommerce-pagination ul { display: flex; gap: 7px; border: 0; }
body.ecb-v10 .woocommerce nav.woocommerce-pagination ul li { border: 0; }
body.ecb-v10 .woocommerce nav.woocommerce-pagination ul li a,
body.ecb-v10 .woocommerce nav.woocommerce-pagination ul li span { display: grid; width: 42px; height: 42px; place-items: center; border: 1px solid var(--v10-rule); background: var(--v10-paper); color: var(--v10-ink); }
body.ecb-v10 .woocommerce nav.woocommerce-pagination ul li span.current { border-color: var(--v10-dark); background: var(--v10-dark); color: #fff; }

body.ecb-v10.single-product div.product { gap: 44px; }
body.ecb-v10.single-product .woocommerce-product-gallery { min-width: 0; }
body.ecb-v10.single-product .entry-summary > .product_title { margin: 0 0 9px; font: 400 clamp(38px,4vw,54px)/1.03 var(--v10-display); letter-spacing: -.02em; }
body.ecb-v10.single-product .entry-summary > .price { color: var(--v10-ink); font-size: 20px; }
body.ecb-v10.single-product .entry-summary > .price ins { color: var(--v10-red); text-decoration: none; }
body.ecb-v10.single-product table.variations th,
body.ecb-v10.single-product table.variations td { display: block; width: 100%; padding: 0; }
body.ecb-v10.single-product table.variations th { margin: 13px 0 7px; color: var(--v10-ink); font-size: 11px; letter-spacing: .14em; text-transform: uppercase; }
body.ecb-v10.single-product .variable-items-wrapper { gap: 9px; }
body.ecb-v10.single-product .variable-item { min-width: 38px; min-height: 38px; border: 1px solid var(--v10-rule) !important; border-radius: 0 !important; box-shadow: none !important; }
body.ecb-v10.single-product .variable-item.selected { border-color: var(--v10-accent) !important; box-shadow: 0 0 0 2px var(--v10-page), 0 0 0 3px var(--v10-accent) !important; }
body.ecb-v10.single-product .variable-item.disabled { opacity: .35; cursor: not-allowed; }
body.ecb-v10.single-product .single_add_to_cart_button { flex: 1; min-height: 52px; }
body.ecb-v10.single-product .quantity input { min-height: 52px; border-color: var(--v10-rule); }
body.ecb-v10.single-product .ecb-assure { border-block: 1px solid var(--v10-rule); background: var(--v10-wash); }
body.ecb-v10.single-product .ecb-assure__item { border-color: var(--v10-rule); }
body.ecb-v10.single-product .ecb-acc { border-color: var(--v10-rule); }
body.ecb-v10.single-product .ecb-acc__item { border-color: var(--v10-rule); }
body.ecb-v10.single-product .ecb-acc__head { font-family: var(--v10-body); letter-spacing: .08em; }
body.ecb-v10.single-product .ecb-share { border-color: var(--v10-rule); }
body.ecb-v10.single-product .related > h2 { font: 400 36px/1.1 var(--v10-display); text-align: center; }

/* The summary column, tightened.

   Every block down this column was separated by 24px, and the ones that also
   carry a top border added 24px of padding on the other side of it — so a
   ruled divider cost 48px, twice. Stacked five deep that is most of a screen
   of nothing, and it pushed the price, the sizes and the button apart from
   each other when they are one decision.

   16px between blocks, 14px around a rule. The dividers still read as
   dividers; the column now reads as one panel instead of five loose cards. */
body.ecb-v10.single-product .entry-summary > .woocommerce-product-details__short-description { margin-top: 12px; }
body.ecb-v10.single-product .ecb-delivery-estimate,
body.ecb-v10.single-product .ecb-eta { margin-top: 14px; padding: 12px 14px; }
body.ecb-v10.single-product .ecb-sku { margin-top: 8px; }
body.ecb-v10.single-product .ecb-assure { margin-top: 18px; padding-top: 16px; }
body.ecb-v10.single-product .ecb-acc { margin-top: 18px; }
body.ecb-v10.single-product .ecb-direct { margin-top: 12px; }

body.ecb-v10.single-product .ecb-stickybar { border-top: 1px solid var(--v10-rule); background: rgba(255,253,250,.97); box-shadow: 0 -10px 30px rgba(23,16,13,.09); backdrop-filter: blur(12px); }
body.ecb-v10.single-product .ecb-stickybar__btn { border-color: var(--v10-dark); border-radius: 0; background: var(--v10-dark); color: #fff; }
body.ecb-v10.single-product .ecb-stickybar.is-visible ~ .ecb-v10-backtop { bottom: 84px; }

/* --------------------------------------------------------------------------
   Cart, checkout, account, lookup and order surfaces
   -------------------------------------------------------------------------- */
.ecb-v10-commerce-head { margin: 0 0 36px; }
.ecb-v10-commerce-head h1 { margin: 10px 0 0; font: 400 clamp(38px,4vw,52px)/1 var(--v10-display); }
.ecb-v10-commerce-head > p:not(.ecb-v10-eyebrow) { max-width: 620px; margin: 13px 0 0; color: var(--v10-muted); }
body.ecb-v10.woocommerce-cart .entry-header,
body.ecb-v10.woocommerce-checkout .entry-header { display: none; }
body.ecb-v10 .woocommerce-cart-form,
body.ecb-v10 .cart_totals,
body.ecb-v10 .woocommerce-checkout-review-order,
body.ecb-v10 .woocommerce-checkout .col2-set,
body.ecb-v10 .woocommerce-MyAccount-content,
body.ecb-v10 .ecb-lookup { border-color: var(--v10-rule); border-radius: 0; }
body.ecb-v10 .woocommerce-cart-form,
body.ecb-v10 .cart_totals,
body.ecb-v10 .woocommerce-checkout-review-order { background: var(--v10-paper); }
body.ecb-v10 .shop_table th { color: var(--v10-muted); font-size: 10px; letter-spacing: .14em; text-transform: uppercase; }
body.ecb-v10 .shop_table td,
body.ecb-v10 .shop_table th { border-color: var(--v10-rule); }
body.ecb-v10 .cart_totals h2,
body.ecb-v10 #order_review_heading,
body.ecb-v10 .woocommerce-billing-fields h3 { font: 400 30px/1.1 var(--v10-display); }
body.ecb-v10 .woocommerce-checkout #payment { border-radius: 0; background: var(--v10-wash); }
body.ecb-v10 .woocommerce-checkout #payment ul.payment_methods { border-color: var(--v10-rule); }
body.ecb-v10 .woocommerce-error,
body.ecb-v10 .woocommerce-info,
body.ecb-v10 .woocommerce-message { border: 1px solid var(--v10-rule); border-top: 3px solid var(--v10-accent); border-radius: 0; background: var(--v10-paper); }
body.ecb-v10.woocommerce-account .woocommerce { max-width: 1180px; }
body.ecb-v10.logged-in.woocommerce-account .woocommerce-MyAccount-navigation { padding: 20px; border: 1px solid var(--v10-rule); background: var(--v10-dark); }
body.ecb-v10.logged-in.woocommerce-account .woocommerce-MyAccount-navigation a { color: #D8C9BC; font-size: 12px; letter-spacing: .08em; }
body.ecb-v10.logged-in.woocommerce-account .woocommerce-MyAccount-navigation .is-active a,
body.ecb-v10.logged-in.woocommerce-account .woocommerce-MyAccount-navigation a:hover { color: var(--v10-accent-hi); }
body.ecb-v10 .ecb-card,
body.ecb-v10 .ecb-v9-account-card,
body.ecb-v10 .ecb-order-summary { border-color: var(--v10-rule); border-radius: 0; background: var(--v10-paper); box-shadow: none; }
body.ecb-v10 .ecb-progress__dot,
body.ecb-v10 .ecb-progress__bar { border-color: var(--v10-accent); }

/* --------------------------------------------------------------------------
   Authentication
   -------------------------------------------------------------------------- */
body.ecb-v10-auth-page .site-main {
	width: 100%;
	max-width: none;
	min-height: 820px;
	padding: 70px 20px;
	background: linear-gradient(rgba(23,16,13,.48), rgba(23,16,13,.58)), url("../images/v10/auth-bg.jpg") center/cover fixed;
}
body.ecb-v10-auth-page .site-main > .ct-container { width: min(100%, 560px); padding: 0; }
body.ecb-v10-auth-page .entry-header,
body.ecb-v10-auth-page .hero-section { display: none; }
body.ecb-v10-auth-page #customer_login,
body.ecb-v10-auth-page .woocommerce-ResetPassword {
	width: 100%;
	margin: 0;
	padding: 0;
	border: 1px solid rgba(255,255,255,.18);
	background: rgba(23,16,13,.9);
	color: #EFE4D4;
	box-shadow: 0 30px 80px rgba(0,0,0,.32);
	backdrop-filter: blur(12px);
}
body.ecb-v10-auth-page #customer_login > .u-column1,
body.ecb-v10-auth-page #customer_login > .u-column2 { float: none; width: 100%; padding: 34px 42px 42px; }
body.ecb-v10-login-view #customer_login > .u-column2,
body.ecb-v10-register-view #customer_login > .u-column1 { display: none; }
body.ecb-v10-auth-page .ecb-account-intro,
body.ecb-v10-auth-page .ecb-account-why { display: none; }
body.ecb-v10-auth-page #customer_login > .u-column1 > h2,
body.ecb-v10-auth-page #customer_login > .u-column2 > h2 { margin: 0 0 22px; color: #fff; font: 400 32px/1.1 var(--v10-display); }
.ecb-v10-auth-intro,
.ecb-v10-lost-intro { padding: 42px 42px 24px; background: rgba(23,16,13,.9); color: #EFE4D4; text-align: center; }
.ecb-v10-auth-intro .ecb-v10-brand,
.ecb-v10-lost-intro .ecb-v10-brand { justify-content: center; margin-bottom: 26px; }
.ecb-v10-auth-intro h1,
.ecb-v10-lost-intro h1 { margin: 10px 0; color: #fff; font: 400 36px/1.04 var(--v10-display); }
.ecb-v10-auth-intro > p:not(.ecb-v10-eyebrow),
.ecb-v10-lost-intro > p:not(.ecb-v10-eyebrow) { max-width: 410px; margin: 0 auto; color: #B6A697; font-size: 13px; line-height: 1.6; }
.ecb-v10-auth-intro nav { display: grid; grid-template-columns: 1fr 1fr; margin-top: 27px; border-bottom: 1px solid rgba(255,255,255,.17); }
.ecb-v10-auth-tab { padding: 13px; color: #B6A697 !important; font-size: 10.5px; letter-spacing: .15em; text-decoration: none; text-transform: uppercase; }
.ecb-v10-login-view .ecb-v10-auth-tab:first-child,
.ecb-v10-register-view .ecb-v10-auth-tab:last-child { border-bottom: 2px solid var(--v10-accent-hi); color: #fff !important; }
body.ecb-v10-auth-page .woocommerce form { margin: 0; padding: 0; border: 0; background: transparent; }
body.ecb-v10-auth-page .woocommerce form label { color: #D8C9BC; font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase; }
body.ecb-v10-auth-page .woocommerce form :where(input.input-text, select) { min-height: 50px; border-color: rgba(255,255,255,.22); background: rgba(255,255,255,.075); color: #fff; }
body.ecb-v10-auth-page .woocommerce form input::placeholder { color: #948478; }
/* The one button on these forms — Sign in, Register, Save password.

   It was dark ink on the light accent, which measures 2.30:1 in the light
   theme: a navy slab with the word buried in it, on the screen where a
   customer is already frustrated because they have forgotten a password.

   Green, and not only for contrast. Every other blue thing on this page is
   a link or a field; the one control that commits the action should not
   look like them. White on #1E7A3C is 5.38:1, and the button reads 3.50:1
   against the panel behind it, so its edge is visible too. */
body.ecb-v10-auth-page .woocommerce form .button {
	width: 100%;
	margin-top: 10px;
	border: 1px solid #1E7A3C;
	background: #1E7A3C;
	color: #FFFFFF;
	font-weight: 600;
	letter-spacing: .1em;
	transition: background 200ms ease, border-color 200ms ease;
}
body.ecb-v10-auth-page .woocommerce form .button:hover,
body.ecb-v10-auth-page .woocommerce form .button:focus-visible {
	border-color: #166030;
	background: #166030;
	color: #FFFFFF;
}
body.ecb-v10-auth-page .woocommerce-LostPassword a,
body.ecb-v10-auth-page .ecb-v10-auth-switch a { color: var(--v10-accent-hi); }
.ecb-v10-auth-mode { margin: 0 0 18px; }
.ecb-v10-auth-mode span { display: inline-flex; min-height: 32px; align-items: center; padding: 0 12px; border: 1px solid rgba(255,255,255,.2); color: var(--v10-accent-hi); font-size: 10px; letter-spacing: .12em; text-transform: uppercase; }
.ecb-v10-phone { display: flex; align-items: stretch; }
.ecb-v10-phone b { display: flex; flex: 0 0 66px; align-items: center; justify-content: center; border: 1px solid rgba(255,255,255,.22); border-right: 0; color: #fff; font-size: 13px; }
.ecb-v10-phone input { min-width: 0; flex: 1; }
.ecb-v10-auth-switch { margin: 20px 0 0; color: #B6A697; font-size: 12px; text-align: center; }
body.ecb-v10-auth-page .woocommerce-ResetPassword { padding: 34px 42px 42px; }

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */
.ecb-v10-footer { background: var(--v10-dark); color: #B6A697; }
.ecb-v10-footer__grid { display: grid; grid-template-columns: 1.45fr .82fr .82fr 1.15fr; gap: 44px; padding-block: 52px; }
.ecb-v10-footer .ecb-v10-brand__words > span { color: #fff; }
.ecb-v10-footer__brand > p { max-width: 360px; margin: 22px 0 0; font-size: 13px; line-height: 1.75; }
.ecb-v10-footer h2 { margin: 0 0 18px; color: var(--v10-accent-hi); font: 500 11.5px/1.3 var(--v10-body); letter-spacing: .2em; text-transform: uppercase; }
.ecb-v10-footer ul { margin: 0; padding: 0; list-style: none; }
.ecb-v10-footer li { margin: 0; }
.ecb-v10-footer li a,
.ecb-v10-footer__contact a { display: block; width: fit-content; padding: 5px 0; color: #B6A697; font-size: 13px; text-decoration: none; transition: color 180ms ease, transform 220ms var(--v10-ease); }
.ecb-v10-footer li a:hover,
.ecb-v10-footer__contact a:hover { color: var(--v10-accent-hi); transform: translateX(4px); }
.ecb-v10-social { display: flex; gap: 9px; margin-top: 22px; }
.ecb-v10-social a { display: grid; width: 42px; height: 42px; place-items: center; border: 1px solid #3C2C23; border-radius: 50%; color: #B6A697; transition: color 180ms ease, border-color 180ms ease, transform 220ms ease; }
.ecb-v10-social a:hover { border-color: var(--v10-accent-hi); color: var(--v10-accent-hi); transform: scale(1.07); }
.ecb-v10-payments { border-top: 1px solid rgba(255,255,255,.1); border-bottom: 1px solid rgba(255,255,255,.1); }
.ecb-v10-payments > div { display: flex; flex-wrap: wrap; align-items: center; gap: 9px; padding-block: 18px; }
.ecb-v10-payments span { margin-right: 8px; color: var(--v10-accent-hi); font-size: 10px; letter-spacing: .18em; text-transform: uppercase; }
.ecb-v10-payments b { padding: 7px 10px; border: 1px solid #3C2C23; color: #CBBEB4; font-size: 10px; font-weight: 500; letter-spacing: .05em; }
.ecb-v10-footer__bottom > div { display: flex; align-items: center; justify-content: space-between; gap: 20px; padding-block: 20px; color: #806F63; font-size: 11px; }
.ecb-v10-backtop { position: fixed; z-index: 8500; right: 22px; bottom: 22px; width: 46px; height: 46px; border: 1px solid rgba(255,255,255,.2); background: var(--v10-dark); color: #fff; font-size: 20px; opacity: 0; visibility: hidden; transform: translateY(12px); transition: opacity 180ms ease, transform 220ms var(--v10-ease), visibility 0s linear 220ms; cursor: pointer; }
.ecb-v10-backtop.is-visible { opacity: 1; visibility: visible; transform: none; transition-delay: 0s; }

/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */
@media (max-width: 1199px) {
	.ecb-v10-topnav { gap: 18px; }
	.ecb-v10-catnav > .ecb-v10-shell > ul { gap: 24px; }
	.ecb-v10-footer__grid { grid-template-columns: 1.25fr repeat(3,1fr); gap: 30px; }
}

@media (max-width: 999px) {
	.admin-bar .ecb-v10-header { top: 32px; }
	.ecb-v10-shell { padding-inline: 24px; }
	.ecb-v10-headmain { max-height: 62px; }
	.ecb-v10-headmain__inner { min-height: 62px; padding-inline: 6px; }
	.ecb-v10-mobile-only { display: inline-flex; }
	.ecb-v10-logo { flex: 1; justify-content: center; }
	.ecb-v10-logo .ecb-v10-brand > img { height: 32px; }
	.ecb-v10-logo .ecb-v10-brand__words > span { font-size: 13px; }
	.ecb-v10-logo .ecb-v10-brand__words small { margin-top: 4px; font-size: 6px; }
	.ecb-v10-topnav,
	.ecb-v10-signin { display: none; }
	.ecb-v10-actions { gap: 0; }
	.ecb-v10-iconbtn { width: 44px; height: 44px; }
	.ecb-v10-catnav > .ecb-v10-shell { padding: 0; overflow-x: auto; scrollbar-width: none; }
	.ecb-v10-catnav > .ecb-v10-shell::-webkit-scrollbar { display: none; }
	.ecb-v10-catnav > .ecb-v10-shell > ul { width: max-content; min-height: 42px; justify-content: flex-start; gap: 22px; padding-inline: 16px; }
	.ecb-v10-catnav > .ecb-v10-shell > ul > li > a { font-size: 10.5px; }
	.ecb-v10-dropdown { display: none; }
	.ecb-v10-header.is-condensed .ecb-v10-headmain { max-height: 62px; opacity: 1; transform: none; }
	.ecb-v10-header.is-condensed .ecb-v10-announcement { max-height: 0; min-height: 0; padding-block: 0; opacity: 0; }
	.ecb-v10-hero { height: 610px; }
	.ecb-v10-hero__copy { width: min(610px, 72vw); }
	.ecb-v10-trust { grid-template-columns: repeat(2, 1fr); }
	.ecb-v10-trust a:nth-child(2) { border-right: 0; }
	.ecb-v10-trust a:nth-child(-n+2) { border-bottom: 1px solid var(--v10-rule); }
	.ecb-v10-products,
	body.ecb-v10 .woocommerce ul.products { grid-template-columns: repeat(3,minmax(0,1fr)); }
	.ecb-v10-products.is-rail { grid-template-columns: none; grid-auto-columns: calc((100% - 44px) / 3); }
	.ecb-v10-arrival-grid { grid-template-columns: 1fr 1fr; }
	.ecb-v10-arrival-grid .is-feature { grid-row: auto; }
	.ecb-v10-contact-actions { grid-template-columns: 1fr 1fr; }
	.ecb-v10-contact-actions > *:last-child { grid-column: 1 / -1; }
	.ecb-v10-findus__grid { grid-template-columns: 1fr; }
	.ecb-v10-footer__grid { grid-template-columns: 1.5fr 1fr 1fr; }
	.ecb-v10-footer__contact { grid-column: 1 / -1; }
}

@media (max-width: 719px) {
	.admin-bar .ecb-v10-header { top: 46px; }
	.ecb-v10-shell { padding-inline: 18px; }
	.ecb-v10-announcement { min-height: 44px; gap: 7px; font-size: 9.5px; letter-spacing: .08em; }
	.ecb-v10-announcement i { display: none; }
	.ecb-v10-hero { height: 620px; }
	.ecb-v10-hero__scrim { background: linear-gradient(to top, rgba(23,16,13,.9), rgba(23,16,13,.28) 62%, rgba(23,16,13,.08)); }
	.ecb-v10-hero__inner { align-items: end; padding-bottom: 80px; }
	.ecb-v10-hero__copy { width: 100%; }
	.ecb-v10-hero__copy h1,
	.ecb-v10-hero__copy h2 { font-size: clamp(43px, 12vw, 58px); }
	.ecb-v10-hero__copy > p:not(.ecb-v10-eyebrow) { max-width: 90%; font-size: 13.5px; }
	.ecb-v10-hero__arrow { display: none; }
	.ecb-v10-hero__dots { left: 16px; bottom: 16px; transform: none; }
	/* Set on the root, not on .ecb-v10-section, so every band that reads the
	   token — Find Us included — tightens together on a phone. */
	:root { --v10-section-y: 46px; --v10-head-gap: 24px; }
	.ecb-v10-sectionhead { margin-bottom: 32px; }
	.ecb-v10-sectionhead.is-row { align-items: center; }
	.ecb-v10-sectionhead h2 { font-size: 34px; }
	.ecb-v10-occasion-grid { grid-template-columns: 1fr 1fr; grid-template-rows: 260px 360px 260px; gap: 12px; }
	.ecb-v10-occasion:nth-child(1) { grid-area: 1 / 1; }
	.ecb-v10-occasion:nth-child(2) { grid-area: 2 / 1 / 3 / 3; }
	.ecb-v10-occasion:nth-child(3) { grid-area: 1 / 2; }
	.ecb-v10-occasion:nth-child(4) { grid-area: 3 / 1; }
	.ecb-v10-occasion:nth-child(5) { grid-area: 3 / 2; }
	.ecb-v10-products,
	body.ecb-v10 .woocommerce ul.products { grid-template-columns: repeat(2,minmax(0,1fr)); gap: 30px 14px; }
	.ecb-v10-products.is-rail { grid-template-columns: none; grid-auto-columns: 62%; gap: 14px; }
	.ecb-v10-picks__head-actions .ecb-v10-carousel-buttons { display: none; }
	.ecb-v10-product h3,
	body.ecb-v10 .woocommerce ul.products li.product .woocommerce-loop-product__title { font-size: 16px; }
	.ecb-v10-lookbook .ecb-v10-shell > div:last-child { grid-template-columns: 1fr 1fr; grid-template-rows: 390px 250px; gap: 12px; }
	.ecb-v10-lookbook figure:first-child { grid-column: 1 / -1; grid-row: auto; }
	.ecb-v10-wedding { min-height: 520px; }
	.ecb-v10-reach { grid-template-columns: 1fr; }
	.ecb-v10-pagehero { min-height: 330px; }
	.ecb-v10-contact-actions { grid-template-columns: 1fr; }
	.ecb-v10-contact-actions > *:last-child { grid-column: auto; }
	.ecb-v10-map,
	.ecb-v10-map iframe { min-height: 380px; height: 380px; }
	body.ecb-v10.woocommerce-page .ct-container,
	body.ecb-v10.search .ct-container,
	body.ecb-v10.error404 .ct-container { padding-inline: 18px; }
	body.ecb-v10.single-product div.product { gap: 34px; }
	body.ecb-v10.logged-in.woocommerce-account .woocommerce-MyAccount-navigation,
	body.ecb-v10.logged-in.woocommerce-account .woocommerce-MyAccount-content { width: 100%; }
	.ecb-v10-footer__grid { grid-template-columns: 1fr 1fr; }
	.ecb-v10-footer__brand,
	.ecb-v10-footer__contact { grid-column: 1 / -1; }
}

@media (max-width: 519px) {
	.ecb-v10-shell { padding-inline: 16px; }
	.ecb-v10-announcement { flex-direction: column; gap: 1px; padding-block: 7px; letter-spacing: .05em; }
	.ecb-v10-logo .ecb-v10-brand { gap: 8px; }
	.ecb-v10-logo .ecb-v10-brand__words > span { font-size: 11px; letter-spacing: .09em; }
	.ecb-v10-logo .ecb-v10-brand__words small { letter-spacing: .28em; }
	.ecb-v10-actions .ecb-v10-iconbtn { width: 40px; }
	.ecb-v10-hero__copy > div { flex-direction: column; align-items: stretch; max-width: 280px; }
	.ecb-v10-hero__copy .ecb-v10-button { width: 100%; }
	.ecb-v10-trust a { min-height: 92px; padding: 20px 12px; }
	.ecb-v10-trust b { font-size: 9px; letter-spacing: .12em; }
	.ecb-v10-trust span { font-size: 10.5px; }
	.ecb-v10-occasion-grid { grid-template-rows: 210px 330px 210px; }
	.ecb-v10-occasion span { left: 15px; bottom: 15px; font-size: 12px; letter-spacing: .15em; }
	.ecb-v10-sectionhead.is-row { align-items: flex-end; }
	.ecb-v10-sectionhead.is-row > a { display: none; }
	.ecb-v10-carousel-buttons button { width: 42px; height: 42px; }
	.ecb-v10-categoryrail { grid-auto-columns: 72%; }
	.ecb-v10-lookrail { grid-auto-columns: 82%; }
	.ecb-v10-look { height: 500px; }
	.ecb-v10-products,
	body.ecb-v10 .woocommerce ul.products { grid-template-columns: repeat(2,minmax(0,1fr)); gap: 26px 10px; }
	.ecb-v10-arrival-grid { grid-template-columns: 1fr 1fr; gap: 24px 10px; }
	.ecb-v10-product__body { padding-top: 11px; }
	.ecb-v10-product__eyebrow { font-size: 8.5px; }
	.ecb-v10-product h3 { font-size: 15px; }
	.ecb-v10-product__price { font-size: 12px; }
	.ecb-v10-product__view { display: none; }
	.ecb-v10-lookbook .ecb-v10-shell > div:last-child { grid-template-rows: 330px 200px; }
	.ecb-v10-instagram { padding-block: 46px; }
	.ecb-v10-instagram h2 { font-size: 38px; }
	.ecb-v10-wedding h2 { font-size: 46px; }
	.ecb-v10-search__dialog { padding: 44px 22px 28px; }
	.ecb-v10-search__dialog h2 { font-size: 34px; }
	.ecb-v10-search__dialog form { grid-template-columns: 1fr; gap: 10px; }
	.ecb-v10-search__dialog form button { min-height: 50px; }
	body.ecb-v10-auth-page .site-main { min-height: 720px; padding: 44px 14px; background-attachment: scroll; }
	.ecb-v10-auth-intro,
	.ecb-v10-lost-intro { padding: 32px 24px 20px; }
	body.ecb-v10-auth-page #customer_login > .u-column1,
	body.ecb-v10-auth-page #customer_login > .u-column2,
	body.ecb-v10-auth-page .woocommerce-ResetPassword { padding: 26px 24px 32px; }
	.ecb-v10-footer__grid { grid-template-columns: 1fr; padding-block: 40px; }
	.ecb-v10-footer__brand,
	.ecb-v10-footer__contact { grid-column: auto; }
	.ecb-v10-footer__bottom > div { flex-direction: column; align-items: flex-start; }
	.ecb-v10-backtop { right: 14px; bottom: 14px; }
}

@media (max-width: 359px) {
	.ecb-v10-brand__words { display: none; }
	.ecb-v10-products,
	body.ecb-v10 .woocommerce ul.products,
	.ecb-v10-arrival-grid { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
	body.ecb-v10 *,
	body.ecb-v10 *::before,
	body.ecb-v10 *::after { scroll-behavior: auto !important; animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
	.ecb-v10-hero__slide > img,
	.ecb-v10-look > img { transform: none !important; }
	.ecb-v10-look__play::after { animation: none !important; opacity: 0 !important; }
}

@media print {
	.ecb-v10-header,
	.ecb-v10-footer,
	.ecb-v10-backtop,
	.ecb-v10-drawer,
	.ecb-v10-search { display: none !important; }
}

/* --------------------------------------------------------------------------
   Saving badge, .ecb-off / .ecb-price-off
   ecb_price_html() appends <span class="ecb-off ecb-price-off">Save N%</span>
   to every sale price. Two rules in style.css then collided on it: the block
   at ~3164 turns .ecb-off into a filled badge (background --ecb-sale, white
   text) while the later .ecb-price-off at ~9350 sets colour to --ecb-v9-sale,
   the same red. Foreground equalled background, so the badge rendered as a
   solid unreadable rectangle beside the price on the homepage cards and in
   the single-product summary.

   Cards already carry the corner flag (.ecb-v10-product__sale), which is what
   the approved design shows, so the duplicate inline badge is dropped there —
   the archive loop hides it the same way. Where the badge does show, it takes
   the flag's own treatment: white on --v10-red.
   -------------------------------------------------------------------------- */
.ecb-v10-product__price .ecb-off { display: none; }

.ecb-off.ecb-price-off {
	background-color: var(--v10-red);
	color: #fff;
}

/* --------------------------------------------------------------------------
   Form submits that Blocksy was repainting in its palette blue
   Blocksy's static/main.min.css is enqueued after the child stylesheet, and
   its `.button, .ct-button, [type="submit"], ...` rule carries the same
   specificity as a single ECB class. Source order therefore handed the
   parent theme the win, and two live submits rendered in #2872FA: the shop
   catalogue search and the order-lookup form ecb-commerce-core prints on
   /order-tracking/. This sheet loads after main.min.css, so the class-level
   selectors below are enough — no !important needed.

   Treatment is the approved design's primary submit: espresso ground, cream
   label, uppercase and letterspaced, deepening on hover.
   -------------------------------------------------------------------------- */
.ecb-shopsearch__submit,
.ecb-lookup__form button.button,
.ecb-lookup__form [type="submit"] {
	border: 0;
	background-color: var(--v10-dark);
	color: #FBF8F4;
	font-family: var(--v10-body);
	letter-spacing: .16em;
	text-transform: uppercase;
	transition: background-color 220ms ease;
}

.ecb-shopsearch__submit:hover,
.ecb-shopsearch__submit:focus-visible,
.ecb-lookup__form button.button:hover,
.ecb-lookup__form button.button:focus-visible,
.ecb-lookup__form [type="submit"]:hover,
.ecb-lookup__form [type="submit"]:focus-visible {
	background-color: #2E201A;
	color: #FBF8F4;
}

.ecb-lookup__form button.button,
.ecb-lookup__form [type="submit"] {
	min-height: 52px;
	padding: 0 30px;
	font-size: 12.5px;
}

/* --------------------------------------------------------------------------
   Trending Looks play control
   The marker is the character U+25B6, which Windows resolves through Segoe UI
   Emoji and paints as a blue emoji tile — `color: #fff` does not apply to a
   colour font, so the control read as a stray blue square over the poster on
   every Windows browser. The glyph is decorative (aria-hidden), so it is
   hidden and the triangle drawn with borders, which no font can override.
   -------------------------------------------------------------------------- */
.ecb-v10-look__play {
	font-size: 0;
	line-height: 0;

	/* Glass rather than a grey wash: the poster stays readable through it, so
	   the control sits ON the photograph instead of punching a hole in it. */
	-webkit-backdrop-filter: blur(7px) saturate(130%);
	backdrop-filter: blur(7px) saturate(130%);
	background: rgba(23, 16, 13, .26);
	border-color: rgba(255, 255, 255, .58);
	box-shadow: 0 12px 34px rgba(0, 0, 0, .34);

	/* The centring translate has to be repeated in every transform below, or
	   the button jumps to the corner the moment one of them applies. */
	transition:
		opacity 260ms var(--v10-ease),
		transform 320ms var(--v10-ease),
		background-color 260ms var(--v10-ease),
		border-color 260ms var(--v10-ease);
}

/* The ring that says "playable".

   It rests at opacity 0 and the animation brings it in. That order matters: a
   browser with animations switched off then shows ONE ring, not a second static
   one stranded around the button. */
.ecb-v10-look__play::after {
	content: "";
	position: absolute;
	inset: -1px;
	border: 1px solid currentColor;
	border-radius: 50%;
	opacity: 0;
	animation: ecb-look-pulse 2800ms var(--v10-ease) infinite;
	pointer-events: none;
}

@keyframes ecb-look-pulse {
	0%   { opacity: .5; transform: scale(1); }
	65%  { opacity: 0;  transform: scale(1.5); }
	100% { opacity: 0;  transform: scale(1.5); }
}

.ecb-v10-look__play::before {
	content: "";
	display: block;
	width: 0;
	height: 0;
	border-top: 8px solid transparent;
	border-bottom: 8px solid transparent;
	border-left: 13px solid currentColor;
}

/* --------------------------------------------------------------------------
   Typeface tokens
   style.css declares the V10 families at :root (line ~31) and then the older
   "frozen type" block at ~7213 redeclares --ecb-font-body and
   --ecb-font-heading as the V9 system stacks — Avenir Next and Iowan Old
   Style. That block is later in the file, so it won.

   Everything drawn by the V10 layer reads --v10-body / --v10-display and was
   unaffected, but every surface still styled from the older tokens fell back
   to system faces: the single-product title, its price, the breadcrumbs and
   ~94 rules besides. On Windows that resolved to Arial and Palatino, so the
   product page carried neither of the approved typefaces even though both are
   self-hosted by this theme and were already loaded on the page.

   Restated here, after both declarations. Noto Sans Bengali stays in the
   stack for the reason style.css gives: it only matches Bengali codepoints,
   so it cannot change how Latin text renders, and the Bangla policy copy
   needs it.
   -------------------------------------------------------------------------- */
:root {
	--ecb-font-body: "Rubik", "Noto Sans Bengali", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
	--ecb-font-heading: "Cormorant Garamond", "Tiro Bangla", "Noto Sans Bengali", Georgia, "Times New Roman", serif;
	--ecb-font-bangla: "Noto Sans Bengali", "Rubik", "Segoe UI", Helvetica, Arial, sans-serif;
}

/* --------------------------------------------------------------------------
   Related products, on a phone

   Blocksy stamps `ct-hidden-sm ct-hidden-md` on the related-products block,
   and its own CSS turns those into `display: none !important` below 1000px.
   So the one row that says "here is something else you might like" was shown
   only to desktop — while most of this shop's visitors are on a phone, and
   for them the product page simply ended.

   Blocksy is the parent theme and is never edited, so this is an override,
   and `!important` is required to answer an `!important`. The selector is
   scoped to the V10 single-product page so no other use of those utility
   classes anywhere on the site is affected.
   -------------------------------------------------------------------------- */
@media (max-width: 999.98px) {
	body.ecb-v10.single-product .related.products.ct-hidden-sm,
	body.ecb-v10.single-product .related.products.ct-hidden-md {
		display: block !important;
	}
}

/* Two across on a phone, matching the shop grid rather than one huge card. */
@media (max-width: 767px) {
	body.ecb-v10.single-product .related.products ul.products {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 26px 10px;
	}
}

/* --------------------------------------------------------------------------
   The Description tab

   It inherited the full 1343px of the page with no measure at all, so a line
   of Bangla sat alone in an acre of white and the whole panel read as an
   afterthought rather than the product's own detail.

   The paragraph gap is the other half. This shop writes the description as a
   bullet per line, and WordPress makes each line its own <p> — at the stock
   24px that is not a list, it is eight separate paragraphs. 12px still reads
   as prose when somebody writes prose, and as a list when they write a list.
   -------------------------------------------------------------------------- */
/* The tabs wrapper is printed outside the page shell, so it had no gutter at
   all: the DESCRIPTION tab and every line under it sat hard against the left
   edge of the browser while the summary above and Related products below were
   both inset. Given the shell's own measurements so it lines up with them
   rather than merely stops touching the edge. */
body.ecb-v10.single-product .woocommerce-tabs {
	max-width: var(--v10-shell);
	margin-inline: auto;
	padding-inline: 40px;
}

/* The shell's own steps, restated HERE rather than added to the shell's media
   blocks near line 970. Those blocks sit ~330 lines above this rule and carry
   the same specificity, so the 40px above simply won inside them and a phone
   kept a desktop gutter. Source order is the whole reason these live here. */
@media (max-width: 999px) { body.ecb-v10.single-product .woocommerce-tabs { padding-inline: 24px; } }
@media (max-width: 719px) { body.ecb-v10.single-product .woocommerce-tabs { padding-inline: 18px; } }
@media (max-width: 519px) { body.ecb-v10.single-product .woocommerce-tabs { padding-inline: 16px; } }

body.ecb-v10.single-product .woocommerce-Tabs-panel--description {
	max-width: 68ch;
	padding-top: 6px;
}

body.ecb-v10.single-product .woocommerce-Tabs-panel--description p {
	margin: 0 0 12px;
	line-height: 1.75;   /* Bangla conjuncts need the room Latin does not */
}

body.ecb-v10.single-product .woocommerce-Tabs-panel--description p:last-child { margin-bottom: 0; }

/* A real list, when one is written as one. */
body.ecb-v10.single-product .woocommerce-Tabs-panel--description :is(ul, ol) { margin: 0 0 12px; padding-left: 1.25em; }
body.ecb-v10.single-product .woocommerce-Tabs-panel--description li { margin-bottom: 5px; line-height: 1.75; }

/* --------------------------------------------------------------------------
   Product page headline and price
   The approved page sets the product name in the display face around 38px and
   the price beneath it at 28px, the same pairing the cards use. Section 41 of
   style.css ("Phase 6C — product information hierarchy") predates the V10
   freeze and pins both to the body face at 24px/20px with !important, so the
   single product page was the one place the display face never appeared.
   Matching !important is the only way past that; the selectors are otherwise
   the narrowest that reach the elements.
   -------------------------------------------------------------------------- */
body.ecb-v10.single-product .entry-summary .entry-title,
body.ecb-v10.single-product .entry-summary h1.product_title {
	font-family: var(--v10-display) !important;
	font-size: clamp(30px, 2.6vw, 38px) !important;
	font-weight: 400 !important;
	line-height: 1.12;
	color: var(--v10-ink);
}

body.ecb-v10.single-product .entry-summary > .price {
	font-family: var(--v10-display) !important;
	font-size: 28px !important;
	font-weight: 400 !important;
	color: var(--v10-ink);
}

body.ecb-v10.single-product .entry-summary > .price ins {
	color: var(--v10-red);
	text-decoration: none;
}

body.ecb-v10.single-product .entry-summary > .price del {
	font-size: 19px;
	color: var(--v10-muted);
}

/* --------------------------------------------------------------------------
   Add to cart / Buy Now hover sweep
   Both buttons were built as an outlined label over a ::before that scales in
   from the left. On this stack that pseudo-element computes to display:none,
   so the fill never painted — and because the hover rule still flips the label
   to ivory, hovering Add to cart left near-white text on a white button and
   the label disappeared. The same happened in the .added state, since the
   pointer is still over the button when WooCommerce finishes.

   The sweep is redrawn here as a background-image on the button itself, which
   paints above background-color and below the label with no stacking context
   to negotiate, so no pseudo-element is involved. ::before is retired for
   these two so nothing double-draws.
   -------------------------------------------------------------------------- */
body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button,
body.ecb-v10 .ecb-buynow {
	background-repeat: no-repeat;
	background-position: left center;
	background-size: 0 100%;
	transition: background-size 400ms var(--ecb-ease), color 400ms var(--ecb-ease), border-color 350ms var(--ecb-ease);
}

body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button::before,
body.ecb-v10 .ecb-buynow::before {
	content: none;
}

body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button {
	background-image: linear-gradient(var(--ecb-plum), var(--ecb-plum));
}

body.ecb-v10 .ecb-buynow {
	background-image: linear-gradient(var(--ecb-charcoal), var(--ecb-charcoal));
}

body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button:hover:not(:disabled):not(.disabled),
body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button:focus-visible:not(:disabled):not(.disabled),
body.ecb-v10 .ecb-buynow:hover:not(:disabled):not(.disabled),
body.ecb-v10 .ecb-buynow:focus-visible:not(:disabled):not(.disabled) {
	background-size: 100% 100%;
}

/* A disabled or out-of-stock button must never look like it is filling. */
body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button:disabled,
body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button.disabled,
body.ecb-v10 .ecb-buynow:disabled,
body.ecb-v10 .ecb-buynow.disabled {
	background-image: none;
}

/* --------------------------------------------------------------------------
   "View cart", the link WooCommerce prints beside Add to cart once an item is
   added. Blocksy hands it rgba(224,229,235,.6) — a cool grey that belongs to
   no part of this palette. It is a secondary route, so it takes the same
   quiet outline as the WhatsApp and Call actions beneath it.
   -------------------------------------------------------------------------- */
body.ecb-v10 .added_to_cart,
body.ecb-v10 .ct-cart-actions .added_to_cart {
	--theme-button-background-initial-color: transparent;
	--theme-button-background-hover-color: var(--ecb-plum);
	--theme-button-text-initial-color: var(--ecb-plum);
	--theme-button-text-hover-color: #FBF8F4;
	min-height: 44px;
	border: 1px solid var(--ecb-plum);
	background-color: transparent;
	color: var(--ecb-plum);
	font-size: 12.5px;
	letter-spacing: .12em;
	text-transform: uppercase;
}

body.ecb-v10 .added_to_cart:hover,
body.ecb-v10 .added_to_cart:focus-visible {
	background-color: var(--ecb-plum);
	color: #FBF8F4;
}

/* --------------------------------------------------------------------------
   Standfirst paragraphs inside a constrained block layout
   .ecb-lede caps its measure at 38rem for readability. WordPress's
   is-layout-constrained then centres any child narrower than the container,
   so on /faq/ the standfirst sat 307px to the right of the H1 and of every
   question below it, reading as a mistake rather than a measure. The cap
   stays; the block just keeps the page's left edge.
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   Size type mark
   Stands where the size selector would stand, in the same label-then-control
   rhythm, so a one-size or made-to-measure piece reads as a deliberate answer
   to the size question rather than a missing control.
   -------------------------------------------------------------------------- */
.ecb-sizetype {
	margin: 0 0 18px;
}

.ecb-sizetype__label {
	display: block;
	margin-bottom: 9px;
	color: var(--v10-muted);
	font-size: 10.5px;
	letter-spacing: .14em;
	text-transform: uppercase;
}

.ecb-sizetype__chip {
	display: inline-flex;
	min-height: 40px;
	align-items: center;
	padding: 0 18px;
	border: 1px solid var(--v10-dark);
	color: var(--v10-dark);
	font-size: 12.5px;
	letter-spacing: .1em;
	text-transform: uppercase;
}

.ecb-sizetype--custom .ecb-sizetype__chip {
	border-color: var(--v10-accent);
	color: var(--v10-accent);
}

.ecb-sizetype__note {
	max-width: 46ch;
	margin: 11px 0 0;
	color: var(--v10-muted);
	font-size: 13px;
	line-height: 1.6;
	text-wrap: pretty;
}

.ecb-sizetype__note a {
	color: var(--ecb-plum);
	text-underline-offset: 3px;
}

/* The second note is the pair of links; keep them on one line where there is
   room and let them wrap cleanly where there is not. */
.ecb-sizetype__note + .ecb-sizetype__note {
	display: flex;
	flex-wrap: wrap;
	gap: 6px 18px;
	margin-top: 8px;
}

/* --------------------------------------------------------------------------
   Forgot-password panel
   The auth screens put their form on a dark panel over the photograph, and
   .woocommerce-ResetPassword is styled for it — cream label text, translucent
   inputs. But that panel is declared on a two-class selector, and the generic
   "body.ecb-v10-auth-page .woocommerce form { background: transparent; padding: 0 }"
   reset a few lines later carries an extra element selector and therefore wins.
   Sign in and Create account were unaffected: #customer_login is a div, not a
   form, so the reset never matched it.

   The result was cream text and a transparent input sitting directly on the
   photograph, with nothing behind them — the one auth screen you reach when you
   are already locked out. Restated at a specificity the reset cannot beat.
   -------------------------------------------------------------------------- */
body.ecb-v10-auth-page .woocommerce form.woocommerce-ResetPassword,
body.ecb-v10-auth-page .woocommerce form.lost_reset_password {
	width: 100%;
	max-width: none;
	margin: 0;
	padding: 34px 42px 42px;
	border: 1px solid rgba(255, 255, 255, .18);
	border-top: 0;
	background: rgba(23, 16, 13, .9);
	color: #EFE4D4;
}


/* --------------------------------------------------------------------------
   Checkout fields the delivery-area selector fills in
   WooCommerce's own District dropdown asked the same question as the ECB
   "Area / District" selector standing next to it. It is still submitted and
   still stored — the server derives it from the area choice — but it is no
   longer a second thing to answer. Kept in the DOM so WooCommerce's own
   scripts, validation and address saving carry on unchanged.
   -------------------------------------------------------------------------- */
body.ecb-v10 .woocommerce form .form-row.ecb-derived-field,
body.ecb-v10 .ecb-derived-field {
	position: absolute !important;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

body.ecb-v10 .entry-content > .ecb-lede,
body.ecb-v10 .is-layout-constrained > .ecb-lede {
	/* Take the same column every sibling takes. The 38rem cap is what pulled
	   the block out of it, and WordPress centres constrained children with
	   margin-left/right: auto !important, so both have to be restated. */
	max-width: none !important;
	margin-inline: auto !important;
}

/* ---------------------------------------------------------------------------
   Made-to-measure panel at checkout

   Sits under the order notes, so it reads as the last thing asked before
   payment.  Two columns on desktop, one on a phone; the hint under each field
   is the same wording as the size guide so the customer is not told two
   different things about the same measurement.
   --------------------------------------------------------------------------- */

body.ecb-v10 .ecb-measure {
	margin: 30px 0 0;
	padding: 26px 26px 8px;
	border: 1px solid var(--v10-rule);
	background: var(--v10-paper);
}

body.ecb-v10 .ecb-measure__title {
	margin: 0 0 6px;
	font-family: var(--v10-display);
	font-size: 25px;
	font-weight: 500;
	line-height: 1.2;
	color: var(--v10-ink);
}

body.ecb-v10 .ecb-measure__lede {
	max-width: 58ch;
	margin: 0 0 22px;
	font-size: 13.5px;
	line-height: 1.65;
	color: var(--v10-ink-soft);
	text-wrap: pretty;
}

body.ecb-v10 .ecb-measure__set {
	margin: 0 0 18px;
	padding: 0;
	border: 0;
	border-top: 1px solid var(--v10-rule);
	padding-top: 18px;
}

body.ecb-v10 .ecb-measure__legend {
	padding: 0;
	margin-bottom: 14px;
	font-size: 10.5px;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--v10-muted);
}

body.ecb-v10 .ecb-measure__grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 4px 22px;
}

body.ecb-v10 .ecb-measure__field {
	margin: 0 0 14px;
}

body.ecb-v10 .ecb-measure__field--wide {
	margin-top: 4px;
}

body.ecb-v10 .ecb-measure__field label {
	display: block;
	margin-bottom: 6px;
	font-size: 12.5px;
	letter-spacing: .02em;
	color: var(--v10-ink);
}

body.ecb-v10 .ecb-measure__field input,
body.ecb-v10 .ecb-measure__field textarea {
	width: 100%;
	min-height: 44px;
	padding: 10px 12px;
	border: 1px solid var(--v10-rule);
	background: var(--v10-page);
	font-family: var(--v10-body);
	font-size: 14px;
	color: var(--v10-ink);
}

body.ecb-v10 .ecb-measure__field textarea {
	min-height: 66px;
	resize: vertical;
}

body.ecb-v10 .ecb-measure__field input:focus,
body.ecb-v10 .ecb-measure__field textarea:focus {
	outline: 2px solid var(--v10-accent);
	outline-offset: 1px;
	border-color: var(--v10-accent);
}

body.ecb-v10 .ecb-measure__hint {
	display: block;
	margin-top: 5px;
	font-size: 11.5px;
	line-height: 1.5;
	color: var(--v10-muted);
	text-wrap: pretty;
}

@media (max-width: 640px) {
	body.ecb-v10 .ecb-measure {
		padding: 20px 18px 4px;
	}

	body.ecb-v10 .ecb-measure__grid {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* ---------------------------------------------------------------------------
   Size chart

   Five narrow numeric columns.  It fits at every width the site is built for,
   but the wrapper scrolls anyway so a longer chart added later cannot push the
   page sideways.
   --------------------------------------------------------------------------- */

body.ecb-v10 .ecb-sizechart {
	margin: 26px 0 30px;
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
}

body.ecb-v10 .ecb-sizechart table {
	width: 100%;
	min-width: 380px;
	border-collapse: collapse;
	font-variant-numeric: tabular-nums;
}

body.ecb-v10 .ecb-sizechart th,
body.ecb-v10 .ecb-sizechart td {
	padding: 11px 14px;
	border: 0;
	border-bottom: 1px solid var(--v10-rule);
	text-align: right;
	font-size: 14px;
	color: var(--v10-ink);
}

body.ecb-v10 .ecb-sizechart th:first-child,
body.ecb-v10 .ecb-sizechart td:first-child {
	text-align: left;
}

body.ecb-v10 .ecb-sizechart thead th {
	border-bottom-color: var(--v10-ink);
	font-family: var(--v10-body);
	font-size: 10.5px;
	font-weight: 400;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--v10-muted);
}

body.ecb-v10 .ecb-sizechart tbody td:first-child {
	letter-spacing: .08em;
	color: var(--v10-ink-soft);
}

body.ecb-v10 .ecb-sizechart tbody tr:last-child td {
	border-bottom-color: var(--v10-ink);
}

body.ecb-v10 .ecb-sizechart figcaption,
body.ecb-v10 .ecb-sizechart .wp-element-caption {
	margin-top: 12px;
	font-size: 12.5px;
	line-height: 1.6;
	color: var(--v10-muted);
	text-align: left;
	text-wrap: pretty;
}

/* ---------------------------------------------------------------------------
   Condensed header keeps the brand

   Scrolling used to take the whole brand row away and leave the category strip
   floating on its own, which is what made the bar look like it was jumping: two
   rows collapsing at once, one of them sliding upward under `overflow: hidden`,
   changed the sticky element's height by 132px in a single step. Now only the
   announcement strip goes; the brand row shrinks in place and the logo stays put
   at every scroll position.
   --------------------------------------------------------------------------- */

.ecb-v10-headmain__inner,
.ecb-v10-brand > img,
.ecb-v10-brand__words > span,
.ecb-v10-brand__words small {
	transition: height 260ms var(--v10-ease), min-height 260ms var(--v10-ease),
		font-size 260ms var(--v10-ease), margin-top 260ms var(--v10-ease);
}

.ecb-v10-header.is-condensed .ecb-v10-headmain { max-height: 62px; }
.ecb-v10-header.is-condensed .ecb-v10-headmain__inner { min-height: 62px; }
.ecb-v10-header.is-condensed .ecb-v10-brand > img { height: 34px; }
.ecb-v10-header.is-condensed .ecb-v10-brand__words > span { font-size: 14px; letter-spacing: .13em; }
.ecb-v10-header.is-condensed .ecb-v10-brand__words small { margin-top: 3px; font-size: 7px; letter-spacing: .3em; }

@media (prefers-reduced-motion: reduce) {
	.ecb-v10-headmain,
	.ecb-v10-headmain__inner,
	.ecb-v10-announcement,
	.ecb-v10-brand > img,
	.ecb-v10-brand__words > span,
	.ecb-v10-brand__words small { transition: none; }
}
/* ---------------------------------------------------------------------------
   Password show/hide

   Blocksy draws this toggle as a 14px mask-image on an empty button, and a mask
   repeats by default. Our WooCommerce button rule was giving every button a 48px
   min-height, which the toggle inherited — so the eye tiled three times down it
   on the account, sign-in and registration forms. The rule now skips this button;
   these three lines make sure no future height can tile the icon again.

   Blocksy also centres the icon against a 40px field, and V10 fields are 48px, so
   the eye sat above centre. Telling Blocksy the real field height fixes its own
   arithmetic rather than overriding the result.
   --------------------------------------------------------------------------- */

body.ecb-v10 form:is(.login, .register, .edit-account, .lost_reset_password) [class*="password-input"] {
	--theme-form-field-height: 48px;
}

body.ecb-v10 .show-password-input {
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
}

body.ecb-v10 .show-password-input:focus-visible {
	outline: 2px solid var(--v10-accent);
	outline-offset: 3px;
}

/* Edge draws its own reveal control inside the field. Ours is the one wired to
   the label and the keyboard, so hide theirs rather than show two. */
body.ecb-v10 input[type="password"]::-ms-reveal,
body.ecb-v10 input[type="password"]::-ms-clear { display: none; }


/* ---------------------------------------------------------------------------
   Account menu

   "Account details" is the one label that wraps to two lines at this width, and
   the fixed row height cropped the second line outside the panel. Let the row
   take the height its label needs.
   --------------------------------------------------------------------------- */

body.ecb-v10.logged-in.woocommerce-account .woocommerce-MyAccount-navigation li a {
	height: auto;
	min-height: 55px;
	padding-block: 13px;
	line-height: 1.35;
	text-wrap: pretty;
}

/* ---------------------------------------------------------------------------
   Sign in and create account

   The panel is meant to be the dark card set on the photograph, and everything
   inside it — labels, links, the heading, the field borders — is coloured for
   that ground. WooCommerce wraps each form in `.col-1` / `.col-2`, which arrive
   carrying a white card of their own; painted over the dark panel, that left
   white text on white. The heading disappeared entirely and the field labels
   were reading at 1.6:1.

   Clearing the columns' own surface puts the intended card back, and every
   colour in this section resolves against the ground it was chosen for.
   --------------------------------------------------------------------------- */

body.ecb-v10-auth-page #customer_login > .u-column1,
body.ecb-v10-auth-page #customer_login > .u-column2,
body.ecb-v10-auth-page #customer_login > .col-1,
body.ecb-v10-auth-page #customer_login > .col-2 {
	border: 0;
	border-radius: 0;
	background: transparent;
	box-shadow: none;
}

/* The toggle's mask is tinted with the theme text colour, which is dark; on this
   panel it needs the light one or the eye is invisible against the field. */
body.ecb-v10-auth-page form:is(.login, .register) [class*="password-input"] .show-password-input { background-color: #D8C9BC; }
body.ecb-v10-auth-page form:is(.login, .register) [class*="password-input"] .show-password-input:hover,
body.ecb-v10-auth-page form:is(.login, .register) [class*="password-input"] .show-password-input:focus-visible,
body.ecb-v10-auth-page form:is(.login, .register) [class*="password-input"] .show-password-input.display-password { background-color: var(--v10-accent-hi); }

/* ---------------------------------------------------------------------------
   Product gallery

   Blocksy's gallery track is a horizontally scrolling flex row. Showing one
   frame at a time by hiding the others with `display: none` left the track's
   scroll position pointing at a layout that no longer existed, so the one
   visible frame ended up scrolled out of the window — the image went blank the
   moment anything touched the gallery. Measured at rest: the active frame was
   sitting 382px to the left of its own container.

   Stacking the frames in a single grid cell removes the scroll axis entirely.
   There is nothing to scroll, nothing to translate, and changing frame is a
   crossfade rather than a slide that can strand the picture off-screen.
   --------------------------------------------------------------------------- */

body.ecb-v10 .woocommerce-product-gallery.ecb-gallery-ready .flexy-view,
body.ecb-v10 .woocommerce-product-gallery.ecb-gallery-ready .flexy-items {
	overflow: hidden;
	scroll-snap-type: none;
}

body.ecb-v10 .woocommerce-product-gallery.ecb-gallery-ready .flexy-items {
	display: grid;
	transform: none !important;
	transition: none;
}

body.ecb-v10 .woocommerce-product-gallery.ecb-gallery-ready .flexy-items > .flexy-item {
	display: block;
	grid-area: 1 / 1;

	/* The reset that was missing, and the whole reason the main photograph was
	   an empty ivory box.

	   Blocksy positions its carousel by translating the CHILDREN:
	       .flexy-items > * { transform: translate3d(-100%, 0, 0) }
	   An earlier attempt reset `transform` on `.flexy-items` — the container —
	   which Blocksy never transforms, so nothing changed. Every frame stayed
	   shifted a full width to the left, outside a `.flexy-view` that clips its
	   overflow. The frame was there, visible, carrying a loaded image, and
	   parked off the side of its own container.

	   `order` goes with it: Blocksy reorders the children to fake the loop,
	   which is meaningless once they are stacked in one grid cell. */
	transform: none !important;
	order: 0 !important;
	opacity: 0;
	visibility: hidden;
	transition: opacity 300ms var(--v10-ease), visibility 0s linear 300ms;
}

body.ecb-v10 .woocommerce-product-gallery.ecb-gallery-ready .flexy-items > .flexy-item.is-active {
	opacity: 1;
	visibility: visible;
	transition-delay: 0s, 0s;
}

@media (prefers-reduced-motion: reduce) {
	body.ecb-v10 .woocommerce-product-gallery.ecb-gallery-ready .flexy-items > .flexy-item { transition: none; }
}

/* The sticky bar sat at 97% opacity, so whatever scrolled under it stayed faintly
   legible through it — product titles and thumbnails ghosting across the nav.
   Nothing is gained by the translucency at that level; make it opaque. */
body.ecb-v10 .ecb-v10-header { background: var(--v10-page); }

/* ---------------------------------------------------------------------------
   Notices

   V10 repainted these banners onto pale paper but left the text colour they
   inherit from Blocksy, which is white because Blocksy draws them as solid
   coloured bars. The result was white on #FFFDFA — 1.02:1 — so every message
   WooCommerce shows was invisible: "Please choose product options", "added to
   your cart", checkout validation, all of it. Set the ink with the ground.
   --------------------------------------------------------------------------- */

body.ecb-v10 :where(.woocommerce-error, .woocommerce-info, .woocommerce-message, .woocommerce-noreviews),
body.ecb-v10 :where(.woocommerce-error, .woocommerce-info, .woocommerce-message) li,
body.ecb-v10 :where(.woocommerce-error, .woocommerce-info, .woocommerce-message) strong {
	color: var(--v10-ink);
}

body.ecb-v10 .woocommerce-error { border-top-color: var(--v10-red); }
body.ecb-v10 .woocommerce-error::before { color: var(--v10-red); }
body.ecb-v10 .woocommerce-info::before,
body.ecb-v10 .woocommerce-message::before { color: var(--v10-accent); }

body.ecb-v10 :where(.woocommerce-error, .woocommerce-info, .woocommerce-message) a:not(.button) {
	color: var(--ecb-plum, var(--v10-ink));
	text-underline-offset: 3px;
}

/* ---------------------------------------------------------------------------
   Cart totals

   The totals table was laid out with `table-layout: fixed`, and because the
   shipping row's cell is a full-width block the column algorithm read the first
   row alone: label 325px, amount 3px. Every figure then rendered outside its own
   cell and outside the card's border. Letting the table size itself, and giving
   the label column only the width its text needs, puts the amounts back inside.

   The table also carried a border of its own inside a card that already has one,
   which is the second box in the corner. Rows are separated by rules instead.
   --------------------------------------------------------------------------- */

body.ecb-v10 .cart_totals table.shop_table {
	table-layout: auto;
	width: 100%;
	border: 0;
	border-collapse: collapse;
}

body.ecb-v10 .cart_totals table.shop_table th,
body.ecb-v10 .cart_totals table.shop_table td {
	padding: 13px 0;
	border: 0;
	border-bottom: 1px solid var(--v10-rule);
	vertical-align: baseline;
}

body.ecb-v10 .cart_totals table.shop_table th {
	width: 1%;
	white-space: nowrap;
	text-align: left;
	font-weight: 400;
	color: var(--v10-ink-soft);
}

body.ecb-v10 .cart_totals table.shop_table td {
	text-align: right;
	color: var(--v10-ink);
	font-variant-numeric: tabular-nums;
}

/* The delivery row is its own block — heading, method, then the address. */
body.ecb-v10 .cart_totals table.shop_table tr.woocommerce-shipping-totals td {
	width: 100%;
	text-align: left;
}

body.ecb-v10 .cart_totals table.shop_table tr:last-child th,
body.ecb-v10 .cart_totals table.shop_table tr:last-child td {
	border-bottom: 0;
}

body.ecb-v10 .cart_totals table.shop_table tr.order-total th,
body.ecb-v10 .cart_totals table.shop_table tr.order-total td {
	padding-top: 16px;
	border-top: 1px solid var(--v10-ink);
	font-size: 16px;
	color: var(--v10-ink);
}

/* ---------------------------------------------------------------------------
   The buy actions

   Add to cart was drawn as an outlined button that fills with plum from the left
   on hover. Two things went wrong with that. Caught part-way — a pointer leaving
   mid-transition, or a touch screen holding the hover state — it renders as a
   plum block against white and reads as a broken control. And at rest the
   primary action was an outline while Buy Now beside it was a solid bar, so the
   secondary action looked like the important one.

   The primary action is now solid at rest and deepens on hover. Nothing animates
   width, so there is no state in which it can be caught half-drawn.
   --------------------------------------------------------------------------- */

body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button {
	background-image: none;
	background-color: var(--ecb-plum, var(--v10-dark));
	border: 1px solid var(--ecb-plum, var(--v10-dark));
	color: #fff;
	transition: background-color 220ms var(--v10-ease), border-color 220ms var(--v10-ease);
}

body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button:hover:not(:disabled):not(.disabled),
body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button:focus-visible:not(:disabled):not(.disabled) {
	background-color: var(--v10-dark);
	border-color: var(--v10-dark);
	color: #fff;
}

/* Buy Now is the second route to the same purchase, so it steps back to an
   outline rather than competing with the primary button beside it. */
body.ecb-v10 .ecb-buynow {
	background-image: none;
	background-color: transparent;
	border: 1px solid var(--v10-dark);
	color: var(--v10-dark);
	transition: background-color 220ms var(--v10-ease), color 220ms var(--v10-ease);
}

body.ecb-v10 .ecb-buynow:hover:not(:disabled):not(.disabled),
body.ecb-v10 .ecb-buynow:focus-visible:not(:disabled):not(.disabled) {
	background-color: var(--v10-dark);
	color: #fff;
}

/* Out of stock, or no size chosen yet: quiet, and unmistakably not pressable. */
body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button:disabled,
body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button.disabled {
	background-color: var(--v10-wash);
	border-color: var(--v10-rule);
	color: var(--v10-muted);
	cursor: not-allowed;
}

/* ---------------------------------------------------------------------------
   Theme toggle

   Lives in the header row with search and the bag, so it reads as one of the
   shop's controls rather than a widget bolted on. Only one of the two icons is
   ever in the box: the sun when the page is dark, the moon when it is light —
   the icon shows what pressing it will give you, which is the same promise the
   label makes.
   --------------------------------------------------------------------------- */

.ecb-theme-toggle {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	color: inherit;
	cursor: pointer;
}

.ecb-theme-toggle svg {
	transition: opacity 200ms var(--v10-ease), transform 320ms var(--v10-ease);
}

.ecb-theme-toggle__sun {
	position: absolute;
	inset: 50% auto auto 50%;
	translate: -50% -50%;
}

/* Light page: offer the moon. */
.ecb-theme-toggle__sun { opacity: 0; transform: rotate(-90deg) scale(.6); }
.ecb-theme-toggle__moon { opacity: 1; transform: none; }

/* Dark page: offer the sun. */
html.ecb-dc .ecb-theme-toggle__moon { opacity: 0; transform: rotate(90deg) scale(.6); }
html.ecb-dc .ecb-theme-toggle__sun { opacity: 1; transform: translate(-50%, -50%) rotate(0) scale(1); }

html.ecb-dc .ecb-theme-toggle:hover { color: var(--v10-accent-hi); }
body.ecb-lt .ecb-theme-toggle:hover { color: var(--ecb-plum); }

@media (prefers-reduced-motion: reduce) {
	.ecb-theme-toggle svg { transition: opacity 120ms linear; transform: none !important; }
	html.ecb-dc .ecb-theme-toggle__sun { transform: translate(-50%, -50%) !important; }
}

/* ---------------------------------------------------------------------------
   The brand lock-up

   The logo is one image now — monogram, halo and wordmark together — so it is
   sized by height and lets its own aspect do the rest. Two copies are in the
   markup, the uploaded original and a cream repaint, and only the one matching
   the current theme is ever displayed.
   --------------------------------------------------------------------------- */

.ecb-v10-brand { display: inline-flex; align-items: center; }

.ecb-v10-brand > img.ecb-v10-brand__logo {
	display: block;
	width: auto;
	height: 52px;
	max-width: none;
	object-fit: contain;
	transition: height 260ms var(--v10-ease);
}

.ecb-v10-header.is-condensed .ecb-v10-brand > img.ecb-v10-brand__logo { height: 38px; }

/* One version at a time. */
.ecb-v10-brand > img.ecb-v10-brand__logo--dark { display: none; }
html.ecb-dc .ecb-v10-brand > img.ecb-v10-brand__logo--light { display: none; }
html.ecb-dc .ecb-v10-brand > img.ecb-v10-brand__logo--dark { display: block; }

/* The drawer and the footer are dark in both themes and carry the cream mark. */
.ecb-v10-brand--on-dark > img.ecb-v10-brand__logo { height: 46px; }

@media (max-width: 880px) {
	.ecb-v10-brand > img.ecb-v10-brand__logo { height: 40px; }
	.ecb-v10-header.is-condensed .ecb-v10-brand > img.ecb-v10-brand__logo { height: 34px; }
}

@media (max-width: 480px) {
	.ecb-v10-brand > img.ecb-v10-brand__logo,
	.ecb-v10-header.is-condensed .ecb-v10-brand > img.ecb-v10-brand__logo { height: 32px; }
}

@media (prefers-reduced-motion: reduce) {
	.ecb-v10-brand > img.ecb-v10-brand__logo { transition: none; }
}

/* ---------------------------------------------------------------------------
   Theme control in the drawer

   A named row rather than a second icon: on a phone the header already carries
   a hamburger, the logo, search and the bag, and a fifth 40px target among them
   is where a setting goes to be missed. The drawer says what it is and shows
   which of the two is on.
   --------------------------------------------------------------------------- */

.ecb-v10-drawer__theme {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 18px 0 4px;
	border-top: 1px solid rgba(255, 255, 255, .12);
	margin-top: 4px;
}

.ecb-v10-drawer__theme-label {
	font-size: 10px;
	letter-spacing: .22em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, .55);
}

.ecb-v10-drawer__theme-btn {
	display: inline-flex;
	align-items: stretch;
	min-height: 40px;
	padding: 0;
	border: 1px solid rgba(255, 255, 255, .28);
	border-radius: 0;
	background: transparent;
	cursor: pointer;
	overflow: hidden;
}

.ecb-v10-drawer__theme-btn > span {
	display: flex;
	align-items: center;
	padding: 0 16px;
	font-family: var(--v10-body);
	font-size: 11px;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, .62);
	transition: background-color 200ms var(--v10-ease), color 200ms var(--v10-ease);
}

/* Whichever theme is on is the filled half. */
.ecb-v10-drawer__theme-off { background: var(--v10-accent-hi); color: #14100E !important; }
html.ecb-dc .ecb-v10-drawer__theme-off { background: transparent; color: rgba(255, 255, 255, .62) !important; }
html.ecb-dc .ecb-v10-drawer__theme-on { background: var(--v10-accent-hi); color: #14100C !important; }

.ecb-v10-drawer__theme-btn:focus-visible {
	outline: 2px solid var(--v10-accent-hi);
	outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
   Add to cart — the buy row

   Modelled on the reference: quantity and a single outlined button sitting as
   one pair, the label in wide-tracked capitals, and a cart mark inside the
   button rather than beside it.

   The icon is a mask rather than an <img> or an inline SVG, for two reasons: it
   needs no markup change on a WooCommerce template, and a mask is painted with
   `background-color`, so setting that to `currentColor` makes the icon follow
   the label through every state — including the hover that inverts the button —
   without a second rule.
   --------------------------------------------------------------------------- */

body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 11px;
	text-transform: uppercase;
	letter-spacing: .16em;
	font-size: 12.5px;
	font-weight: 500;
}

body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button::before {
	content: "";
	flex: none;
	width: 18px;
	height: 18px;
	background-color: currentColor;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-image: var(--ecb-cart-icon);
	mask-image: var(--ecb-cart-icon);
}

:root {
	--ecb-cart-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M6 7V6a6 6 0 0 1 12 0v1h2.2a1 1 0 0 1 1 1.1l-1.3 12A2 2 0 0 1 17.9 22H6.1a2 2 0 0 1-2-1.9l-1.3-12A1 1 0 0 1 3.8 7H6zm2 0h8V6a4 4 0 0 0-8 0v1z'/%3E%3C/svg%3E");
}

/* The pair reads as one control: same height, same hairline, no gap that makes
   them look like two unrelated things. */
body.ecb-v10.single-product form.cart .quantity input,
body.ecb-v10.single-product .single_add_to_cart_button { min-height: 52px; }

@media (max-width: 560px) {
	body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button {
		gap: 9px;
		letter-spacing: .12em;
	}
}

/* This button's pseudo-elements are forced to `display: none` somewhere in the
   parent stack — the same thing that defeated the hover sweep in the first
   round. Saying it explicitly is the whole fix. */
body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button::before {
	display: block;
}

/* The mark is a real span injected by the script, not a pseudo-element: this
   button's pseudo-elements are forced to `display: none` somewhere in the parent
   stack. A mask on a real element paints reliably, and painting it with
   `currentColor` means it inverts with the button on hover for free. */
body.ecb-v10 .single_add_to_cart_button .ecb-cart-mark {
	display: block;
	flex: none;
	width: 18px;
	height: 18px;
	background-color: currentColor;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-image: var(--ecb-cart-icon);
	mask-image: var(--ecb-cart-icon);
}

/* At 360 the mark plus the tracked-out label no longer fitted the button's own
   width, so the text wrapped and the row grew from 52px to 66px — the one place
   this control changed height. The label never wraps now, and the type tightens
   just enough at that width to stay on one line beside the mark. */
body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button {
	white-space: nowrap;
}

@media (max-width: 400px) {
	body.ecb-v10.woocommerce div.product form.cart .single_add_to_cart_button {
		gap: 8px;
		font-size: 11px;
		letter-spacing: .08em;
	}

	body.ecb-v10 .single_add_to_cart_button .ecb-cart-mark {
		width: 16px;
		height: 16px;
	}
}

/* ---------------------------------------------------------------------------
   Stock

   The count is quiet; the shortage is not. Red is already this site's "act on
   this" colour and it is used sparingly enough that borrowing it here still
   reads as urgent rather than decorative.
   --------------------------------------------------------------------------- */

/* style.css reaches this line at `.woocommerce div.product .stock.in-stock`,
   which is (0,4,1) and paints it the in-stock green — so a plain `.ecb-stock`
   rule loses and "Only 4 left" came out reassuringly green. Matched at (0,5,3). */
body.ecb-v10.woocommerce div.product p.stock.ecb-stock {
	margin: 0 0 14px;
	font-size: 13px;
	font-weight: 400;
	letter-spacing: .02em;
	color: var(--ecb-stock-ok);
}

body.ecb-v10.woocommerce div.product p.stock.ecb-stock--low {
	color: var(--ecb-sale);
	font-weight: 600;
}

/* On a card it sits under the title as a small line, not a badge: a badge there
   would compete with the discount mark, which is the louder of the two. */
body.ecb-v10 .ecb-stock--card {
	margin: 6px 0 0;
	font-size: 11.5px;
	letter-spacing: .06em;
	text-transform: uppercase;
}

/* ---------------------------------------------------------------------------
   Live activity

   Small, bottom-left, and never in the way. A full-screen or centre-screen
   notice would interrupt the one thing the visitor came to do; this is meant to
   be noticed out of the corner of the eye and then ignored.
   --------------------------------------------------------------------------- */

.ecb-live-viewers {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0 0 16px;
	font-size: 12.5px;
	color: var(--v10-muted);

	/* The line arrives a beat after the page and fades in rather than snapping,
	   so it is read as something that just happened. It is revealed by removing
	   [hidden], and the starting state below applies until .is-in lands. */
	opacity: 0;
	transform: translateY(3px);
	transition: opacity .45s var(--v10-ease), transform .45s var(--v10-ease);
}

.ecb-live-viewers.is-in {
	opacity: 1;
	transform: none;
}

/* The `hidden` attribute needs help here, and this is not cosmetic.
   A browser hides [hidden] with `display: none` from its OWN stylesheet, and
   any author `display` — the flex above — outranks that, whatever the
   specificity. The line was therefore never hidden at all: on a quiet product
   page it rendered with no text and a pulsing green dot, which is exactly the
   "something is loading forever" look the badge is meant to avoid. */
.ecb-live-viewers[hidden] {
	display: none;
}

.ecb-live-viewers__dot {
	width: 7px;
	height: 7px;
	flex: none;
	border-radius: 50%;
	background: #2E9E5B;
	box-shadow: 0 0 0 0 rgba(46, 158, 91, .55);
	animation: ecb-live-pulse 2.4s var(--v10-ease) infinite;
}

@keyframes ecb-live-pulse {
	0%   { box-shadow: 0 0 0 0 rgba(46, 158, 91, .5); }
	70%  { box-shadow: 0 0 0 7px rgba(46, 158, 91, 0); }
	100% { box-shadow: 0 0 0 0 rgba(46, 158, 91, 0); }
}

.ecb-live-toasts {
	position: fixed;
	left: 20px;
	bottom: 20px;
	z-index: 9000;
	display: flex;
	flex-direction: column;
	gap: 10px;
	pointer-events: none;
	max-width: min(340px, calc(100vw - 40px));
}

.ecb-toast {
	pointer-events: auto;
	position: relative;
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 10px 34px 10px 10px;
	background: var(--v10-paper);
	border: 1px solid var(--v10-rule);
	border-radius: 10px;
	box-shadow: 0 10px 30px -10px rgba(20, 16, 14, .28);
	opacity: 0;
	transform: translateY(10px);
	transition: opacity 300ms var(--v10-ease), transform 300ms var(--v10-ease);
}

.ecb-toast.is-in { opacity: 1; transform: none; }

/* The life bar.

   Full width when the card lands, then it drains to nothing over exactly as
   long as the card will live, and the card leaves as the bar empties. The two
   are the same event, so the disappearance is something the reader saw coming
   rather than something that happened to them.

   A transition rather than a keyframe animation, because a transition can be
   frozen at its current width when someone hovers to read, and restarted from
   there — a paused animation would still finish on the original clock. */
.ecb-toast__life {
	position: absolute;
	left: 0;
	bottom: 0;
	width: 100%;
	height: 2px;
	background: var(--v10-accent);
	border-radius: 0 0 0 10px;
	opacity: .55;
}

.ecb-toast.is-ticking .ecb-toast__life {
	width: 0;
	transition: width 6500ms linear;
}

.ecb-toast__img {
	width: 46px;
	height: 58px;
	flex: none;
	object-fit: cover;
	border-radius: 5px;
	background: var(--v10-wash);
}

.ecb-toast__body { min-width: 0; }

.ecb-toast p { margin: 0; }

/* The dark layer forces `color: inherit` on every p via
   `html.ecb-dc body :where(p, li, …)`, which is (0,1,2) and outranks a single
   class — the toast lost its hierarchy and printed every line in ink. Two
   classes beats one class plus two elements, so these win in both themes. */
.ecb-live-toasts .ecb-toast__who {
	font-size: 12.5px;
	font-weight: 600;
	color: var(--v10-ink);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.ecb-live-toasts .ecb-toast__what {
	font-size: 12px;
	line-height: 1.45;
	color: var(--v10-muted);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.ecb-live-toasts .ecb-toast__link { color: var(--v10-accent); text-decoration: none; }
.ecb-toast__link:hover { text-decoration: underline; }

.ecb-live-toasts .ecb-toast__when {
	margin-top: 2px;
	font-size: 10.5px;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--v10-muted);
}

.ecb-toast__close {
	position: absolute;
	top: 4px;
	right: 4px;
	width: 24px;
	height: 24px;
	display: grid;
	place-items: center;
	border: 0;
	background: none;
	color: var(--v10-muted);
	font-size: 17px;
	line-height: 1;
	cursor: pointer;
	border-radius: 5px;
}

.ecb-toast__close:hover { color: var(--v10-ink); background: var(--v10-wash); }

@media (max-width: 600px) {
	.ecb-live-toasts { left: 12px; right: 12px; bottom: 12px; max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
	.ecb-toast { transition: none; }
	/* The bar still empties — it is information, not decoration — but instantly,
	   so nothing on screen is continuously moving. */
	.ecb-toast.is-ticking .ecb-toast__life { transition: none; }
	.ecb-live-viewers__dot { animation: none; }

	/* No fade, but the line must still be visible once it is unhidden — the
	   starting state above is opacity 0, so it needs cancelling here too. */
	.ecb-live-viewers { transition: none; opacity: 1; transform: none; }
}

/* In the bag the line sits under the product name, tight to it. */
body.ecb-v10 .ecb-stock--cart {
	margin: 4px 0 0;
	font-size: 11.5px;
	letter-spacing: .04em;
}
body.ecb-v10 .ecb-stock--cart { color: var(--ecb-stock-ok); }
body.ecb-v10 .ecb-stock--cart.ecb-stock--low { color: var(--ecb-sale); font-weight: 600; }

/* The QR hint sits inside a filled dark button that already sets white type,
   then style.css repaints it `var(--ecb-plum)` — which has been ink since the
   burgundy was retired, so it was ink on ink at 1.05:1. A child of a filled
   button takes the button's colour. */
body.ecb-v10 .ecb-qr-open .ecb-qr-open__hint {
	color: inherit;
	opacity: .82;
}

/* The signup honeypot. Off-screen rather than display:none — some scripts skip
   anything hidden, and the point is that they should fill it in. */
.ecb-guard-field {
	position: absolute !important;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* ---------------------------------------------------------------------------
   The V9 page hero

   Shop, and every category page, use `.ecb-v9-pagehero` — a photograph under a
   dark scrim. It is a dark band in BOTH themes, so it is styled once here
   rather than twice in the layers.

   Two things were wrong. style.css sets the title white, correctly, but the
   light layer's `body.ecb-lt :where(h1, h2, …)` ink rule matches at the same
   specificity and loads later, so "Shop all" came out near-black on a dark
   photograph. And the eyebrow carries a hard-coded #E1C697 from before this
   palette existed — the last gold on the storefront.

   Matched at (0,2,0), which clears both.
   --------------------------------------------------------------------------- */

body.ecb-v10 .ecb-v9-pagehero__title {
	color: #FFFFFF;
}

body.ecb-v10 .ecb-v9-pagehero__eyebrow {
	/* The light step of the accent: this sits on a photograph, and the deep navy
	   disappears into one for the same reason it did in the V10 hero. */
	color: #A9C6FF;
}

/* --------------------------------------------------------------------------
   Links that had lost their own colour

   `body.ecb-v10 a { color: inherit }` near the top of this file is (0,1,2).
   Every one of these is styled in style.css by a single class at (0,1,0), so
   the inherit won and each took the body text colour instead of the one it was
   given. Most of them sit on the page background, where the inherited colour is
   at least readable and the loss is only of identity — but one was not:

   `.ecb-direct__btn--wa` has a fixed WhatsApp-green ground. In light the
   inherited ink happened to land at 5.50:1; in dark it inherits #D6CBBC and
   measures **1.24:1** — a green button with a word that is not there. Its ink
   is pinned rather than tokenised, because the ground is a brand colour that
   does not change with the theme, so the text must not either.

   Restated at (0,2,0) on V10 tokens, so both themes follow one definition.
   -------------------------------------------------------------------------- */
body.ecb-v10 .ecb-direct__btn--wa {
	color: #0B3D22;
}

body.ecb-v10 .ecb-direct__btn--call,
body.ecb-v10 .ecb-share__btn,
body.ecb-v10 .ecb-subnav__link {
	color: var(--v10-ink);
}

body.ecb-v10 .ecb-empty__link {
	color: var(--v10-accent);
}

body.ecb-v10 .ecb-cat-quicknav__link {
	color: var(--v10-muted);
}

body.ecb-v10 .ecb-cat-quicknav__link:hover,
body.ecb-v10 .ecb-subnav__link:hover,
body.ecb-v10 .ecb-share__btn:hover,
body.ecb-v10 .ecb-direct__btn--call:hover {
	color: var(--v10-accent);
}

/* The reset-confirmation message needs the panel the form has.

   WooCommerce renders `lost-password-confirmation.php` as a bare <p> with no
   class and no wrapper. The form state sits on `.woocommerce-ResetPassword`,
   which carries the dark panel — but once the form is replaced by the
   confirmation there is no panel left, so the sentence lands straight on the
   background photograph and washes out. `.woocommerce > p` reaches only this
   one: every paragraph in the form state is inside <form>, not a direct child. */
body.ecb-v10-auth-page .woocommerce > p {
	max-width: 100%;
	margin: 0;
	padding: 30px 42px 34px;
	border: 1px solid rgba(255, 255, 255, .18);
	background: rgba(23, 16, 13, .9);
	color: #EFE4D4;
	font-size: 14px;
	line-height: 1.7;
	text-align: center;
	box-shadow: 0 30px 80px rgba(0, 0, 0, .32);
	backdrop-filter: blur(12px);
}

/* A gallery must never be an empty box.

   The stacking rules above hide every frame that is not `.is-active`, and
   nothing in the server-rendered HTML carries that class — it is added by
   script. So any product with more than one photograph depended entirely on
   that script finishing to show anything at all, and if it did not, the
   customer got a framed white rectangle where the garment should be. The demo
   products all have a single image and no gallery, which is why it went
   unseen until a real product with four photographs was published.

   This is the safety net: while no frame has been marked, the first one shows.
   The moment the script marks one, `:has()` stops matching and the normal
   crossfade takes over. A browser without `:has()` simply drops this rule and
   is no worse off than before. */
body.ecb-v10 .woocommerce-product-gallery.ecb-gallery-ready .flexy-items:not(:has(> .flexy-item.is-active)) > .flexy-item:first-child {
	opacity: 1;
	visibility: visible;
}

/* Reset by phone, under the email form on the lost-password page. */
.ecb-rp { margin-top: 26px; }

.ecb-rp__or {
	position: relative;
	margin: 0 0 20px;
	text-align: center;
}
.ecb-rp__or::before {
	position: absolute;
	top: 50%;
	left: 0;
	right: 0;
	height: 1px;
	background: rgba(255, 255, 255, .18);
	content: "";
}
.ecb-rp__or span {
	position: relative;
	padding: 0 12px;
	background: rgba(23, 16, 13, .9);
	color: #B6A697;
	font-size: 10.5px;
	letter-spacing: .18em;
	text-transform: uppercase;
}

.ecb-rp__lead { margin: 0 0 14px; color: #D8C9BC; font-size: 13px; line-height: 1.6; }

.ecb-rp__msg {
	margin: 0 0 14px;
	padding: 10px 12px;
	border-left: 3px solid;
	font-size: 13px;
	line-height: 1.5;
}
/* Green reads as "done, now check your phone"; amber as "try again". Both are
   measured against the dark panel they sit on. */
.ecb-rp__msg.is-info  { border-color: #4FA96A; background: rgba(79, 169, 106, .12); color: #CDEAD6; }
.ecb-rp__msg.is-error { border-color: #E0A34A; background: rgba(224, 163, 74, .12); color: #F3DCBB; }

/* The code box: wide, spaced digits, so a six figure code is easy to check. */
#ecb_rp_code {
	font-size: 20px;
	letter-spacing: .5em;
	text-align: center;
	font-variant-numeric: tabular-nums;
}

/* Password reset by code. */
.ecb-otp__lead { margin: 0 0 16px; color: #D8C9BC; font-size: 13.5px; line-height: 1.6; }

.ecb-otp__msg {
	margin: 0 0 16px;
	padding: 11px 13px;
	border-left: 3px solid;
	border-radius: 3px;
	font-size: 13px;
	line-height: 1.5;
}
.ecb-otp__msg.is-info  { border-color: #4FA96A; background: rgba(79, 169, 106, .12); color: #CDEAD6; }
.ecb-otp__msg.is-error { border-color: #E0A34A; background: rgba(224, 163, 74, .12); color: #F3DCBB; }

/* The code box. Wide, spaced digits — six figures should be checkable at a
   glance against the notification they were read from. */
.ecb-otp__code {
	font-size: 24px !important;
	font-weight: 600;
	letter-spacing: .42em;
	text-align: center;
	text-indent: .42em;      /* the tracking is trailing, so re-centre it */
	font-variant-numeric: tabular-nums;
}

.ecb-otp__again { margin: 14px 0 0; text-align: center; }
.ecb-otp__again a { color: #B6A697; font-size: 12.5px; text-decoration: underline; }
.ecb-otp__again a:hover { color: #fff; }


/* --------------------------------------------------------------------------
   The code panel

   The reset screen is two stacked cards: `.ecb-v10-lost-intro` carries the mark
   and the heading, and the form below it continues the same dark panel with the
   top border removed, so the two read as one sheet of paper.

   That panel was declared on `form.woocommerce-ResetPassword` — WooCommerce's
   own form, which the code flow replaces. The code form is a form of ours
   inside `.ecb-otp`, matched none of it, and came out as cream text and a
   translucent input sitting directly on the photograph. The panel is restated
   here for the wrapper, at a specificity the generic
   `body.ecb-v10-auth-page .woocommerce form` reset cannot beat.
   -------------------------------------------------------------------------- */
body.ecb-v10-auth-page .woocommerce .ecb-otp {
	width: 100%;
	max-width: none;
	margin: 0;
	padding: 34px 42px 42px;
	border: 1px solid rgba(255, 255, 255, .18);
	border-top: 0;
	background: rgba(23, 16, 13, .9);
	color: #EFE4D4;
	box-shadow: 0 30px 80px rgba(0, 0, 0, .32);
}

body.ecb-v10-auth-page .woocommerce .ecb-otp form.ecb-otp__form {
	margin: 0;
	padding: 0;
	border: 0;
	background: transparent;
}

/* The mark and heading sit on the card above; nothing should show between. */
body.ecb-v10-auth-page .ecb-v10-lost-intro { padding-bottom: 30px; }

@media (max-width: 767px) {
	body.ecb-v10-auth-page .woocommerce .ecb-otp { padding: 26px 24px 32px; }
}


/* --------------------------------------------------------------------------
   The frames Blocksy collapses

   Blocksy keeps its carousel cheap by giving every frame its observer has not
   scrolled into view a height of one pixel:

       [data-flexy] .flexy-items > *:not(.flexy-item-is-visible) { height: 1px }

   These frames are stacked in a single grid cell, so the track never scrolls and
   that observer never fires past the first one. Frame 1 was 615px tall; frames
   2, 3 and 4 were one pixel, with the photograph overflowing into an ancestor
   that clips — which is why every thumbnail except the first opened onto an
   empty box. The class is now set in script for all of them; this is the same
   statement in CSS, so the frames have their height before script runs and
   cannot lose it if it does not.
   -------------------------------------------------------------------------- */
body.ecb-v10 .woocommerce-product-gallery.ecb-gallery-ready .flexy-items > .flexy-item {
	height: auto !important;
	min-height: 0;
}

/* --------------------------------------------------------------------------
   Hover zoom

   The photograph scales inside its own frame and follows the cursor — the
   pattern the owner asked for, and the one every catalogue of this kind uses.
   The frame already clips, so the whole effect is a transform with a moving
   origin; nothing is drawn on top of the picture.

   Two limits keep it from being the thing that was reported as broken. The
   factor never exceeds what the file can supply, so the magnified view is
   always sharper than the frame. And the origin is clamped to the picture
   itself: a tall photograph in a 4:5 frame leaves a band of empty paper down
   each side, and zooming into that band fills the frame with nothing.

   `will-change` only while zooming: promoting four full-height photographs to
   their own layers for the life of the page costs memory on a phone, for
   something only a mouse will ever use.
   -------------------------------------------------------------------------- */
body.ecb-v10 .woocommerce-product-gallery .flexy-item figure {
	overflow: hidden;
	cursor: zoom-in;
}

/* Easing in on arrival, then nothing — while the cursor moves the picture has
   to track it, not chase it a fifth of a second behind. */
body.ecb-v10 .woocommerce-product-gallery .flexy-item figure img {
	transition: transform 260ms var(--v10-ease);
}

body.ecb-v10 .woocommerce-product-gallery .flexy-item figure.ecb-zooming img {
	will-change: transform;
}

body.ecb-v10 .woocommerce-product-gallery .flexy-item figure.ecb-zooming:hover img {
	transition-property: none;
}

@media (prefers-reduced-motion: reduce) {
	body.ecb-v10 .woocommerce-product-gallery .flexy-item figure img { transition: none; }
}
/* --------------------------------------------------------------------------
   The code, as six boxes

   The field is the whole control and stays exactly where it was; it is simply
   made invisible and laid over the boxes, which are painted from its value.
   Colour, caret and background all go — but not the field, and not its size, so
   the click target and the focus ring are still the real ones.
   -------------------------------------------------------------------------- */
.ecb-otp__boxes { position: relative; margin: 0 0 22px; }

.ecb-otp__boxes-label {
	display: block;
	margin: 0 0 10px;
	color: #D8C9BC;
	font-size: 10.5px;
	letter-spacing: .12em;
	text-transform: uppercase;
}

.ecb-otp__boxes-hint {
	display: block;
	margin: 10px 0 0;
	color: #B6A697;
	font-size: 12px;
}

.ecb-otp__row {
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	gap: 10px;
}

.ecb-otp__cell {
	display: flex;
	min-height: 62px;
	align-items: center;
	justify-content: center;
	border: 1px solid rgba(255, 255, 255, .22);
	border-radius: 4px;
	background: rgba(255, 255, 255, .075);
	color: #fff;
	font-size: 26px;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	line-height: 1;
	transition: border-color 160ms var(--v10-ease), background-color 160ms var(--v10-ease);
}

.ecb-otp__cell.is-filled {
	border-color: rgba(255, 255, 255, .5);
	background: rgba(255, 255, 255, .12);
}

/* Where the next digit lands. The caret is hidden, so this is the only thing
   telling you the field has focus and where you are in it. */
.ecb-otp__cell.is-next {
	border-color: var(--v10-accent-hi);
	box-shadow: 0 0 0 1px var(--v10-accent-hi);
}

/* The field itself, once the boxes exist. Kept in the layout and kept focusable
   — only its paint is removed. */
body.ecb-v10-auth-page .woocommerce .ecb-otp .ecb-otp__boxes.is-boxed input.ecb-otp__code {
	position: absolute;
	inset: 0;
	height: 100%;
	min-height: 0;
	margin: 0;
	padding: 0;
	border: 0;
	background: transparent;
	color: transparent;
	caret-color: transparent;
	text-align: center;
	letter-spacing: 0;
	text-indent: 0;
	font-size: 16px;              /* iOS zooms a focused field under 16px */
}

/* The boxes carry the focus ring, so the field must not draw a second one. */
body.ecb-v10-auth-page .woocommerce .ecb-otp .ecb-otp__boxes.is-boxed input.ecb-otp__code:focus,
body.ecb-v10-auth-page .woocommerce .ecb-otp .ecb-otp__boxes.is-boxed input.ecb-otp__code:focus-visible {
	outline: 0;
	box-shadow: none;
}

/* Selection would show the invisible text as a coloured band across the boxes. */
.ecb-otp__boxes.is-boxed input.ecb-otp__code::selection { background: transparent; }

.ecb-otp__field { position: relative; }

@media (max-width: 480px) {
	.ecb-otp__row { gap: 6px; }
	.ecb-otp__cell { min-height: 52px; font-size: 21px; }
}


/* --------------------------------------------------------------------------
   The floor on small text

   Swept the live pages and measured every element carrying its own text. Three
   pieces of real information were sitting under the point where they can be
   read at arm's length on a phone: the result count on the shop page, WooCommerce's
   own buttons where it prints them at its default size, and the delivery note.
   Tracked uppercase captions are allowed to be small — that is what they are —
   but a sentence a customer is meant to read is not.
   -------------------------------------------------------------------------- */
body.ecb-v10 .woocommerce-result-count,
body.ecb-v10 .woocommerce-ordering select { font-size: 12.5px; }

/* WooCommerce's cart, checkout and account buttons inherit an 11px scale from
   the theme; a control label is not a caption. */
body.ecb-v10 .woocommerce a.button,
body.ecb-v10 .woocommerce button.button,
body.ecb-v10 .woocommerce input.button { font-size: 12.5px; }


/* --------------------------------------------------------------------------
   Header height

   Measured against the reference the owner asked to match: their header is a
   single 64px bar that scrolls away with the page. This one is three stacked
   bars that stay — announcement, brand, categories — and at 43 + 90 + 49 = 182px
   it was holding nearly a fifth of a laptop screen before a single product was
   visible, which is what "khub boro" was describing.

   The three bars stay, because each earns its place: delivery charges up front,
   the mark, and the categories a shopper came for. They are simply cut to the
   height the type actually needs — 32 + 66 + 42 = 140px — and the condensed
   state that already existed is made worth having: past the fold the shop keeps
   only what a shopper still needs to navigate, at 94px.
   -------------------------------------------------------------------------- */
body.ecb-v10 .ecb-v10-announcement {
	min-height: 32px;
	padding-block: 5px;
	font-size: 11px;
	letter-spacing: .14em;
}

body.ecb-v10 .ecb-v10-headmain { max-height: 66px; }
body.ecb-v10 .ecb-v10-headmain__inner { min-height: 66px; }
body.ecb-v10 .ecb-v10-brand > img,
body.ecb-v10 .ecb-v10-brand > img.ecb-v10-brand__logo { height: 38px; }

body.ecb-v10 .ecb-v10-catnav > .ecb-v10-shell > ul { min-height: 42px; }

/* Condensed: the announcement has already gone (rule further up). The brand bar
   and the categories each give up a few more pixels, so what is left is a
   working navigation rather than a masthead following you down the page. */
body.ecb-v10 .ecb-v10-header.is-condensed .ecb-v10-headmain { max-height: 56px; }
body.ecb-v10 .ecb-v10-header.is-condensed .ecb-v10-headmain__inner { min-height: 56px; }
body.ecb-v10 .ecb-v10-header.is-condensed .ecb-v10-brand > img,
body.ecb-v10 .ecb-v10-header.is-condensed .ecb-v10-brand > img.ecb-v10-brand__logo { height: 32px; }
body.ecb-v10 .ecb-v10-header.is-condensed .ecb-v10-catnav > .ecb-v10-shell > ul { min-height: 38px; }
body.ecb-v10 .ecb-v10-header.is-condensed .ecb-v10-catnav > .ecb-v10-shell > ul > li > a { font-size: 11px; }

body.ecb-v10 .ecb-v10-catnav > .ecb-v10-shell > ul,
body.ecb-v10 .ecb-v10-headmain,
body.ecb-v10 .ecb-v10-headmain__inner,
body.ecb-v10 .ecb-v10-brand > img {
	transition: min-height 240ms var(--v10-ease), max-height 240ms var(--v10-ease), height 240ms var(--v10-ease);
}

@media (prefers-reduced-motion: reduce) {
	body.ecb-v10 .ecb-v10-catnav > .ecb-v10-shell > ul,
	body.ecb-v10 .ecb-v10-headmain,
	body.ecb-v10 .ecb-v10-headmain__inner,
	body.ecb-v10 .ecb-v10-brand > img { transition: none; }
}

@media (max-width: 1000px) {
	body.ecb-v10 .ecb-v10-headmain,
	body.ecb-v10 .ecb-v10-headmain__inner { max-height: 58px; min-height: 58px; }
	body.ecb-v10 .ecb-v10-brand > img,
	body.ecb-v10 .ecb-v10-brand > img.ecb-v10-brand__logo { height: 32px; }
	body.ecb-v10 .ecb-v10-announcement { min-height: 28px; font-size: 10px; }
}


/* --------------------------------------------------------------------------
   The header gets out of the way

   Condensing it was not enough: 95px of bar still followed every page down,
   which is what the owner was pointing at — the reference site's header simply
   leaves. So this one leaves too, on the way down, and comes back the moment
   you scroll up, from wherever you are. Reading gets the whole screen; wanting
   the menu gets the menu, without a trip to the top of the page.

   `transform` rather than `top`: a transform is composited, so this costs
   nothing on a phone and cannot reflow the page under the reader's thumb.
   -------------------------------------------------------------------------- */
body.ecb-v10 .ecb-v10-header {
	transition: transform 300ms var(--v10-ease);
	will-change: transform;
}

body.ecb-v10 .ecb-v10-header.is-away {
	transform: translateY(-100%);
}

/* The admin bar sits above the header and does not move, so the header only has
   to clear its own height, not the strip above it. */
.admin-bar.ecb-v10 .ecb-v10-header.is-away {
	transform: translateY(calc(-100% - 32px));
}

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


/* --------------------------------------------------------------------------
   The floor on small text, on a phone

   Swept the declared sizes rather than the rendered ones, because the smallest
   type on this shop is inside the narrow breakpoints and never appears on a
   desktop sweep. Three pieces of real information were between 8.5 and 9.5px on
   the screens where nearly every customer of this shop actually reads them.

   Raised to 10.5-11px, which is the floor for tracked uppercase. The announcement
   is restated last so it wins over the 719px rule above it: the delivery charge
   is the first fact a customer looks for, and it was the smallest thing on the
   page.
   -------------------------------------------------------------------------- */
@media (max-width: 719px) {
	body.ecb-v10 .ecb-v10-announcement { font-size: 10.5px; letter-spacing: .1em; }
}

@media (max-width: 519px) {
	body.ecb-v10 .ecb-v10-trust b { font-size: 11px; }
	body.ecb-v10 .ecb-v10-product__eyebrow { font-size: 10px; }
	body.ecb-v10 .ecb-v10-announcement { font-size: 10.5px; }
}

/* --------------------------------------------------------------------------
   Desktop: the brand bar leaves, the categories stay

   The reference category page, measured: its <header> is `position: relative`
   and scrolls off entirely, and exactly one element is sticky — a 46px strip of
   category links pinned at top: 0. Nothing else follows the page down.

   That is the right shape for a shop. Working through a category, the control
   you keep reaching for is the switch to another category; the logo, the account
   link and the cart are not what you are doing.

   HOW, AND WHY NOT THE OBVIOUS WAY

   Making the header static and the category bar `position: sticky` is the
   obvious build and it does not work: a sticky element can only stick within its
   own parent's box, and that parent is a 146px header. It scrolled away with it,
   measured at y = -561. (A `will-change: transform` on the header breaks sticky
   inside it too, for a different reason — it becomes a containing block.)

   So the header stays sticky and the two upper bars are collapsed to nothing
   once the page has moved. What remains pinned is the category strip alone,
   which is the same 39px result, with no DOM surgery and nothing to go wrong on
   a browser that treats sticky differently.

   Desktop only. On a phone the category strip is a scrolling rail and the menu,
   search and bag live in the brand bar, so there the whole header stays and
   keeps the hide-on-the-way-down behaviour above — taking the menu away on a
   phone leaves no way back to it.
   -------------------------------------------------------------------------- */
@media (min-width: 1000px) {
	/* The brand bar folds away rather than the header sliding off, so the
	   category strip is never carried out of view with it. */
	body.ecb-v10 .ecb-v10-header.is-condensed .ecb-v10-headmain {
		max-height: 0;
		opacity: 0;
		border-bottom-width: 0;
		pointer-events: none;
	}

	body.ecb-v10 .ecb-v10-header.is-condensed .ecb-v10-headmain__inner {
		min-height: 0;
	}

	/* Pinned over the catalogue, the strip needs an edge; sitting in the header
	   it does not. */
	body.ecb-v10 .ecb-v10-header.is-condensed .ecb-v10-catnav {
		box-shadow: 0 8px 22px rgba(23, 16, 13, .08);
	}

	/* Nothing left to hide: the header is already down to the strip, and sliding
	   that away too would leave the catalogue with no navigation at all. */
	/* Both of them: the admin-bar variant carries an extra class and therefore
	   beats a plain override, which is why the header kept sliding away for a
	   logged-in admin while a visitor saw the category bar stay. */
	body.ecb-v10 .ecb-v10-header.is-away,
	.admin-bar.ecb-v10 .ecb-v10-header.is-away { transform: none; }
}


/* --------------------------------------------------------------------------
   The order-tracking card, in the shop's own colours

   ECB Commerce Core sets each state's tone as a literal — `.ecb-card--ship`
   carries #4a1834 — so the tokens the light and dark sheets redefine never
   reach it. The result is the one page a customer opens after paying still
   wearing the old plum and pink, next to a navy site.

   Only the two brand-coloured states are repointed. Green for delivered, amber
   for waiting and red for stopped are not brand colours, they are meaning, and
   they stay.
   -------------------------------------------------------------------------- */
body.ecb-v10 .ecb-card {
	--tone: var(--v10-accent);
	--tone-soft: #E7EDFB;
}

body.ecb-v10 .ecb-card--check { --tone: var(--v10-accent); --tone-soft: #E7EDFB; }
body.ecb-v10 .ecb-card--ship  { --tone: var(--v10-accent); --tone-soft: #E7EDFB; }

/* On the dark sheet the pale wash is wrong twice over — too bright against the
   page, and the navy on it is the light-theme navy. Both come from the tokens. */
html.ecb-dc body.ecb-v10 .ecb-card,
html.ecb-dc body.ecb-v10 .ecb-card--check,
html.ecb-dc body.ecb-v10 .ecb-card--ship {
	--tone: var(--v10-accent-hi);
	--tone-soft: rgba(169, 198, 255, .14);
}


/* --------------------------------------------------------------------------
   Chat launcher and back-to-top

   Both live in the bottom-right corner, so they are laid out together: the
   launcher owns the corner, the back-to-top sits above it. On a phone they clear
   the sticky Buy bar on a product page.
   -------------------------------------------------------------------------- */
.ecb-chat {
	position: fixed;
	z-index: 9500;
	right: 20px;
	bottom: 20px;
	-webkit-tap-highlight-color: transparent;
}

.ecb-chat__launch {
	display: grid;
	place-items: center;
	width: 54px;
	height: 54px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: var(--v10-accent);
	color: #fff;
	cursor: pointer;
	touch-action: manipulation;
	box-shadow: 0 10px 28px rgba(10, 44, 150, .34);
	transition: transform 200ms var(--v10-ease), background-color 200ms var(--v10-ease);
}
@media (hover: hover) {
	.ecb-chat__launch:hover { transform: translateY(-2px); }
}
.ecb-chat__launch:active { transform: scale(.94); }
.ecb-chat__launch:focus-visible { outline: 3px solid var(--v10-accent-hi); outline-offset: 3px; }

/* One button, two glyphs: the bubble becomes a cross when the panel is open, so
   the control that opened it is the control that closes it. */
.ecb-chat__x { display: none; }
.ecb-chat.is-open .ecb-chat__bubble { display: none; }
.ecb-chat.is-open .ecb-chat__x { display: block; }

.ecb-chat__panel {
	position: absolute;
	right: 0;
	bottom: 68px;
	width: 268px;
	padding: 20px 18px 18px;
	border: 1px solid rgba(20, 16, 14, .1);
	border-radius: 14px;
	background: #fff;
	box-shadow: 0 18px 46px rgba(20, 16, 14, .18);
	opacity: 0;
	transform: translateY(8px) scale(.98);
	transform-origin: bottom right;
	transition: opacity 200ms var(--v10-ease), transform 200ms var(--v10-ease);
}
.ecb-chat.is-open .ecb-chat__panel { opacity: 1; transform: none; }

.ecb-chat__close {
	position: absolute;
	top: 8px;
	right: 10px;
	padding: 2px 6px;
	border: 0;
	background: none;
	color: #8B8178;
	font-size: 20px;
	line-height: 1;
	cursor: pointer;
}
@media (hover: hover) {
	.ecb-chat__close:hover { color: var(--v10-ink); }
}

.ecb-chat__title { margin: 0 0 3px; color: var(--v10-ink); font-size: 15px; font-weight: 600; }
.ecb-chat__sub   { margin: 0 0 15px; color: var(--v10-muted); font-size: 12.5px; }

.ecb-chat__options { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

.ecb-chat__opt {
	display: grid;
	place-items: center;
	gap: 7px;
	padding: 14px 8px;
	border: 1px solid rgba(20, 16, 14, .1);
	border-radius: 10px;
	color: var(--v10-ink);
	font-size: 12.5px;
	font-weight: 600;
	text-decoration: none;
	transition: transform 160ms var(--v10-ease), border-color 160ms var(--v10-ease);
}
@media (hover: hover) {
	.ecb-chat__opt:hover { transform: translateY(-2px); }
}
.ecb-chat__opt:active { transform: scale(.97); }
.ecb-chat__opt.is-messenger { background: #EEF4FF; }
@media (hover: hover) { .ecb-chat__opt.is-messenger:hover { border-color: #0084FF; } }
.ecb-chat__opt.is-messenger .ecb-chat__icon { color: #0084FF; }
.ecb-chat__opt.is-whatsapp { background: #ECFAF0; }
@media (hover: hover) { .ecb-chat__opt.is-whatsapp:hover { border-color: #25D366; } }
.ecb-chat__opt.is-whatsapp .ecb-chat__icon { color: #25D366; }
.ecb-chat__icon { display: block; line-height: 0; }

@media (max-width: 767px) {
	/* `env()` keeps the pair clear of the iPhone home indicator; it resolves to
	   0 everywhere else, so this is the same 14px on every other phone. */
	.ecb-chat { right: 14px; bottom: calc(14px + env(safe-area-inset-bottom, 0px)); }
	.ecb-chat__launch { width: 50px; height: 50px; }
	.ecb-chat__panel { width: min(268px, calc(100vw - 34px)); bottom: 62px; }

}

@media (prefers-reduced-motion: reduce) {
	.ecb-chat__launch,
	.ecb-chat__panel,
	.ecb-chat__opt { transition: none; }

}


/* --------------------------------------------------------------------------
   "Tell me when it's back"

   Sits where Add to bag would be on a product that has one, so the eye lands on
   an offer rather than on an absence.
   -------------------------------------------------------------------------- */
.ecb-restock {
	margin: 22px 0 6px;
	padding: 18px 20px;
	border: 1px solid var(--v10-line, #EDE4D8);
	border-radius: 6px;
	background: var(--v10-paper, #FBF8F4);
}
.ecb-restock__lead { margin: 0 0 14px; color: var(--v10-ink-soft); font-size: 14px; line-height: 1.6; }
.ecb-restock__lead strong { color: var(--v10-ink); font-size: 15px; }

.ecb-restock__form { display: grid; gap: 10px; }
.ecb-restock__form input {
	width: 100%;
	min-height: 46px;
	padding: 0 14px;
	border: 1px solid var(--v10-line, #EDE4D8);
	border-radius: 4px;
	background: var(--v10-page);
	color: var(--v10-ink);
	font-size: 14px;
}
.ecb-restock__form input::placeholder { color: var(--v10-muted); }
.ecb-restock__form .button {
	min-height: 46px;
	border: 0;
	border-radius: 4px;
	background: var(--v10-accent);
	color: #fff;
	font-size: 12.5px;
	font-weight: 600;
	letter-spacing: .1em;
	text-transform: uppercase;
	cursor: pointer;
}
.ecb-restock__form .button:hover { background: #072173; }

.ecb-restock__count { margin: 12px 0 0; color: var(--v10-muted); font-size: 12.5px; }
.ecb-restock__done {
	margin: 0;
	padding: 12px 14px;
	border-left: 3px solid #1F7A3C;
	background: rgba(31, 122, 60, .08);
	color: var(--v10-ink);
	font-size: 14px;
}

@media (min-width: 560px) {
	.ecb-restock__form { grid-template-columns: 1fr 1fr auto; }
	.ecb-restock__form .button { padding-inline: 22px; }
}


/* The date under each step of the order tracker. Small and quiet: the step name
   is the message, the time is the footnote that stops a customer having to ask
   "when was that". */
body.ecb-v10 .ecb-progress__when {
	display: block;
	margin-top: 4px;
	color: var(--v10-muted);
	font-size: 11px;
	line-height: 1.35;
}
body.ecb-v10 .ecb-progress__step.is-current .ecb-progress__when { color: var(--v10-ink-soft); }


/* --------------------------------------------------------------------------
   The announcement bar, rotating

   Each message sits in the same cell, one visible at a time. The one leaving
   rises and fades, the one arriving comes up from below — the movement is
   upward for both, so the bar reads as a reel turning rather than two things
   crossfading in place.

   The bar's own height is fixed by the tallest message, not by whichever one is
   showing, so the header never jumps as the text changes. That is the whole
   reason the items are stacked in a grid cell instead of swapped in flow.
   -------------------------------------------------------------------------- */
body.ecb-v10 .ecb-v10-announcement[data-ecb-rotator] {
	display: grid;
	place-items: center;
	overflow: hidden;
}

body.ecb-v10 .ecb-v10-ann__item {
	grid-area: 1 / 1;
	display: inline-flex;
	align-items: center;
	gap: 12px;
	opacity: 0;
	transform: translateY(9px);
	visibility: hidden;
	transition:
		opacity 420ms var(--v10-ease),
		transform 420ms var(--v10-ease),
		visibility 0s linear 420ms;
	white-space: nowrap;
}

body.ecb-v10 .ecb-v10-ann__item.is-active {
	opacity: 1;
	transform: none;
	visibility: visible;
	transition-delay: 0s, 0s, 0s;
}

/* Leaving upward, arriving from below: the class is removed before the next one
   is added, so this is the state the outgoing message passes through. */
body.ecb-v10 .ecb-v10-ann__item.is-leaving {
	opacity: 0;
	transform: translateY(-9px);
}

/* The strong tag inside a message is the part worth reading — the price, the
   place — and keeps the accent it had when the bar was one fixed line. */
body.ecb-v10 .ecb-v10-ann__item strong { color: var(--v10-accent-hi); font-weight: 500; }

@media (max-width: 719px) {
	/* A long message cannot be one line on a phone; let it wrap and let the bar
	   take the height it needs rather than clipping the sentence. */
	body.ecb-v10 .ecb-v10-ann__item { white-space: normal; text-align: center; gap: 7px; }
}

@media (prefers-reduced-motion: reduce) {
	body.ecb-v10 .ecb-v10-ann__item { transition: opacity 200ms linear; transform: none; }
	body.ecb-v10 .ecb-v10-ann__item.is-leaving { transform: none; }
}

/* --------------------------------------------------------------------------
   One back-to-top, not two

   The theme drew its own — a 46px dark square at right:22 bottom:22 — and the
   chat launcher took the same corner. Measured, they overlapped by a few pixels
   and rendered as a white circle sitting inside a black square: one control that
   looked like two, in both themes.

   The theme's is retired rather than restyled. Two controls doing one job is not
   a colour problem, and the one that stays is the one that can be positioned
   against the launcher it shares a corner with.
   -------------------------------------------------------------------------- */
.ecb-v10-backtop { display: none !important; }

/* --------------------------------------------------------------------------
   Back to top

   Quieter than the chat button, because it is the lesser errand: an outline
   circle on the page colour rather than a filled navy disc. It sits directly
   above the launcher and shares its right edge, so the two read as one stack in
   the corner instead of two things that happen to be near each other.
   -------------------------------------------------------------------------- */
.ecb-totop {
	position: fixed;
	z-index: 9400;
	right: 26px;                 /* centres the 42px circle over the 54px launcher */
	bottom: 86px;                /* launcher bottom 20 + its 54 + 12 of air */
	display: grid;
	place-items: center;
	width: 42px;
	height: 42px;
	padding: 0;
	border: 1px solid var(--v10-line, rgba(20, 16, 14, .14));
	border-radius: 50%;
	background: var(--v10-page);
	color: var(--v10-ink);
	cursor: pointer;
	touch-action: manipulation;
	-webkit-tap-highlight-color: transparent;
	box-shadow: 0 8px 22px rgba(20, 16, 14, .16);

	/* Arrives rather than appears: hidden state is scaled down and clear, so
	   un-hiding it grows the circle into place instead of blinking it on. */
	opacity: 0;
	transform: scale(.82);
	transition:
		opacity 220ms var(--v10-ease),
		transform 220ms var(--v10-ease),
		background-color 180ms var(--v10-ease),
		color 180ms var(--v10-ease);
}

.ecb-totop.is-shown { opacity: 1; transform: none; }

@media (hover: hover) {
	.ecb-totop:hover {
		background: var(--v10-accent);
		border-color: var(--v10-accent);
		color: #fff;
		transform: translateY(-2px);
	}
}

/* Touch gets its own answer: a press that dips, and releases. Without this a
   phone either shows nothing on tap or — with the rule above ungated — keeps
   the navy fill long after the finger has gone. */
.ecb-totop:active { transform: scale(.94); }
.ecb-totop:focus-visible { outline: 3px solid var(--v10-accent); outline-offset: 3px; }

/* `hidden` keeps it out of the tab order and the accessibility tree while it is
   not offered; the class above is what animates. */
.ecb-totop[hidden] { display: none; }

@media (max-width: 767px) {
	/* Lifts by the same amount as the launcher, so the 10px between them holds. */
	.ecb-totop { right: 20px; bottom: calc(74px + env(safe-area-inset-bottom, 0px)); width: 38px; height: 38px; }
}

/* --------------------------------------------------------------------------
   Above the Buy bar, and only while it is there

   A product page carries a sticky Buy bar on a phone, so both controls lift over
   it rather than sitting on the one button that takes the money. But the bar
   only appears once the page has been scrolled past the real Add to bag — it
   carries `.is-visible` for exactly that — so the lift is tied to the class
   rather than to being on a product page. Lifting unconditionally leaves the
   stack floating in the middle of nowhere on a product page that has not been
   scrolled yet.

   The sibling combinator works because all three are printed into the footer, in
   this order: stickybar, chat, back-to-top.

   The gap between the two stays 10px, the same as everywhere else. It was 4px
   here — arithmetic, not eyesight: chat bottom 82 + its 50 = 132, and the arrow
   started at 136.
   -------------------------------------------------------------------------- */
@media (max-width: 767px) {
	body.ecb-v10.single-product .ecb-stickybar.is-visible ~ .ecb-chat  { bottom: calc(82px  + env(safe-area-inset-bottom, 0px)); }
	body.ecb-v10.single-product .ecb-stickybar.is-visible ~ .ecb-totop { bottom: calc(142px + env(safe-area-inset-bottom, 0px)); }
}

@media (prefers-reduced-motion: reduce) {
	.ecb-totop { transition: none; transform: none; }
	.ecb-totop.is-shown { transform: none; }
	.ecb-totop:active { transform: none; }
	.ecb-chat__launch:active,
	.ecb-chat__opt:active { transform: none; }
}
