/* ==========================================================================
   Yazan (Astra Child) — WooCommerce components
   Implements Blueprint Parts 7 (cards), 8 (product page), 9 (collection),
   10 (cart), 15 (mobile) at the CSS level. Pairs with inc/woocommerce.php.
   Flat + hairlines is the luxury grammar — avoid drop shadows almost entirely.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Product cards (Part 7)
   -------------------------------------------------------------------------- */
.yazan ul.products li.product.yz-card {
	position: relative;
	text-align: left;
	box-shadow: none;
	background: transparent;
}

/* --------------------------------------------------------------------------
   Card elevation on hover — deliberately restrained, and deliberately on `translate:`.

   The card is what a shopper reads, compares and clicks; the product is the subject and the
   effect is not. So this is a straight lift and a soft cast shadow — no tilt, no rotation, no
   overshoot. The price never moves sideways under the pointer.

   ⚠️ `translate:`, NOT `transform:`. `.yz-reveal` (motion.css Part 7) already owns this element's
   reveal offset, and the two are independent CSS properties: writing this as `transform` would
   cancel the reveal's start position, so cards would pop in flat instead of rising. That channel
   split is the architectural rule documented in motion.css Part 2.

   `--mo-lift` scales from the store's motion-intensity setting, so "motion: off" flattens this
   to zero without a media query.
   -------------------------------------------------------------------------- */
@media (hover: hover) {
	.yazan ul.products li.product.yz-card {
		transition:
			translate var(--mo-med) var(--mo-ease-out),
			box-shadow var(--mo-med) var(--mo-ease-out);
	}

	.yazan ul.products li.product.yz-card:hover,
	.yazan ul.products li.product.yz-card:focus-within {
		translate: 0 calc(var(--mo-lift) * -1);
		box-shadow: 0 22px 48px rgba(0, 0, 0, 0.12);
	}
}

/* Media wrapper: consistent 4:5 ratio, single background store-wide. */
.yazan ul.products li.product.yz-card a img,
.yazan ul.products li.product.yz-card .yz-card__img--alt {
	aspect-ratio: 4 / 5;
	object-fit: cover;
	width: 100%;
	margin: 0;
	background: var(--yz-ivory);
}

/* Position the image link as the stacking context for hover crossfade + CTA bar.
   The aspect-ratio guarantees the media box reserves its 4:5 height even if an <img> ever
   fails to render — so the absolutely-positioned .yz-badges overlay never collapses/scatters. */
.yazan ul.products li.product.yz-card > a:first-of-type,
.yazan ul.products li.product.yz-card .woocommerce-LoopProduct-link {
	position: relative;
	display: block;
	overflow: hidden;
	aspect-ratio: 4 / 5;
	background: var(--yz-ivory);
}

/* Slow zoom — light moving across the stone (Part 9).
   Guard the pointer-driven zoom behind `@media (hover: hover)` so a tap on touch devices
   (which emulates :hover) can't leave the image stuck zoomed until the next tap. */
.yazan ul.products li.product.yz-card img { transition: transform 1.2s var(--mo-ease-out); }
@media (hover: hover) {
	.yazan ul.products li.product.yz-card:hover img { transform: scale(1.05); }
}

/* Crossfade to the second angle. Include `transform` in the transition so the alt image zooms in
   sync with the primary — otherwise this rule clobbers the inherited `transition: transform 1.2s`
   (transition is not additive) and the alt image snaps to scale(1.05) instantly on hover. */
.yz-card__img--alt {
	position: absolute; inset: 0;
	opacity: 0;
	transition: opacity var(--mo-med) var(--mo-ease-out),
	            transform 1.2s var(--mo-ease-out);
	pointer-events: none;
}
/* Keyboard focus reveals the alt angle on any device; pointer hover only where a real hover
   exists (no sticky crossfade after a tap). */
.yz-card:focus-within .yz-card__img--alt { opacity: 1; }
@media (hover: hover) {
	.yz-card:hover .yz-card__img--alt { opacity: 1; }
}

/* Subject line + title + price.
   Rhythm mirrors the reference card (compact, tight vertical gaps: vendor line → title →
   price), but the title keeps the brand's serif display face — the "balanced" direction. */
.yz-subject {
	display: block;
	margin: 13px 0 5px;
	font-family: var(--yz-font-body);
	font-size: 10.5px;
	font-weight: 500;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--yz-muted);
	line-height: 1.1;
}
.yazan ul.products li.product.yz-card .woocommerce-loop-product__title {
	font-family: var(--yz-font-display);
	font-weight: 500;
	font-size: 17px;
	line-height: 1.24;
	letter-spacing: 0.01em;
	margin: 0;
	padding: 0;
	color: var(--yz-ink);
	transition: color var(--mo-med) var(--mo-ease-out);
}
/* On card hover the title warms gently from ink to a restrained aged gold — a single, intentional
   on-brand accent, replacing Astra's global `a:hover` accent blue (--ast-global-color-1), which is
   off-brand (no blue in the palette) and read as the title "fading". The title is a link
   (.ast-loop-product__link) wrapping the <h2>, so we override the anchor at rest too. */
.yazan ul.products li.product.yz-card .ast-loop-product__link,
.yazan ul.products li.product.yz-card .ast-loop-product__link:hover,
.yazan ul.products li.product.yz-card .ast-loop-product__link:focus {
	color: inherit;
}
/* Aged gold — a darkened member of the brand's gold-sand (--yz-sand #CBB78F), which is too pale
   to read as title text on the light card. This deeper tone keeps the gold hue but stays legible
   and restrained (no shiny yellow). Keyboard focus warms the title on any device; pointer hover
   only where a real hover exists, so a tap never leaves the title stuck gold. */
.yazan ul.products li.product.yz-card:focus-within .woocommerce-loop-product__title {
	color: #9A7B3F;
}
@media (hover: hover) {
	.yazan ul.products li.product.yz-card:hover .woocommerce-loop-product__title {
		color: #9A7B3F;
	}
}
.yazan ul.products li.product.yz-card .price {
	display: block;
	margin-top: 6px;
	color: var(--yz-ink);
	font-family: var(--yz-font-body);
	font-size: 14px;
	font-weight: 400;
	letter-spacing: 0.01em;
}
.yazan ul.products li.product.yz-card .price del {
	color: var(--yz-muted);
	opacity: 1;
	margin-inline-start: 8px;
	font-size: 13px;
}
.yazan ul.products li.product.yz-card .price ins {
	text-decoration: none;
	font-weight: 500;
}

/* Badges (top-left overlay). */
.yz-badges {
	position: absolute;
	top: 12px; inset-inline-start: 12px;
	z-index: 2;
	display: flex;
	flex-direction: column;
	gap: 6px;
	pointer-events: none;
}
/* Every value here is a custom property with the built-in as its fallback, and that is the seam
   the dashboard writes through: yazan-core prints `:root{--yz-badge-radius:999px}` for whatever the
   owner changed in Product display → Badges and nothing at all for what they did not. A rule would
   have had to out-specify theme-burgundy.css to do the same job; a variable simply wins in both
   themes, and an unset one leaves the per-visitor Black⇄Burgundy switch untouched. */
.yz-badge {
	font-family: var(--yz-font-body);
	font-size: var(--yz-badge-size, 11px);
	text-transform: var(--yz-badge-transform, uppercase);
	letter-spacing: var(--yz-badge-tracking, 0.1em);
	padding: var(--yz-badge-pad-block, 5px) var(--yz-badge-pad-inline, 10px);
	border-radius: var(--yz-badge-radius, 0);
	line-height: 1;
	background: var(--yz-ink);
	color: var(--yz-ivory);
	/* The hairline is always in the box and transparent until a badge colours it, so turning a
	   border on does not grow the badge by two pixels and nudge the strip. */
	border: var(--yz-badge-border-width, 1px) solid transparent;
}
/* Hide Astra's built-in on-sale badge (ast-onsale-card) — our badge system replaces it,
   so only our "Offer" badge shows instead of a duplicate "Sale!" pill. */
body.yazan .ast-onsale-card,
body.yazan .ast-on-card-button.ast-onsale-card { display: none !important; }

/* Hide Astra's default "Out of stock" bar (ast-shop-product-out-of-stock) — our .yz-badge--sold
   prints for every out-of-stock product (see inc/woocommerce.php), so the bar is always a duplicate
   in a clashing off-brand style. The on-brand SOLD badge is the single source of truth for stock. */
body.yazan ul.products li.product .ast-shop-product-out-of-stock { display: none !important; }

.yz-badge--rare      { background: var(--yz-badge-rare-bg, var(--yz-agate)); color: var(--yz-badge-rare-fg, var(--yz-ivory)); border-color: var(--yz-badge-rare-border, transparent); }
/* Solid ink fill + ivory text so it stays legible over dark product photos; the silver hairline
   keeps it visually distinct from the other (fill-only) badges — which is why THIS one's border
   falls back to a visible colour and the others fall back to transparent. A transparent fill made
   it vanish over dark imagery — showing only the border as an empty box. */
.yz-badge--certified { background: var(--yz-badge-certified-bg, var(--yz-ink)); color: var(--yz-badge-certified-fg, var(--yz-ivory)); border-color: var(--yz-badge-certified-border, var(--yz-silver)); }
.yz-badge--limited   { background: var(--yz-badge-limited-bg, var(--yz-ink)); color: var(--yz-badge-limited-fg, var(--yz-ivory)); border-color: var(--yz-badge-limited-border, transparent); }
.yz-badge--sold      { background: var(--yz-badge-sold-bg, var(--yz-muted)); color: var(--yz-badge-sold-fg, var(--yz-ivory)); border-color: var(--yz-badge-sold-border, transparent); }
.yz-badge--sale      { background: var(--yz-badge-sale-bg, var(--yz-agate)); color: var(--yz-badge-sale-fg, var(--yz-ivory)); border-color: var(--yz-badge-sale-border, transparent); }

/* The two badge looks a custom property cannot carry, because neither is one value.

   A CORNER is two properties that must move together — releasing `inset-inline-start` as the end is
   set, or the strip stretches across the whole card. An OUTLINE is a fill swapped for a hairline,
   and the hairline has to follow whatever colour the owner gave the text, which `currentColor` does
   and a second variable would only duplicate. Both arrive as a body class from
   Yazan_Product_Display_Storefront::body_class().

   Written `html body.…` on purpose: theme-burgundy.css paints badges at `html[data-yz-theme] .yz-…`,
   and a plain `body.…` selector loses to it. */
/* The same strip on the ring's own page. NOT positioned: there is no photograph under it there —
   it sits in the summary column above the eyebrow, so it lays out in the flow and runs across
   rather than down. The badges themselves are byte-for-byte the card's, which is the point: a
   shopper arriving from a card should recognise what they clicked. */
.yz-badges--single {
	position: static;
	flex-direction: row;
	flex-wrap: wrap;
	align-items: center;
	margin-block-end: 10px;
	pointer-events: auto;
}

html body.yz-pd-badges-end .yz-badges:not(.yz-badges--single) {
	inset-inline-start: auto;
	inset-inline-end: 12px;
	align-items: flex-end;
}
html body.yz-pd-badges-outline .yz-badge {
	background: transparent;
	border-width: var(--yz-badge-border-width, 1px);
	/* No border colour chosen: the outline takes the text colour, which is the only colour an
	   outlined badge is known to have. A chosen one wins, per badge, in the rules below. */
	border-color: currentColor;
}
html body.yz-pd-badges-outline .yz-badge--rare      { border-color: var(--yz-badge-rare-border, currentColor); }
html body.yz-pd-badges-outline .yz-badge--certified { border-color: var(--yz-badge-certified-border, currentColor); }
html body.yz-pd-badges-outline .yz-badge--limited   { border-color: var(--yz-badge-limited-border, currentColor); }
html body.yz-pd-badges-outline .yz-badge--sold      { border-color: var(--yz-badge-sold-border, currentColor); }
html body.yz-pd-badges-outline .yz-badge--sale      { border-color: var(--yz-badge-sale-border, currentColor); }

/* Optional signature sheen sweep on rare cards only (motion Part 9). */
.yz-card--rare .woocommerce-LoopProduct-link::after,
.yz-card--rare > a:first-of-type::after {
	content: '';
	position: absolute; inset: 0;
	background: linear-gradient(105deg, transparent 40%, rgba(245, 241, 233, 0.18) 50%, transparent 60%);
	transform: translateX(-120%);
	pointer-events: none;
}
.yz-card--rare:hover .woocommerce-LoopProduct-link::after,
.yz-card--rare:hover > a:first-of-type::after {
	transition: transform 900ms var(--mo-ease-out);
	transform: translateX(120%);
}

/* Quick-add bar (Part 9 — "hover unlocks function").
   Restyle Astra's modern on-card trigger into the reference's full-width bar that RISES from the
   bottom of the media on hover. We STYLE Astra's trigger and never remove it: in modern shop style
   it is the only add-to-cart in the loop. The trigger <a> is a SIBLING of the image link inside
   .astra-shop-thumbnail-wrap (nested <a> is invalid, so the parser splits them) — which is why the
   wrap, not the link, is the positioning + clip context for the rising bar. */
.yazan ul.products li.product.yz-card .astra-shop-thumbnail-wrap {
	position: relative;
	overflow: hidden;
}
.yazan .yz-card .ast-on-card-button:not(.ast-onsale-card) {
	position: absolute;
	overflow: hidden;          /* clips the gold shimmer sweep (::before) to the bar */
	inset-inline: 0;
	bottom: 0;
	top: auto;                 /* cancel Astra's top:1em / inset-inline-end:1em icon pinning */
	inset-inline-end: auto;
	width: 100%;
	min-height: 0;
	margin: 0;
	padding: 13px 16px;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.55em;
	background: rgba(20, 18, 16, 0.92);
	color: var(--yz-ivory);
	border-top: 1px solid transparent;   /* gold hairline lifts in on button hover (below) */
	visibility: visible;       /* reveal is driven by transform, not opacity */
	opacity: 1;
	transform: translateY(100%);
	transition: transform var(--mo-med) var(--mo-ease-inout),
	            background var(--mo-fast) ease,
	            border-color var(--mo-fast) ease,
	            color var(--mo-fast) ease;
	z-index: 5;
}
/* Keyboard focus lifts the buy bar on any device. */
.yazan .yz-card:focus-within .ast-on-card-button:not(.ast-onsale-card) {
	transform: translateY(0);
	opacity: 1;
	visibility: visible;
}
/* Pointer hover lifts it only where a real hover exists (desktop) — so a tap on touch can't leave
   the bar stuck half-open. */
@media (hover: hover) {
	.yazan .yz-card:hover .ast-on-card-button:not(.ast-onsale-card) {
		transform: translateY(0);
		opacity: 1;
		visibility: visible;
	}
}
/* Touch devices have no hover, so the "rises on hover" bar would be permanently unreachable — and
   it IS the only add-to-cart in the modern loop. Show it at rest instead: a standing buy bar per
   card. (opacity/visibility are already 1 at the base rule; only the translate needs resetting.) */
@media (hover: none) {
	.yazan .yz-card .ast-on-card-button:not(.ast-onsale-card) {
		transform: translateY(0);
	}
}
/* Astra's hover-only tooltip becomes the bar's always-visible tracked-uppercase label. */
.yazan .ast-on-card-button:not(.ast-onsale-card) .ast-card-action-tooltip {
	position: static;
	margin: 0;
	padding: 0;
	background: transparent;
	color: inherit;
	border-radius: 0;
	visibility: visible;
	opacity: 1;
	font-family: var(--yz-font-body);
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	line-height: 1;
	white-space: nowrap;
}
.yazan .ast-on-card-button:not(.ast-onsale-card) .ast-card-action-tooltip::after { display: none; }
/* Strip Astra's circular icon chip → a small bag glyph sitting left of the label. */
.yazan .ast-on-card-button:not(.ast-onsale-card) .ahfb-svg-iconset {
	order: -1;
	width: auto;
	height: auto;
	background: transparent;
	border-radius: 0;
	box-shadow: none;
	opacity: 1;
	color: inherit;
}
.yazan .ast-on-card-button:not(.ast-onsale-card) .ahfb-svg-iconset svg { width: 15px; height: 15px; }
/* Button hover/focus: the whole bar flips to gold (gold-sand fill, ink text + glyph) — an
   unmistakable but still restrained gold moment that echoes the title's aged-gold hover, so the
   card shares one gold hover language. Ink-on-gold is high-contrast and reads clearly. */
.yazan .ast-on-card-button:not(.ast-onsale-card):hover,
.yazan .ast-on-card-button:not(.ast-onsale-card):focus {
	background: #9A7B3F;       /* aged gold — same tone as the title hover, deeper than gold-sand */
	color: var(--yz-ink);
	border-top-color: #7C6231;  /* darker gold edge */
}
.yazan .ast-on-card-button:not(.ast-onsale-card):hover .ahfb-svg-iconset,
.yazan .ast-on-card-button:not(.ast-onsale-card):focus .ahfb-svg-iconset { color: var(--yz-ink); }
/* The store-wide `.add_to_cart_button:hover` override (!important, further down) turns buttons into
   a transparent ghost with ink text — right on an ivory page, but this bar sits over the photograph,
   so the label vanished into the dark stone. Here the bar clears to the photograph with an ivory
   label; the shadow keeps it legible over a light stone. */
body.yazan .yz-card .ast-on-card-button:not(.ast-onsale-card):hover,
body.yazan .yz-card .ast-on-card-button:not(.ast-onsale-card):focus {
	background-color: transparent !important;
	border-color: transparent !important;
	border-top-color: rgba(245, 241, 233, 0.6) !important;
	color: var(--yz-ivory) !important;
	text-shadow: 0 1px 3px rgba(12, 11, 10, 0.75);
}
body.yazan .yz-card .ast-on-card-button:not(.ast-onsale-card):hover .ahfb-svg-iconset,
body.yazan .yz-card .ast-on-card-button:not(.ast-onsale-card):focus .ahfb-svg-iconset { color: var(--yz-ivory); }

/* Hover motion: a single light sweep across the gold bar + a small lift of the bag glyph.
   The sweep is a diagonal highlight that starts off-screen and glides across once (not looping),
   matching the rare-card sheen grammar. Text/icon sit above it (relative + z-index). */
.yazan .ast-on-card-button:not(.ast-onsale-card)::before {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(105deg, transparent 42%, rgba(245, 241, 233, 0.55) 50%, transparent 58%);
	transform: translateX(-125%);
	pointer-events: none;
	z-index: 1;
}
.yazan .ast-on-card-button:not(.ast-onsale-card):hover::before,
.yazan .ast-on-card-button:not(.ast-onsale-card):focus::before {
	transition: transform 950ms var(--mo-ease-out);
	transform: translateX(125%);
}
.yazan .ast-on-card-button:not(.ast-onsale-card) .ast-card-action-tooltip,
.yazan .ast-on-card-button:not(.ast-onsale-card) .ahfb-svg-iconset {
	position: relative;
	inset: auto;              /* cancel Astra's `right:100%` tooltip offset — under position:relative
	                             it reactivates and would shove the label out of the (clipped) bar */
	z-index: 2;               /* keep label + glyph above the sweep */
}
.yazan .ast-on-card-button:not(.ast-onsale-card) .ahfb-svg-iconset {
	transition: transform var(--mo-med) var(--mo-ease-out);
}
.yazan .ast-on-card-button:not(.ast-onsale-card):hover .ahfb-svg-iconset,
.yazan .ast-on-card-button:not(.ast-onsale-card):focus .ahfb-svg-iconset {
	transform: translateY(-2px);   /* small bag lift */
}

/* --------------------------------------------------------------------------
   Collection / shop grid (Part 9) — 3 cols desktop reads more premium
   -------------------------------------------------------------------------- */
@media (min-width: 993px) {
	.yazan.woocommerce ul.products.columns-3,
	.yazan.woocommerce ul.products.columns-4 {
		gap: 32px;
	}
}

/* ==========================================================================
   SHOP FILTER SIDEBAR + TOOLBAR (commafootball-style two-column shop)
   ========================================================================== */

/* Store container fit: kill the boxed white-card feel + wasted top gap on product archives,
   and give the content the full page-width gutters the reference uses. */
.yazan.post-type-archive-product .ast-woocommerce-container,
.yazan.tax-product_cat .ast-woocommerce-container {
	background: transparent;
	padding: 0 0 36px;   /* pull the whole store block up under the sticky header */
}
.yazan.post-type-archive-product #content .ast-container,
.yazan.tax-product_cat #content .ast-container {
	max-width: 100%;   /* fill the full page width (was capped at 1360px) */
	padding-inline: clamp(16px, 3vw, 48px);
}

/* Left-aligned products header + intro lede (reference "All Products" band). */
.yazan.woocommerce .woocommerce-products-header,
.yazan.woocommerce-page .woocommerce-products-header {
	text-align: left; margin: 0 0 clamp(12px, 1.6vw, 18px); padding: 0;
}
.yazan .woocommerce-breadcrumb { margin: 0 0 8px; }
.yazan .woocommerce-products-header__title.page-title {
	font-family: var(--yz-font-display); font-weight: 600;
	font-size: clamp(28px, 3.4vw, 44px); line-height: 1.05; margin: 0;
}
.yazan .yz-shop-intro {
	color: var(--yz-muted); max-width: 62ch; margin: 6px 0 0;
	font-size: 0.98rem; line-height: 1.55;
}

/* ---- Elementor bands above and below the archive ----------------------
   Printed by yazan-core's ShopChromeRenderer on woocommerce_before/after_main_content, so they sit
   inside Astra's `#primary` and OUTSIDE `.yz-shop__results` — which is what keeps them alive through
   the instant-filter swap in interactions.js.

   Two rules only. Everything inside the band is designed in Elementor and styled by the widgets'
   own stylesheet, so anything more opinionated here would fight the operator's own layout.

   These live in woocommerce.css rather than the plugin's sections.css because this file loads
   whenever WooCommerce is active (inc/enqueue.php), while `yazan-homepage-sections` only loads when
   a yazan-* widget asks for it — and a band built from stock Elementor widgets would get no wrapper
   rules at all. */
.yazan .yz-shop-chrome { margin-block: 0; }
.yazan .yz-shop-chrome--before { margin-block-end: clamp(24px, 3vw, 48px); }
.yazan .yz-shop-chrome--after { margin-block-start: clamp(32px, 4vw, 64px); }

/* Shell: full-width toolbar stacked above the sidebar+grid row, so the filter toggle stays put. */
.yazan .yz-shop { display: block; }
.yazan .yz-shop__body {
	display: grid;
	grid-template-columns: 240px minmax(0, 1fr);
	gap: clamp(24px, 2.6vw, 40px);
	align-items: start;
}
.yazan .yz-shop__main { min-width: 0; }

/* Filters collapsed: hide only the filter form (groups); the toggle — the first child of the sidebar —
   stays visible. On desktop the body drops to a single column and the sidebar (now just the toggle)
   moves ABOVE the grid as a thin bar, so the sidebar reserves NO column and the grid spans full width
   at 5-up. The toggle keeps its top-left position; only the groups disappear. */
.yazan .yz-shop--nofilters .yz-filters { display: none; }
@media (min-width: 992px) {
	.yazan .yz-shop--nofilters .yz-shop__body { grid-template-columns: minmax(0, 1fr); }
	.yazan .yz-shop--nofilters .yz-shop__sidebar { order: -1; margin-bottom: 4px; }
	/* Closed filters: 5-up across the freed full width (open state stays 4-up). The boosted selector +
	   !important is required to outrank the base `repeat(4, …) !important` open-state rule. */
	.yazan.woocommerce .yz-shop--nofilters .yz-shop__main ul.products:not(.elementor-grid),
	.yazan.woocommerce-page .yz-shop--nofilters .yz-shop__main ul.products:not(.elementor-grid) {
		grid-template-columns: repeat(5, 1fr) !important; gap: 22px;
	}
}
@media (min-width: 1600px) {
	.yazan.woocommerce .yz-shop--nofilters .yz-shop__main ul.products:not(.elementor-grid),
	.yazan.woocommerce-page .yz-shop--nofilters .yz-shop__main ul.products:not(.elementor-grid) {
		grid-template-columns: repeat(6, 1fr) !important;
	}
}
@media (min-width: 2000px) {
	.yazan.woocommerce .yz-shop--nofilters .yz-shop__main ul.products:not(.elementor-grid),
	.yazan.woocommerce-page .yz-shop--nofilters .yz-shop__main ul.products:not(.elementor-grid) {
		grid-template-columns: repeat(7, 1fr) !important;
	}
}

/* AJAX results region — dim briefly while the next filtered page is fetched. */
.yazan .yz-shop__results { position: relative; transition: opacity 180ms ease; }
.yazan .yz-shop__results.is-loading { opacity: 0.45; pointer-events: none; }

/* ---- Toolbar (filter toggle · search · count · sort) -------------------- */
.yazan .yz-shop__toolbar {
	display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
	padding-bottom: 12px; margin-bottom: 16px;
	border-bottom: 1px solid var(--yz-hairline, rgba(20, 18, 16, 0.14));
}
/* Toggle = the sidebar's header (first child of .yz-shop__sidebar). Fixed 240px wide so it reads the
   same whether the sidebar is open (240px column) or collapsed (a thin left-aligned bar above the
   full-width grid). A chevron flips when the groups collapse. */
.yazan .yz-shop__filter-toggle {
	box-sizing: border-box; display: inline-flex; align-items: center; gap: 8px;
	width: 240px; max-width: 100%; margin-bottom: 16px;
	padding: 12px 14px; border: 1px solid var(--yz-ink); background: transparent;
	color: var(--yz-ink); font-family: var(--yz-font-body);
	font-size: 11.5px; font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase;
	cursor: pointer; line-height: 1; white-space: nowrap;
	transition: background 200ms var(--mo-ease-out, ease), color 200ms var(--mo-ease-out, ease);
}
.yazan .yz-shop__filter-toggle:hover { background: var(--yz-ink); color: var(--yz-ivory); }
.yazan .yz-shop__filter-icon { flex: 0 0 auto; }
.yazan .yz-shop__filter-toggle-label { margin-inline-end: auto; }
.yazan .yz-shop__filter-chevron { flex: 0 0 auto; transition: transform 240ms var(--mo-ease-out, ease); }
.yazan .yz-shop--nofilters .yz-shop__filter-chevron { transform: rotate(-90deg); }
.yazan .yz-shop__filter-count {
	display: inline-grid; place-items: center; min-width: 18px; height: 18px; padding: 0 5px;
	background: var(--yz-agate); color: var(--yz-ivory); font-size: 10px; border-radius: 9px;
}
.yazan .yz-shop__search {
	position: relative; flex: 1 1 240px; display: flex; align-items: center;
}
.yazan .yz-shop__search input[type="search"] {
	width: 100%; border: 1px solid var(--yz-hairline, rgba(20, 18, 16, 0.14));
	background: transparent; padding: 12px 44px 12px 16px; border-radius: 0;
	color: var(--yz-ink); font-size: 14px; font-family: var(--yz-font-body);
}
.yazan .yz-shop__search input[type="search"]:focus { outline: none; border-color: var(--yz-ink); }
.yazan .yz-shop__search-btn {
	position: absolute; inset-inline-end: 6px; top: 50%; transform: translateY(-50%);
	background: transparent; border: 0; color: var(--yz-muted); cursor: pointer;
	display: inline-flex; padding: 6px;
}
.yazan .yz-shop__search-btn:hover { color: var(--yz-ink); }
/* Live search dropdown. */
.yazan .yz-live-search {
	position: absolute; top: calc(100% + 6px); inset-inline: 0; z-index: 40;
	background: #fff; border: 1px solid var(--yz-hairline, rgba(20, 18, 16, 0.14));
	box-shadow: 0 24px 48px -24px rgba(20, 18, 16, 0.4);
	max-height: 68vh; overflow-y: auto;
}
.yazan .yz-live-search__state {
	padding: 16px 18px; color: var(--yz-muted); font-size: 13px; letter-spacing: 0.02em;
}
.yazan .yz-live-search__list { list-style: none; margin: 0; padding: 6px; }
.yazan .yz-live-search__item {
	display: flex; align-items: center; gap: 14px; padding: 10px 12px;
	text-decoration: none; color: var(--yz-ink); transition: background 160ms ease;
}
.yazan .yz-live-search__item:hover,
.yazan .yz-live-search__item:focus-visible { background: rgba(20, 18, 16, 0.045); }
.yazan .yz-live-search__thumb {
	flex: 0 0 auto; width: 52px; height: 52px; background-size: cover; background-position: center;
	background-color: var(--yz-ink); background-image: linear-gradient(160deg, #2a2320, var(--yz-ink));
	border: 1px solid var(--yz-hairline, rgba(20, 18, 16, 0.1));
}
.yazan .yz-live-search__meta { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.yazan .yz-live-search__title {
	font-family: var(--yz-font-display); font-size: 16px; font-weight: 600; line-height: 1.2;
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.yazan .yz-live-search__price { font-size: 13px; color: var(--yz-muted); }
.yazan .yz-live-search__price .amount { color: var(--yz-ink); }
.yazan .yz-live-search__price del { opacity: 0.55; margin-inline-end: 6px; }
.yazan .yz-live-search__all {
	display: block; text-align: center; padding: 13px; text-decoration: none;
	border-top: 1px solid var(--yz-hairline, rgba(20, 18, 16, 0.12));
	color: var(--yz-ink); font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
}
.yazan .yz-live-search__all:hover { background: var(--yz-ink); color: var(--yz-ivory); }

.yazan .yz-shop__tools { display: flex; align-items: center; gap: 14px; margin-inline-start: auto; }
.yazan .yz-shop__tools .woocommerce-result-count {
	margin: 0; color: var(--yz-muted); font-size: 12px; letter-spacing: 0.04em;
}
.yazan .yz-shop__tools .woocommerce-ordering { margin: 0; }
.yazan .yz-shop__tools select.orderby {
	border: 1px solid var(--yz-hairline, rgba(20, 18, 16, 0.14)); background: transparent;
	padding: 10px 30px 10px 14px; border-radius: 0; font-size: 12px; letter-spacing: 0.06em;
	text-transform: uppercase; color: var(--yz-ink); cursor: pointer;
}

/* ---- Sidebar ----------------------------------------------------------- */
/* Normal document flow: the whole sidebar scrolls WITH the page (the standard store pattern),
   so the bottom filters (Price) are always reachable and there is no internal scrollbar. */
.yazan .yz-shop__sidebar { align-self: start; }

/* With JS on, filtering is instant on change — the Apply button is redundant. */
.yz-js .yazan .yz-filters__actions { display: none; }

/* "View more / View less" toggle for long filter groups. */
.yazan .yz-opt--extra { display: none; }
.yazan .yz-filter-group.is-expanded .yz-opt--extra { display: block; }
.yazan .yz-filter-more {
	display: inline-flex; align-items: center; gap: 6px;
	margin: 2px 0 16px; padding: 0; background: transparent; border: 0; cursor: pointer;
	color: var(--yz-agate); font-family: var(--yz-font-body);
	font-size: 12px; letter-spacing: 0.04em;
}
.yazan .yz-filter-more:hover { text-decoration: underline; }
.yazan .yz-filter-more__hide { display: none; }
.yazan .yz-filter-group.is-expanded .yz-filter-more__show { display: none; }
.yazan .yz-filter-group.is-expanded .yz-filter-more__hide { display: inline; }

/* ---- Applied-filter chips (AliExpress/Alibaba-style) ------------------- */
.yazan .yz-applied {
	display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
	margin: 0 0 22px; padding-bottom: 4px;
}
.yazan .yz-applied__label {
	color: var(--yz-muted); font-size: 12px; letter-spacing: 0.08em;
	text-transform: uppercase; margin-inline-end: 2px;
}
.yazan .yz-applied__chip {
	display: inline-flex; align-items: center; gap: 8px;
	padding: 7px 10px 7px 13px; text-decoration: none;
	border: 1px solid var(--yz-ink); background: var(--yz-ink); color: var(--yz-ivory);
	font-size: 12px; letter-spacing: 0.03em; line-height: 1;
	transition: background 180ms ease, color 180ms ease;
}
.yazan .yz-applied__chip:hover,
.yazan .yz-applied__chip:focus-visible { background: transparent; color: var(--yz-ink); }
.yazan .yz-applied__x {
	display: inline-flex; align-items: center; justify-content: center;
	font-size: 15px; line-height: 1; opacity: 0.85;
}
.yazan .yz-applied__chip:hover .yz-applied__x { opacity: 1; }
.yazan .yz-applied__clear {
	margin-inline-start: 4px; color: var(--yz-agate); font-size: 12px;
	letter-spacing: 0.04em; text-decoration: none;
}
.yazan .yz-applied__clear:hover { text-decoration: underline; }
/* The single filter control is the toolbar toggle (Close filters ⇄ Filters); the sidebar's own
   "Filter" header would read as a second, redundant button — so it is removed. "Clear all" still
   lives in the applied-filter chip row above the grid. */
.yazan .yz-filters__head { display: none; }
.yazan .yz-filters__title {
	font-family: var(--yz-font-body); font-size: 12px; font-weight: 500;
	letter-spacing: 0.16em; text-transform: uppercase; color: var(--yz-ink);
}
.yazan .yz-filters__clear { font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--yz-muted); }
.yazan .yz-filters__clear:hover { color: var(--yz-agate); }

.yazan .yz-filter-group { border-bottom: 1px solid var(--yz-hairline, rgba(20, 18, 16, 0.12)); }
.yazan .yz-filter-group__head {
	display: flex; align-items: center; justify-content: space-between; width: 100%;
	padding: 16px 2px; background: transparent; border: 0; cursor: pointer;
	font-family: var(--yz-font-body); font-size: 13px; font-weight: 500;
	letter-spacing: 0.1em; text-transform: uppercase; color: var(--yz-ink);
}
.yazan .yz-filter-group__chevron { transition: transform 240ms var(--mo-ease-out, ease); flex: 0 0 auto; }
.yazan .yz-filter-group[aria-collapsed="true"] .yz-filter-group__chevron { transform: rotate(-90deg); }
.yazan .yz-filter-group__body { list-style: none; margin: 0; padding: 0 2px 18px; overflow: hidden; }
.yazan .yz-filter-group[aria-collapsed="true"] .yz-filter-group__body { display: none; }
.yazan .yz-filter-group__body li { margin: 0 0 11px; }

.yazan .yz-filter-option {
	display: flex; align-items: center; gap: 10px; cursor: pointer;
	font-size: 13.5px; color: var(--yz-ink); line-height: 1.2;
}
.yazan .yz-filter-option input[type="checkbox"] {
	appearance: none; -webkit-appearance: none; flex: 0 0 auto;
	width: 16px; height: 16px; margin: 0; border: 1px solid var(--yz-muted);
	background: transparent; border-radius: 0; cursor: pointer; position: relative;
	transition: background 180ms, border-color 180ms;
}
.yazan .yz-filter-option input[type="checkbox"]:checked { background: var(--yz-ink); border-color: var(--yz-ink); }
.yazan .yz-filter-option input[type="checkbox"]:checked::after {
	content: ""; position: absolute; left: 5px; top: 2px; width: 4px; height: 8px;
	border: solid var(--yz-ivory); border-width: 0 1.5px 1.5px 0; transform: rotate(45deg);
}
.yazan .yz-filter-option input[type="checkbox"]:focus-visible { outline: 2px solid var(--yz-sand); outline-offset: 2px; }
.yazan .yz-filter-option__name { flex: 1 1 auto; }
.yazan .yz-filter-option__n { color: var(--yz-muted); font-size: 11.5px; }

/* Price range inputs. */
.yazan .yz-price { padding-top: 4px; }
.yazan .yz-price__inputs { display: flex; align-items: center; gap: 10px; }
.yazan .yz-price__field {
	flex: 1 1 0; display: flex; align-items: center; gap: 4px;
	border: 1px solid var(--yz-hairline, rgba(20, 18, 16, 0.14)); padding: 8px 10px;
}
.yazan .yz-price__field:focus-within { border-color: var(--yz-ink); }
.yazan .yz-price__cur { color: var(--yz-muted); font-size: 12px; }
.yazan .yz-price__field input {
	width: 100%; border: 0; background: transparent; padding: 0; font-size: 13px;
	color: var(--yz-ink); -moz-appearance: textfield;
}
.yazan .yz-price__field input:focus { outline: none; }
.yazan .yz-price__field input::-webkit-outer-spin-button,
.yazan .yz-price__field input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.yazan .yz-price__dash { color: var(--yz-muted); }

.yazan .yz-filters__actions { margin-top: 22px; }
.yazan .yz-btn-solid {
	display: inline-block; width: 100%; text-align: center; cursor: pointer;
	padding: 13px 20px; border: 1px solid var(--yz-ink); background: var(--yz-ink);
	color: var(--yz-ivory); font-family: var(--yz-font-body);
	font-size: 11.5px; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase;
	transition: background 220ms var(--mo-ease-out, ease), color 220ms var(--mo-ease-out, ease);
}
.yazan .yz-btn-solid:hover { background: transparent; color: var(--yz-ink); }

/* Grid inside the shell — 4-up beside the sidebar (matches the reference density and the store's
   own columns-4 setting), regardless of Astra's column class. */
/* NOTE the `!important` + `.woocommerce`/`:not(.elementor-grid)` boost: Astra hard-codes the archive
   grid to `repeat(3, …)` via `.woocommerce ul.products:not(.elementor-grid)` (same specificity as a
   plain `.yz-shop__main ul.products`, so it wins on source order), and the store's own "columns-3"
   setting reinforces it. This override guarantees our column counts win at every breakpoint. */
.yazan.woocommerce .yz-shop__main ul.products:not(.elementor-grid),
.yazan.woocommerce-page .yz-shop__main ul.products:not(.elementor-grid) {
	display: grid; grid-template-columns: repeat(4, 1fr) !important; gap: 26px; margin: 0;
}
/* Keep 4-up beside the sidebar down to the tablet breakpoint (tighter gap so cards stay comfortable). */
@media (min-width: 992px) and (max-width: 1200px) {
	.yazan.woocommerce .yz-shop__main ul.products:not(.elementor-grid),
	.yazan.woocommerce-page .yz-shop__main ul.products:not(.elementor-grid) {
		grid-template-columns: repeat(4, 1fr) !important; gap: 18px;
	}
}
/* Wide screens: add columns so the now full-width grid stays dense instead of ballooning cards. */
@media (min-width: 1600px) {
	.yazan.woocommerce .yz-shop__main ul.products:not(.elementor-grid),
	.yazan.woocommerce-page .yz-shop__main ul.products:not(.elementor-grid) {
		grid-template-columns: repeat(5, 1fr) !important;
	}
}
@media (min-width: 2000px) {
	.yazan.woocommerce .yz-shop__main ul.products:not(.elementor-grid),
	.yazan.woocommerce-page .yz-shop__main ul.products:not(.elementor-grid) {
		grid-template-columns: repeat(6, 1fr) !important;
	}
}
.yazan .yz-shop__main ul.products::before,
.yazan .yz-shop__main ul.products::after { content: none; }
.yazan .yz-shop__main ul.products li.product {
	width: auto !important; margin: 0 !important; float: none !important;
}

/* ---- Responsive: sidebar (with the toggle at its top) stacks above the grid; the toggle stays
   visible and the filter form collapses/opens beneath it via the global .yz-filters rule ------ */
@media (max-width: 991px) {
	.yazan .yz-shop__body { grid-template-columns: 1fr; }
	.yazan .yz-shop__sidebar { position: static; order: -1; margin-bottom: 20px; }
	.yazan.woocommerce .yz-shop__main ul.products:not(.elementor-grid),
	.yazan.woocommerce-page .yz-shop__main ul.products:not(.elementor-grid) { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }
	.yazan .yz-shop__filter-toggle { width: 100%; margin-bottom: 0; }
	.yazan .yz-shop:not(.yz-shop--nofilters) .yz-shop__filter-toggle { margin-bottom: 16px; }
	.yazan .yz-shop__tools { flex-basis: 100%; margin-inline-start: 0; justify-content: space-between; }
}
@media (max-width: 480px) {
	.yazan.woocommerce .yz-shop__main ul.products:not(.elementor-grid),
	.yazan.woocommerce-page .yz-shop__main ul.products:not(.elementor-grid) { grid-template-columns: 1fr 1fr !important; gap: 14px; }
}

/* --------------------------------------------------------------------------
   Single product page (Part 8)
   -------------------------------------------------------------------------- */
.yazan.single-product .yz-eyebrow { margin-bottom: 8px; }

.yazan.single-product .product_title {
	font-family: var(--yz-font-display);
	font-weight: 600;
	font-size: clamp(32px, 3.5vw, 40px);
	line-height: 1.1;
}

/* Serial line — the "LICENSED" equivalent. */
.yz-serial {
	display: flex;
	align-items: center;
	gap: 8px;
	font-size: 13px;
	letter-spacing: 0.04em;
	color: var(--yz-muted);
	margin: 10px 0 18px;
	padding-block: 10px;
	border-top: 1px solid var(--yz-hairline);
	border-bottom: 1px solid var(--yz-hairline);
}
.yz-serial strong { color: var(--yz-ink); font-weight: 500; }
.yz-serial__icon { color: var(--yz-silver); }
.yz-serial a { color: var(--yz-agate); text-decoration: underline; text-underline-offset: 3px; }

/* Comma-style two-column with a STICKY info panel (Part 8).
   `.yz-product-top` (opened/closed via hooks in inc/woocommerce.php) wraps ONLY the gallery + the
   `.summary` — so `position: sticky` on the summary is now bounded to this row and stops before the
   full-width tabs/related below. This is the template wrapper the previous note said pure CSS lacked. */
.yazan.single-product .yz-product-top {
	display: block; /* mobile: stacked, gallery over summary */
}
@media (min-width: 993px) {
	.yazan.single-product .yz-product-top {
		display: grid;
		grid-template-columns: minmax(0, 58%) minmax(0, 42%);
		gap: clamp(32px, 4vw, 64px);
		align-items: start;
	}
	/* Gallery and summary are direct children of .yz-product-top; kill Astra/Woo float widths so the
	   grid owns the columns. */
	.yazan.single-product .yz-product-top .woocommerce-product-gallery,
	.yazan.single-product .yz-product-top .summary.entry-summary {
		width: auto !important;
		float: none !important;
		margin: 0 !important;
	}
	/* The sticky info column — rides down with the gallery, then releases at the row's end.
	   Offset clears the (optionally sticky) header; tune --yz-header-h if the header height changes. */
	.yazan.single-product .yz-product-top .summary.entry-summary {
		position: sticky;
		top: calc(var(--yz-header-h, 96px) + 24px);
		align-self: start;
	}
}

/* Size selector as button swatches rather than a dropdown (progressive — pairs with
   variation-swatches-woo; this styles native selects as a fallback). */
.yazan.single-product .single_add_to_cart_button { width: 100%; }

/* Product gallery (Part 8) — zoom + lightbox + slider are enabled in functions.php; this is the
   flat/hairline/sharp skin. Layout kept (main image + horizontal thumbs) so WooCommerce's flexslider
   is untouched. */
.yazan.single-product .woocommerce-product-gallery__image img {
	background: var(--yz-ivory);
}

/* ONE FRAME, EVERY SLIDE.
   Product photos arrive in mixed ratios (a 4:3 studio shot next to a tall 3:4 detail). FlexSlider
   sized the viewport per slide (smoothHeight — now off in inc/woocommerce.php), so each arrow click
   grew or shrank the gallery and shoved the thumbnails and the sticky summary around. Lock every
   main slide to a single ratio and let the photo fill it; the viewport then measures the same
   height for slide 1 and slide 4. Tunable per theme via --yz-gallery-ratio / --yz-gallery-fit
   (`contain` keeps the full photo with ivory letterboxing instead of a centred crop).
   `.zoomImg` is the enlarged copy Woo's zoom script injects — it must keep its own box. */
.yazan.single-product .woocommerce-product-gallery {
	--yz-gallery-ratio: 1 / 1;
	--yz-gallery-fit: cover;
	position: relative; /* Woo sets this too; restated so the arrow layer below always has an anchor */
}
.yazan.single-product .woocommerce-product-gallery__wrapper .woocommerce-product-gallery__image > a {
	display: block;
}
.yazan.single-product .woocommerce-product-gallery__wrapper .woocommerce-product-gallery__image img:not(.zoomImg) {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: var(--yz-gallery-ratio);
	object-fit: var(--yz-gallery-fit);
	object-position: center;
}

/* --------------------------------------------------------------------------
   PRE-INIT GALLERY = POST-INIT GALLERY (the product page's entire CLS)
   --------------------------------------------------------------------------
   Measured 2026-08-17 (tools/perf.sh, throttled mobile): CLS 0.441, and every point of it is
   `div.summary.entry-summary` shifting at ~7.6s and ~8.1s — the moments FlexSlider initialises.

   The mechanism: WooCommerce renders every gallery image as a stacked block, and Astra prints
   `.woocommerce-product-gallery{ opacity:1 !important }` which makes that stack VISIBLE. On this
   product that is four full-width squares. Seven throttled seconds later FlexSlider collapses them
   into one slide plus a thumbnail strip, the gallery loses ~3 viewport-widths of height, and
   everything below it leaps up. No amount of animation polish matters on a page doing that.

   The fix is to make the "before" layout the same shape as the "after": first image full-width,
   remaining images rendered AS the 4-up thumbnail row (matching data-columns="4" and the
   .flex-control-thumbs geometry below: 10px gaps, square crops). Then init changes pixels, not
   geometry.

   THE `>` COMBINATOR IS THE OFF-SWITCH, so this needs no JS and no timing: FlexSlider wraps the
   slides in an inserted `.flex-viewport` div, which breaks the direct-child match — every rule
   here stops applying at the exact moment the slider takes over. It also degrades well: with JS
   off, the visitor gets a main image over a neat thumbnail grid instead of a tower of duplicates.
   -------------------------------------------------------------------------- */
.yazan.single-product .woocommerce-product-gallery > .woocommerce-product-gallery__wrapper {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 12px 10px; /* row gap ≈ the thumbs' 12px margin-top; column gap = their 10px */
}
.yazan.single-product .woocommerce-product-gallery > .woocommerce-product-gallery__wrapper > .woocommerce-product-gallery__image:first-child {
	grid-column: 1 / -1;
}
.yazan.single-product .woocommerce-product-gallery > .woocommerce-product-gallery__wrapper > .woocommerce-product-gallery__image:not(:first-child) img {
	aspect-ratio: 1 / 1;
	object-fit: cover;
	width: 100%;
	height: auto;
}
/* WooCommerce's noscript-ish links inside non-first slides should not be tab stops twice. */
.yazan.single-product .woocommerce-product-gallery > .woocommerce-product-gallery__wrapper > .woocommerce-product-gallery__image:nth-child(n + 6) {
	display: none; /* the strip holds 4; a 7-image product must not add rows pre-init that vanish after */
}

/* MID-INIT GUARD — the half-second the rules above cannot see.
   FlexSlider's insertion of `.flex-viewport` is what switches the pre-init grid off, but under a
   throttled CPU the viewport exists UNPAINTED-SIZED for several frames before the sizing callback
   runs (measured: slides stack to 2,745px at ~8.1s, then collapse to 462px — both halves of the
   remaining CLS). The settled viewport always carries an inline `height:`, so "inserted but not
   yet sized" is expressible in pure CSS: while the viewport has no inline height, only the first
   slide participates in layout — the same shape as the pre-init grid's hero row, so the frame
   before and the frame after have the same geometry. Slide widths are computed by FlexSlider from
   the container, not from slide visibility, so hiding them during this window changes nothing it
   measures. */
.yazan.single-product .flex-viewport:not([style*="height"]) .woocommerce-product-gallery__image:not(:first-child) {
	display: none;
}
/* …and cap the track. FlexSlider writes the wrapper's inline `width: 600%` one paint BEFORE it
   writes the slides' inline widths, so for a few throttled frames the one visible slide stretches
   to fill a six-viewport-wide track (measured: a 2,100px-tall image in a 350px column — the whole
   0.296 shift). While the viewport is un-sized the track stays viewport-wide; the `!important` is
   required precisely because the 600% is an inline style, and the rule releases the instant the
   inline height lands. */
.yazan.single-product .flex-viewport:not([style*="height"]) .woocommerce-product-gallery__wrapper {
	width: 100% !important;
}
/* …and THE RELEASE INSTANT ITSELF, which both guards above are blind to by construction.
   Every rule in this block is keyed on `:not([style*="height"])`, so all of them stop applying in
   the very frame FlexSlider writes the viewport's inline height — a write it performs once on init
   unconditionally, independent of smoothHeight (already false, inc/woocommerce.php:702; that option
   only stops it RE-animating height on slide changes). Until that write lands `.flex-viewport` has
   no size of its own, so the write is a resize rather than a no-op, and on mobile — where the
   summary is stacked BELOW the gallery rather than beside it — the recompute drops and restores
   `div.summary.entry-summary`'s box across two throttled frames.
   Measured 2026-09-27 (tools/perf.sh mobile): CLS 0.3504, entirely two symmetric 0.1738 entries on
   entry-summary ~148ms apart, bracketing that single inline-style write; desktop scores 0.0004 for
   the same event because there the summary sits beside the gallery instead of under it.
   Giving the viewport the same locked ratio the slides already use means the box is the right size
   BEFORE FlexSlider measures it, so its `height:` write changes nothing. The inline height still
   wins afterwards (an explicit height suppresses aspect-ratio), so this cannot fight the slider —
   it only fills the gap ahead of it. */
.yazan.single-product .flex-viewport {
	aspect-ratio: var(--yz-gallery-ratio, 1 / 1);
}
/* Zoom / lightbox trigger (magnifier) — minimal ink disc, top inline-end. */
.yazan.single-product .woocommerce-product-gallery__trigger {
	top: 14px;
	inset-inline-end: 14px;
	background: rgba(20, 18, 16, 0.85);
	border-radius: 50%;
	transition: background var(--mo-fast) ease, transform var(--mo-fast) ease;
}
.yazan.single-product .woocommerce-product-gallery__trigger:hover {
	background: var(--yz-ink);
	transform: scale(1.06);
}
/* Thumbnails — hairline, muted until active/hover, sharp corners, even gaps.
   Mobile: a horizontal 4-up row below the main image. */
.yazan.single-product .flex-control-thumbs {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	margin: 12px 0 0;
	padding: 0;
	list-style: none;
}
.yazan.single-product .flex-control-thumbs li {
	margin: 0;
	flex: 0 0 calc((100% - 30px) / 4);
	max-width: calc((100% - 30px) / 4);
}
.yazan.single-product .flex-control-thumbs img {
	cursor: pointer;
	opacity: 0.5;
	aspect-ratio: 1 / 1;
	object-fit: cover;
	background: var(--yz-ivory);
	border: 1px solid transparent;
	transition: opacity var(--mo-fast) ease, border-color var(--mo-fast) ease;
}
.yazan.single-product .flex-control-thumbs img:hover { opacity: 0.85; }
.yazan.single-product .flex-control-thumbs img.flex-active { opacity: 1; border-color: var(--yz-ink); }

/* Thumbnails stay a HORIZONTAL strip below the main image — matching the Comma reference (its rail
   sits under the image, not beside it) and keeping WooCommerce's flexslider untouched and robust. */

/* Gallery carousel arrows (enabled via woocommerce_single_product_carousel_options in
   inc/woocommerce.php) — minimal ink discs pinned to the vertical middle of the main image. */
/* WHY THE ARROWS SAT ON THE BOTTOM EDGE: FlexSlider appends `ul.flex-direction-nav` as a SIBLING of
   `.flex-viewport`, inside `.woocommerce-product-gallery` — whose height is image + thumbnail strip.
   `top: 50%` on the anchors was therefore measured against the whole gallery, which lands at the
   image's bottom edge. The list is now an absolutely positioned layer that is exactly the main
   image's box (same width, same --yz-gallery-ratio the slides are locked to), so 50% of IT is the
   true vertical middle of the photo. The layer itself is click-through; only the discs catch the
   pointer. Selectors carry `.woocommerce-product-gallery` so they outrank Astra's own
   `.woocommerce div.product div.images …` skin. */
.yazan.single-product .woocommerce-product-gallery .flex-direction-nav {
	position: absolute;
	top: 0;
	inset-inline: 0;
	width: 100%;
	aspect-ratio: var(--yz-gallery-ratio);
	margin: 0;
	padding: 0;
	list-style: none;
	pointer-events: none;
	z-index: 3;
}
.yazan.single-product .woocommerce-product-gallery .flex-direction-nav li {
	margin: 0;
	padding: 0;
	list-style: none;
}
.yazan.single-product .woocommerce-product-gallery .flex-direction-nav a {
	pointer-events: auto;
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	width: 40px;
	height: 40px;
	margin: 0;
	padding: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(20, 18, 16, 0.85);
	color: var(--yz-ivory);
	border: 0;
	border-radius: 50%;
	box-shadow: none;
	opacity: 0;
	/* The anchors carry the literal words "Previous"/"Next" (WooCommerce's prevText/nextText) and no
	   stylesheet on the page hid them — that's the text bleeding out of the discs. Collapse the text
	   box to nothing; the chevron is a bordered pseudo-element with its own explicit size, so it is
	   unaffected by font-size 0. */
	font-size: 0;
	line-height: 0;
	text-indent: 0;
	overflow: hidden;
	transition: opacity var(--mo-fast) ease, background var(--mo-fast) ease;
}
.yazan.single-product .woocommerce-product-gallery:hover .flex-direction-nav a,
.yazan.single-product .woocommerce-product-gallery .flex-direction-nav a:focus-visible { opacity: 0.9; }
.yazan.single-product .woocommerce-product-gallery .flex-direction-nav a:hover { background: var(--yz-ink); opacity: 1; }
.yazan.single-product .woocommerce-product-gallery .flex-direction-nav a.flex-disabled { opacity: 0 !important; pointer-events: none; }
.yazan.single-product .woocommerce-product-gallery .flex-direction-nav .flex-prev { inset-inline-start: 14px; inset-inline-end: auto; }
.yazan.single-product .woocommerce-product-gallery .flex-direction-nav .flex-next { inset-inline-end: 14px; inset-inline-start: auto; }
/* Touch devices have no hover — keep the discs visible so the gallery is still navigable. */
@media (hover: none) {
	.yazan.single-product .woocommerce-product-gallery .flex-direction-nav a { opacity: 0.9; }
}
/* Replace flexslider's icon-font glyphs with clean chevrons that respect writing direction. */
.yazan.single-product .woocommerce-product-gallery .flex-direction-nav a::before,
.yazan.single-product .woocommerce-product-gallery .flex-direction-nav a::after {
	content: "";
	font-size: 0;
}
.yazan.single-product .woocommerce-product-gallery .flex-direction-nav a::after { display: none; }
.yazan.single-product .woocommerce-product-gallery .flex-direction-nav a::before {
	display: block;
	width: 10px;
	height: 10px;
	/* Physical top+left borders: rotate(-45deg) = points LEFT, rotate(135deg) = points RIGHT. */
	border: 2px solid currentColor;
	border-right: 0;
	border-bottom: 0;
}
.yazan.single-product .woocommerce-product-gallery .flex-direction-nav .flex-prev::before { transform: rotate(-45deg); margin-inline-start: 4px; }
.yazan.single-product .woocommerce-product-gallery .flex-direction-nav .flex-next::before { transform: rotate(135deg); margin-inline-end: 4px; }
/* RTL: "previous" sits on the right and must point right; "next" on the left points left. */
html[dir="rtl"] .yazan.single-product .woocommerce-product-gallery .flex-direction-nav .flex-prev::before { transform: rotate(135deg); }
html[dir="rtl"] .yazan.single-product .woocommerce-product-gallery .flex-direction-nav .flex-next::before { transform: rotate(-45deg); }

/* Price in the info column — sale strikes the original, live price warms to sand (Comma rhythm). */
.yazan.single-product .summary .price {
	font-family: var(--yz-font-display);
	font-size: clamp(24px, 2.4vw, 30px);
	color: var(--yz-ink);
	margin: 4px 0 18px;
}
.yazan.single-product .summary .price del {
	color: var(--yz-muted);
	opacity: 0.7;
	font-size: 0.7em;
	margin-inline-end: 10px;
	font-family: var(--yz-font-body);
}
.yazan.single-product .summary .price ins {
	text-decoration: none;
	color: var(--yz-agate);
}
/* "Save N%" pill inline with the sale price (Comma's SAVE 20% chip). */
.yazan.single-product .summary .price .yz-save {
	display: inline-block;
	vertical-align: middle;
	margin-inline-start: 10px;
	padding: 3px 10px;
	background: var(--yz-agate);
	color: #fff;
	font-family: var(--yz-font-body);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	border-radius: var(--yz-radius-pill);
}

/* Reassurance sub-line under the Add-to-Cart button (Comma's "Wait & Save…" line). */
.yazan.single-product .yz-atc-note {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 12px 0 0;
	font-size: 12.5px;
	letter-spacing: 0.02em;
	color: var(--yz-muted);
}
.yazan.single-product .yz-atc-note__sep { color: var(--yz-hairline); }

/* Muted payment / trust strip — product page, cart, checkout and the footer shortcode all share it,
   so it is scoped to `.yazan` rather than to a single template. Marks are inline SVG on currentColor,
   which keeps them legible in both the obsidian and burgundy token sets. */
.yazan .yz-pay {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 10px;
	margin: 16px 0 0;
	padding-top: 16px;
	border-top: 1px solid var(--yz-hairline);
	color: var(--yz-muted);
}
.yazan .yz-pay__lock { display: inline-flex; color: var(--yz-silver); }
.yazan .yz-pay__label {
	font-size: 12px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}
.yazan .yz-pay__marks {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 6px;
	margin-inline-start: auto;
}
.yazan .yz-pay__mark {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	min-height: 24px;
	padding: 4px 8px;
	border: 1px solid var(--yz-hairline);
	border-radius: 4px;
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.04em;
	color: var(--yz-text-2);
	white-space: nowrap;
}
.yazan .yz-pay__glyph {
	display: block;
	flex: none;
	/* Optical balance: the drawn glyphs sit a touch heavier than the 10px caption beside them. */
	opacity: 0.92;
}
/* The interlocking-circles mark is wider than it is tall — let it breathe less horizontally. */
.yazan .yz-pay__mark--mastercard { padding-inline: 6px; }
.yazan .yz-pay__name { line-height: 1; }

/* Cart / checkout / footer variants: the row is a footnote there, not a panel edge. */
.yazan .yz-pay--cart,
.yazan .yz-pay--checkout {
	margin-top: 14px;
	padding-top: 14px;
}
.yazan .yz-pay--footer {
	margin: 0;
	padding-top: 0;
	border-top: 0;
	justify-content: center;
}
.yazan .yz-pay--footer .yz-pay__marks { margin-inline-start: 0; }

@media (max-width: 600px) {
	.yazan .yz-pay__marks { margin-inline-start: 0; }
}

/* --------------------------------------------------------------------------
   Variation swatches — `cfvsw-*` (CartFlows Variation Swatches, the plugin actually installed).

   ⚠️ WHAT WAS HERE BEFORE STYLED A PLUGIN THIS SITE DOES NOT HAVE.
   The previous block targeted `.variable-items-wrapper` / `.variable-item` / `.variable-item.selected`
   — class names belonging to "Variation Swatches for WooCommerce" (GetWooPlugins). The installed
   plugin is CartFlows' variation-swatches-woo, which emits `.cfvsw-swatches-container`,
   `.cfvsw-swatches-option`, `.cfvsw-swatch-inner` and `.cfvsw-selected-swatch`. Not one of those
   selectors appeared anywhere in the theme's 23 stylesheets, so the swatch row on every variable
   product has been rendering with nothing but plugin defaults — on the single control a customer
   must use to choose what they are buying.

   Class names verified against variation-swatches-woo/inc/swatches.php:352 and
   assets/js/swatches.js:224-235.
   -------------------------------------------------------------------------- */
.yazan.single-product .cfvsw-swatches-container {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 6px 0 4px;
}

.yazan.single-product .cfvsw-swatches-option {
	min-width: 46px;
	min-height: 44px; /* a real touch target, not a 24px chip */
	padding: 0 14px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border: 1px solid var(--yz-border);
	background: var(--yz-surface);
	border-radius: 0; /* sharp corners read "jewellery case" — Blueprint Part 14 */
	box-shadow: none;
	font-size: 13px;
	letter-spacing: 0.04em;
	cursor: pointer;
	/* One declaration, all properties — `transition` is not additive, and a second rule naming
	   only `border-color` would silently drop the others. */
	transition:
		border-color var(--mo-fast) var(--mo-ease-out),
		color var(--mo-fast) var(--mo-ease-out),
		background-color var(--mo-fast) var(--mo-ease-out);
}

.yazan.single-product .cfvsw-swatches-option:hover {
	border-color: var(--yz-border-strong);
}

/* Selected. The plugin's own class, set in swatches.js — not a state this theme invents, so it
   stays correct through the AJAX variation swap. */
.yazan.single-product .cfvsw-swatches-option.cfvsw-selected-swatch {
	border-color: var(--yz-ink);
	color: var(--yz-ink);
	box-shadow: inset 0 0 0 1px var(--yz-ink); /* doubles the border without shifting layout */
}

/* Image swatches: the inner node carries the thumbnail, so the ring belongs on the outer box and
   the image must not be squeezed by the text padding. */
.yazan.single-product .cfvsw-swatches-option.cfvsw-image-option {
	padding: 0;
	overflow: hidden;
}
.yazan.single-product .cfvsw-swatch-inner {
	width: 100%;
	height: 100%;
	min-width: 44px;
	min-height: 44px;
	background-size: cover;
	background-position: center;
	display: block;
}

/* Unavailable combinations stay readable rather than invisible — a customer needs to see that a
   size exists and is sold out, not wonder whether it was ever offered. */
.yazan.single-product .cfvsw-swatches-option.cfvsw-swatches-disabled,
.yazan.single-product .cfvsw-swatches-option.cfvsw-swatches-out-of-stock {
	opacity: 0.4;
	cursor: not-allowed;
	position: relative;
}
.yazan.single-product .cfvsw-swatches-option.cfvsw-swatches-disabled::after,
.yazan.single-product .cfvsw-swatches-option.cfvsw-swatches-out-of-stock::after {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(to top left, transparent calc(50% - 1px), currentColor 50%, transparent calc(50% + 1px));
	opacity: 0.5;
}

.yazan.single-product .cfvsw-swatches-option:focus-visible {
	outline: 2px solid var(--yz-focus, var(--yz-agate));
	outline-offset: 2px;
}

/* The selected-value label the plugin injects next to the attribute name. */
.yazan.single-product .cfvsw-selected-label {
	color: var(--yz-muted);
	font-size: 12px;
	letter-spacing: 0.06em;
	margin-inline-start: 6px;
}

/* Product tabs → Comma-style accordion (built by initProductAccordion in interactions.js). */
.yazan.single-product .yz-accordion > ul.tabs,
.yazan.single-product .yz-accordion > ul.wc-tabs { display: none; }
.yazan.single-product .yz-accordion::before,
.yazan.single-product .yz-accordion::after { display: none; }
.yazan.single-product .yz-acc__head {
	width: 100%;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 20px 2px;
	margin: 0;
	background: none;
	border: 0;
	border-top: 1px solid var(--yz-border);
	color: var(--yz-ink);
	font-family: var(--yz-font-body);
	font-size: 15px;
	letter-spacing: 0.02em;
	text-align: start;
	cursor: pointer;
}
.yazan.single-product .yz-acc__icon {
	position: relative;
	flex: none;
	width: 12px;
	height: 12px;
}
.yazan.single-product .yz-acc__icon::before,
.yazan.single-product .yz-acc__icon::after {
	content: "";
	position: absolute;
	background: var(--yz-muted);
	transition: opacity var(--mo-fast) ease, transform var(--mo-fast) ease;
}
.yazan.single-product .yz-acc__icon::before { inset: 5px 0; height: 2px; }              /* horizontal bar */
.yazan.single-product .yz-acc__icon::after  { inset: 0 5px; width: 2px; }               /* vertical bar (→ + sign) */
.yazan.single-product .yz-acc__head[aria-expanded="true"] .yz-acc__icon::after { transform: scaleY(0); } /* becomes − */
.yazan.single-product .yz-acc__panel {
	padding: 4px 2px 24px;
	color: var(--yz-text-2);
	line-height: 1.7;
}
.yazan.single-product .yz-acc__panel[hidden] { display: none; }
.yazan.single-product .yz-acc__panel:last-of-type { border-bottom: 1px solid var(--yz-border); }

/* --------------------------------------------------------------------------
   Related / up-sell products — Comma-style horizontal slider (CSS scroll-snap,
   no Swiper dependency). WooCommerce prints these as `.related.products` /
   `.up-sells.products` OUTSIDE .yz-product-top, so they run full-width.
   -------------------------------------------------------------------------- */
.yazan.single-product .related.products > ul.products,
.yazan.single-product .up-sells.products > ul.products {
	display: grid;
	/* CRITICAL — Astra ships an EXPLICIT track list for every `ul.products`
	   (`repeat(4, 1fr)` desktop, `repeat(3, minmax(0,1fr))` ≤921px,
	   `repeat(2, minmax(0,1fr))` ≤544px). Inside this `overflow-x: auto` slider the
	   free space is negative, so those `1fr` tracks resolve to **0px** and the first
	   2–3 cards collapse on top of each other at the start edge (the overlapping
	   titles/prices seen on phones) while the rest render in the implicit tracks.
	   Killing the explicit template forces every card into `grid-auto-columns`. */
	grid-template-columns: none !important;
	grid-template-rows: none !important;
	grid-auto-flow: column;
	grid-auto-columns: minmax(220px, 1fr);
	gap: 20px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: thin;
	padding-bottom: 14px;
	margin: 0;
}
.yazan.single-product .related.products > ul.products > li.product,
.yazan.single-product .up-sells.products > ul.products > li.product {
	scroll-snap-align: start;
	width: auto !important;
	margin: 0 !important;
	float: none !important;
}
/* Desktop: show ~4 across, the rest scroll into view — the "slider" read. */
@media (min-width: 993px) {
	.yazan.single-product .related.products > ul.products,
	.yazan.single-product .up-sells.products > ul.products {
		grid-auto-columns: minmax(0, calc((100% - 60px) / 4));
	}
}

/* --------------------------------------------------------------------------
   Sticky mobile Add-to-Cart bar (Part 15) — highest-ROI mobile animation
   -------------------------------------------------------------------------- */
.yz-sticky-atc {
	position: fixed;
	inset-inline: 0;
	bottom: 0;
	z-index: 999;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 12px 16px;
	background: rgba(20, 18, 16, 0.98);
	color: var(--yz-ivory);
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	transform: translateY(100%);
	transition: transform var(--mo-med) var(--mo-ease-inout);
	border-top: 1px solid rgba(245, 241, 233, 0.12);
}
.yz-sticky-atc.is-visible { transform: translateY(0); }
.yz-sticky-atc[hidden] { display: none; }
.yz-sticky-atc__info { display: flex; flex-direction: column; min-width: 0; }
.yz-sticky-atc__name {
	font-size: 13px;
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.yz-sticky-atc__price { font-size: 13px; color: var(--yz-sand); }
.yz-sticky-atc__price del { opacity: 0.6; }
.yz-sticky-atc__btn {
	flex: none;
	background: var(--yz-ivory);
	color: var(--yz-ink);
	border: 0;
	padding: 12px 22px;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	font-size: 12px;
	font-weight: 500;
	cursor: pointer;
}
/* Only ever show on small screens. */
@media (min-width: 993px) { .yz-sticky-atc { display: none !important; } }

/* The bar is `position: fixed` across the FULL viewport bottom, so the concierge
   launcher pinned there at 1.25rem ends up underneath it — on a phone the
   launcher sits inside the black bar and swallows the product name. Step it up by
   the bar's height while it is on screen. `body.yz-atc-visible` is toggled by
   initStickyAtc() in interactions.js, in the same IntersectionObserver callback
   that reveals the bar. (The theme switcher used to be stacked above the launcher
   here; it is header-only now and never pinned to the viewport bottom.) */
@media (max-width: 992px) {
	.yz-chat {
		transition: inset-block-end var(--mo-med, 320ms) var(--mo-ease-inout, ease);
	}
	/* Reads the SAME custom property the launcher's own inset uses, so a bottom offset set in
	   AI Settings → Concierge survives here. Hardcoding 1.25rem again would silently revert a
	   custom offset on every product page on mobile — the highest-traffic template there is. */
	body.yz-atc-visible .yz-chat {
		inset-block-end: calc(var(--yz-chat-y, 1.25rem) + var(--yz-atc-h, 69px));
	}
	/* The promo "Get 10% off" launcher (promo.css) pins to the same bottom edge and was left
	   behind: on a phone it sat on the bar's product name and price (YZ-069, measured at
	   320-768). Same step-up, from its own offset property. */
	body.yz-atc-visible .yz-promo-launcher {
		inset-block-end: calc(var(--yz-promo-y, 18px) + var(--yz-atc-h, 69px));
	}
}

/* --------------------------------------------------------------------------
   Add-to-cart feedback label (motion Part 9)
   -------------------------------------------------------------------------- */
/* Pending add-to-cart.
   The button's OWN children are left in the DOM and hidden, rather than replaced — Astra's
   quick-add control holds the bag SVG and its tooltip in there, and the previous
   `textContent = 'Adding…'` approach deleted both permanently (see initCartFeedback in
   interactions.js). `.yz-adding__label` is appended alongside them and removed on completion. */
.add_to_cart_button.yz-adding,
.single_add_to_cart_button.yz-adding {
	opacity: 0.75;
	position: relative;
	pointer-events: none; /* a second click would queue a second add */
}

/* Hide the real contents without unmounting them. `visibility` rather than `display` so the
   button keeps its measured width and the row does not reflow mid-purchase. */
.add_to_cart_button.yz-adding > *:not(.yz-adding__label),
.single_add_to_cart_button.yz-adding > *:not(.yz-adding__label) {
	visibility: hidden;
}

.yz-adding__label {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 12px;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	white-space: nowrap;
}

/* The single-product button is a plain text node, so there is no child to hide — the label sits
   on top of it and the text underneath is faded out by the opacity above. */
.single_add_to_cart_button.yz-adding { color: transparent; }
.single_add_to_cart_button.yz-adding .yz-adding__label { color: var(--yz-ivory); }

/* --------------------------------------------------------------------------
   WooCommerce buttons — force the ink palette over Astra Global / Elementor Kit
   colors that the starter demo sets with high specificity. !important is used
   deliberately here: this is a store-wide brand override of an opinionated
   starter theme, exactly the case where it is justified.
   -------------------------------------------------------------------------- */
body.yazan .single_add_to_cart_button,
body.yazan .add_to_cart_button,
body.yazan a.button,
body.yazan button.button,
body.yazan input.button,
body.yazan .woocommerce a.button.alt,
body.yazan .woocommerce button.button.alt,
body.yazan .woocommerce #respond input#submit {
	background-color: var(--yz-ink) !important;
	border: 1px solid var(--yz-ink) !important;
	color: var(--yz-ivory) !important;
	border-radius: 0 !important;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	transition: background-color var(--mo-fast) ease, color var(--mo-fast) ease;
}
body.yazan .single_add_to_cart_button:hover,
body.yazan .add_to_cart_button:hover,
body.yazan a.button:hover,
body.yazan button.button:hover,
body.yazan input.button:hover,
body.yazan .woocommerce a.button.alt:hover,
body.yazan .woocommerce button.button.alt:hover,
body.yazan .woocommerce #respond input#submit:hover {
	background-color: transparent !important;
	color: var(--yz-ink) !important;
}

/* --------------------------------------------------------------------------
   Cart drawer (modern-cart) — Part 10. STYLE the plugin's slide-out, don't rebuild.
   Class map (from the plugin templates): .moderncart-panel (sliding panel) ·
   .moderncart-slide-out-header/-title/-close · .moderncart-slide-out-footer ·
   .moderncart-free-shipping-progress-bar > .moderncart-progress-bar · .moderncart-cart-item-* ·
   a.checkout-button. Conservative on-brand baseline (ivory ground, ink text, agate accent, sharp
   corners, hairlines) — spacing/exact shades to be tuned against a screenshot of the OPEN drawer.
   -------------------------------------------------------------------------- */
/* Floating cart button — override the plugin's blue (#705aef) with the brand ink so the
   bubble coordinates with the active theme (near-black in Black, deep burgundy in Burgundy),
   matching the drawer's ink checkout CTA. The count badge takes the agate accent so the item
   count stays legible on the dark button. */
body.yazan #moderncart-floating-cart button {
	background-color: var(--yz-ink) !important;
	color: var(--yz-ivory) !important;
	box-shadow: 0 6px 18px rgba(20, 18, 16, 0.28);
}
body.yazan #moderncart-floating-cart .moderncart-floating-cart-icon svg,
body.yazan #moderncart-floating-cart .moderncart-floating-cart-icon {
	color: var(--yz-ivory) !important;
}
body.yazan #moderncart-floating-cart .moderncart-floating-cart-count {
	background-color: var(--yz-agate) !important;
	color: var(--yz-ivory) !important;
}
body.yazan #moderncart-floating-cart .moderncart-floating-cart-button-notification {
	border-color: var(--yz-ink) !important;
}

/* The rest of the drawer — panel shell, header, item cards, free-shipping bar, discount field,
   totals, CTA and the trust row — now lives in assets/css/cart-drawer.css, which ports the
   reference slide-cart layout. It loads after this sheet and after theme-burgundy.css, and it
   leads every rule with the plugin's two ids so it actually wins; the class-only rules that used
   to sit here never did. See inc/cart-drawer.php for the matching structure hooks. */

/* Returns summary under "Add to cart" — printed by yazan-core (Yazan_Returns_Settings). */
.yz-returns-note {
	margin-block: 0.75rem 0;
	font-size: 0.8125rem;
	line-height: 1.5;
	letter-spacing: 0.01em;
	color: var(--yz-muted);
}
.yz-returns-note a {
	color: inherit;
	text-decoration: underline;
	text-underline-offset: 3px;
}
.yz-returns-note a:hover,
.yz-returns-note a:focus-visible {
	color: var(--yz-ink);
}
.yz-returns-note--final {
	padding-inline-start: 0.75rem;
	border-inline-start: 2px solid var(--yz-agate);
	color: var(--yz-ink);
}

/* Card category line + breadcrumb: text contrast (Agent 3, 2026-09-26; axe color-contrast).
   Astra renders the product card's category line at opacity .6 (#858585-ish on white, 3.6:1; on
   burgundy 1.24:1) and the breadcrumb #777 on the #F5F7F9 archive ground (4.16:1), under the 4.5:1 AA
   asks of 13-15px text. The theme's secondary-text token replaces them (--yz-muted: #6E6A63 ~5.4:1 on
   white; #9E8A8B on the burgundy ground). The breadcrumb rule skips burgundy, which themes it itself. */
body.yazan ul.products li.product .ast-woo-product-category {
	opacity: 1;
	color: var(--yz-muted);
}
html:not([data-yz-theme="burgundy"]) body.yazan .woocommerce-breadcrumb,
html:not([data-yz-theme="burgundy"]) body.yazan .woocommerce-breadcrumb a {
	color: var(--yz-muted);
}

/* In-stock line on the product page: Astra's #77A464 on #F5F7F9 is 2.68:1. A deeper green of the same
   hue (~6:1) keeps the cue and reads (Agent 3, 2026-09-26; axe color-contrast). Burgundy themes it itself. */
html:not([data-yz-theme="burgundy"]) body.yazan.single-product .stock.in-stock {
	color: #3F6B2E;
}

/* One-of-one piece already in the cart: same control, quieter, still clickable (opens the drawer). */
.yz-in-cart { cursor: pointer; }
.single_add_to_cart_button[data-yz-in-cart],
form.cart:has([data-yz-in-cart]) .single_add_to_cart_button { opacity: 0.85; }
.yz-in-cart + .added_to_cart { display: none; }
