
/* lubiwood-nl */
/* Lubiwood newsletter popup. Scoped under .lwnl-* to avoid theme collisions.
   .lwnl-card is the shared visual card — used standalone (auto mode, wrapped in
   .lwnl-root/.lwnl-dialog) and embedded (shortcode, wrapped in .lwnl-embed inside
   a WoodMart popup). Deliberately single-look (brand cream). */

/* ---- standalone overlay (auto mode) ---- */
.lwnl-root{
	position:fixed; inset:0; z-index:999999;
	display:flex; align-items:center; justify-content:center; padding:20px;
}
.lwnl-root[hidden]{ display:none; }
.lwnl-overlay{ position:absolute; inset:0; background:rgba(28,24,18,.55); backdrop-filter:blur(1px); }
.lwnl-dialog{
	position:relative; width:100%; max-width:400px; max-height:calc(100vh - 40px); overflow:auto;
	transform:translateY(14px) scale(.98); opacity:0;
	transition:transform .32s cubic-bezier(.2,.8,.25,1),opacity .32s ease;
}
.lwnl-root.lwnl-open .lwnl-dialog{ transform:none; opacity:1; }

/* ---- embedded (shortcode, inside a WoodMart popup) ---- */
.lwnl-embed{ width:100%; display:flex; justify-content:center; }
.lwnl-embed .lwnl-card{ box-shadow:none; max-width:400px; width:100%; }

/* ---- the card (shared) ---- */
.lwnl-card{
	--lwnl-green:#7ab38b; --lwnl-green-deep:#5e9772; --lwnl-green-ink:#3f6b50;
	--lwnl-tint:#E9F4ED; --lwnl-cream:#F7F3EC; --lwnl-line:#e7ded0;
	--lwnl-ink:#141210; --lwnl-text:#4a463f; --lwnl-muted:#8b8478;
	position:relative; background:var(--lwnl-cream); border-radius:16px; overflow:hidden;
	box-shadow:0 30px 70px -20px rgba(20,16,10,.55),0 0 0 1px rgba(20,16,10,.06);
	font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
	text-align:center;
}

/* Close button — hardened against theme button styles (WoodMart forces width/display),
   so it stays a small circle in the top-right instead of stretching across the top. */
.lwnl-card .lwnl-x{
	position:absolute !important; top:12px !important; right:12px !important; left:auto !important; bottom:auto !important;
	z-index:6; box-sizing:border-box;
	width:34px !important; height:34px !important; min-width:0 !important; max-width:none !important;
	margin:0 !important; padding:0 !important; float:none !important;
	display:flex !important; align-items:center; justify-content:center;
	border-radius:50% !important; background:rgba(255,255,255,.92); border:1px solid rgba(20,16,10,.08);
	color:#3a352d; font-size:18px; line-height:1; cursor:pointer; box-shadow:0 4px 12px -4px rgba(0,0,0,.35);
	text-transform:none; letter-spacing:normal;
}
.lwnl-card .lwnl-x:hover{ background:#fff; }

.lwnl-card .lwnl-media{ position:relative; aspect-ratio:5/3; overflow:hidden; background:#efe7d8; margin:0; }
.lwnl-media{ position:relative; aspect-ratio:5/3; overflow:hidden; background:#efe7d8; }
.lwnl-media img{ width:100%; height:100%; object-fit:cover; display:block; }
.lwnl-badge{
	position:absolute; top:12px; left:12px; background:var(--lwnl-green); color:#fff;
	font-size:12px; font-weight:800; letter-spacing:.02em; padding:7px 12px; border-radius:999px;
	box-shadow:0 6px 16px -4px rgba(63,107,80,.6);
}

.lwnl-body{ padding:22px 24px 24px; }
.lwnl-logo{ height:20px; width:auto; margin:2px auto 14px; display:block; opacity:.9; }
.lwnl-eyebrow{ font-size:11px; letter-spacing:.2em; text-transform:uppercase; color:var(--lwnl-green-ink); font-weight:700; margin:0; }
.lwnl-title{ font-size:25px; line-height:1.12; color:var(--lwnl-ink); margin:9px 0 10px; letter-spacing:-.02em; text-wrap:balance; font-weight:800; }
.lwnl-hl{ color:var(--lwnl-green-deep); }
.lwnl-sub{ font-size:14px; line-height:1.55; color:var(--lwnl-text); margin:0 0 18px; }

.lwnl-form{ display:flex; flex-direction:column; gap:10px; margin:0; }
.lwnl-input{
	height:46px; border-radius:10px; border:1px solid var(--lwnl-line); background:#fff;
	padding:0 14px; font-size:15px; color:var(--lwnl-ink); outline:none; width:100%;
	transition:border-color .15s,box-shadow .15s;
}
.lwnl-input:focus{ border-color:var(--lwnl-green); box-shadow:0 0 0 3px rgba(122,179,139,.25); }
.lwnl-input.lwnl-invalid{ border-color:#c8553d; box-shadow:0 0 0 3px rgba(200,85,61,.18); }
.lwnl-btn{
	height:46px; border-radius:10px; border:0; cursor:pointer; color:#fff;
	background:linear-gradient(180deg,var(--lwnl-green),var(--lwnl-green-deep));
	font-size:15px; font-weight:800; letter-spacing:.01em;
	box-shadow:0 10px 22px -8px rgba(63,107,80,.65); transition:transform .1s,filter .15s;
}
.lwnl-btn:hover{ filter:brightness(1.04); transform:translateY(-1px); }
.lwnl-btn[disabled]{ opacity:.6; cursor:default; transform:none; }
/* Force white label — WoodMart's theme button styles otherwise override .lwnl-btn's colour
   (same override that needed hardening on .lwnl-x); higher specificity + !important wins. */
.lwnl-card .lwnl-btn,
.lwnl-card .lwnl-btn:hover,
.lwnl-card .lwnl-btn:focus{ color:#fff !important; }
.lwnl-error{ color:#c8553d; font-size:12.5px; margin:2px 0 0; }

.lwnl-fine{ font-size:11.5px; color:var(--lwnl-muted); margin:12px 0 0; }

/* success */
.lwnl-check{ width:52px; height:52px; border-radius:50%; margin:0 auto 12px; background:var(--lwnl-tint);
	color:var(--lwnl-green-deep); display:flex; align-items:center; justify-content:center; font-size:26px;
	box-shadow:inset 0 0 0 1px rgba(122,179,139,.4); }
.lwnl-code{ margin:16px auto 6px; display:flex; align-items:stretch; max-width:280px;
	border:2px dashed var(--lwnl-green); border-radius:12px; overflow:hidden; background:#fff; }
.lwnl-code-value{ flex:1; font-family:"SFMono-Regular",Menlo,Consolas,monospace; font-weight:800;
	font-size:20px; letter-spacing:.12em; color:var(--lwnl-ink); display:flex; align-items:center; justify-content:center; padding:12px 8px; }
.lwnl-copy{ background:var(--lwnl-tint); color:var(--lwnl-green-ink); border:0; border-left:2px dashed var(--lwnl-green);
	font-weight:800; font-size:12px; letter-spacing:.08em; text-transform:uppercase; padding:0 16px; cursor:pointer; }
.lwnl-copy.lwnl-copied{ background:var(--lwnl-green); color:#fff; }
.lwnl-note{ font-size:13px; color:var(--lwnl-text); margin:12px 0 0; line-height:1.5; }
.lwnl-shop{ display:inline-block; margin-top:16px; color:var(--lwnl-green-deep); font-weight:700; font-size:14px;
	text-decoration:none; border-bottom:2px solid rgba(122,179,139,.4); padding-bottom:1px; }

@media (prefers-reduced-motion:reduce){
	.lwnl-dialog{ transition:opacity .2s ease; transform:none; }
}


/* lubiwood-bogo-coupon-line */
/* ------------------------------------------------------------------ *
 * BOGO coupon row: "Cosmic Owl Puzzle - S × 1          -19,99 €"
 *
 * bootstrap.php replaces the coupon cell's value with
 *
 *   <span class="lubiwood-bogo-line">
 *     <span class="lubiwood-bogo-line__deal">
 *       <span class="lubiwood-bogo-line__item">Cosmic Owl Puzzle - S × 1</span>
 *       <span class="lubiwood-bogo-line__amount">-19,99 €</span>
 *     </span>
 *   </span> [Remove]
 *
 * Two surfaces, two layouts.
 * ------------------------------------------------------------------ */

/* ---- Side cart (fkcart drawer) ------------------------------------
 * The row is `display:flex` with the "Coupon lch1 ×" chip on the left and
 * `.fkcart-summary-amount` on the right. With a product name in it the cell no
 * longer fits beside the chip, so it drops onto its own full-width line, laid
 * out name-left / amount-right, the name free to wrap.
 *
 * fkcart's template prints a hardcoded "-" text node in front of the value
 * (templates/cart/order-summary.php: `-<?php echo $coupon['value'] ?>`). It
 * has no element to target, so `font-size: 0` on the cell swallows it and the
 * children get their size back — the same trick bogo-cart-summary used for
 * ACFW's blurb. `:has()` keeps all of this off ordinary coupon rows, which
 * keep their minus sign; where :has() is unsupported the row simply renders as
 * today (name + amount inline after the "-"), so no regression. */
#fkcart-modal .fkcart-coupon-applied:has(.lubiwood-bogo-line) {
	flex-wrap: wrap;
}

#fkcart-modal .fkcart-coupon-applied .fkcart-summary-amount:has(.lubiwood-bogo-line) {
	flex: 1 0 100%;
	display: block;
	min-width: 0;
	margin-top: 4px;
	/* Beat the child theme's `#fkcart-modal .fkcart-summary-amount { white-space: nowrap }`. */
	white-space: normal;
	/* Swallows fkcart's hardcoded "-" text node. */
	font-size: 0;
}

#fkcart-modal .lubiwood-bogo-line {
	display: block;
	width: 100%;
	font-size: 13px;
	line-height: 1.35;
}

#fkcart-modal .lubiwood-bogo-line__deal {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	gap: 8px;
}

#fkcart-modal .lubiwood-bogo-line__deal + .lubiwood-bogo-line__deal {
	margin-top: 2px;
}

#fkcart-modal .lubiwood-bogo-line__item {
	flex: 1 1 auto;
	min-width: 0;
	text-align: left;
	white-space: normal;
	overflow-wrap: anywhere;
	font-weight: 400;
	color: var(--fkcart-primary-text-color, #222);
}

#fkcart-modal .lubiwood-bogo-line__amount {
	flex: 0 0 auto;
	white-space: nowrap;
	font-weight: 500;
	color: var(--fkcart-coupon-text-price-color, #5ba238);
}

/* ---- Checkout summary + cart page (WooCommerce totals table) --------
 * The totals table splits the row 50/50 (th "Coupon Lch1" / td value) and
 * FunnelKit's summary column is ~360px wide, so the value cell is ~180px:
 * "Cosmic Owl Puzzle - S × 1  -19,99 €  [Remove]" cannot sit on one line
 * there. Everything stays INSIDE the value cell (a flex `tr` inside a tbody
 * gets wrapped in an anonymous single cell and collapses into column 1 —
 * measured, not guessed), laid out as two right-aligned lines:
 *
 *     Coupon  Lch1        Cosmic Owl Puzzle - S × 1
 *                              -19,99 €  [Remove]
 *
 * The wrappers give up their boxes (`display: contents`) so the cell's flex
 * items are: name (own full line), amount, [Remove] — in DOM order, which
 * keeps "name / amount" pairs together when a repeating BOGO frees several
 * items. `:has()` scopes the cell rules to rows carrying our markup; without
 * it the cell still renders the same text, merely stacked. Scope note: the
 * summary lives in .wfacp_order_summary_container / .wfacp_mini_cart_reviews,
 * not #wfacp-e-form (learned the hard way in funnelkit-checkout-style). */
body .wfacp_order_summary_container tr.cart-discount > td:has(.lubiwood-bogo-line),
body .wfacp_mini_cart_reviews tr.cart-discount > td:has(.lubiwood-bogo-line),
body .cart_totals tr.cart-discount > td:has(.lubiwood-bogo-line),
body .shop_table tr.cart-discount > td:has(.lubiwood-bogo-line) {
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-end;
	align-items: baseline;
	column-gap: .45em;
	row-gap: 2px;
	text-align: right;
	vertical-align: middle;
}

body .wfacp_order_summary_container tr.cart-discount .lubiwood-bogo-line,
body .wfacp_mini_cart_reviews tr.cart-discount .lubiwood-bogo-line,
body .cart_totals tr.cart-discount .lubiwood-bogo-line,
body .shop_table tr.cart-discount .lubiwood-bogo-line,
body .wfacp_order_summary_container tr.cart-discount .lubiwood-bogo-line__deal,
body .wfacp_mini_cart_reviews tr.cart-discount .lubiwood-bogo-line__deal,
body .cart_totals tr.cart-discount .lubiwood-bogo-line__deal,
body .shop_table tr.cart-discount .lubiwood-bogo-line__deal {
	/* FunnelKit: `.wfacp_mini_cart_start_h .wfacp_order_summary_container
	   .wfacp_mini_cart_reviews tbody td span { display: inline-block }` (0,4,3)
	   outranks any sane selector here — verified against the matched rules. */
	display: contents !important;
}

/* The name: a full line of its own, right-aligned, wrapping if it must.
   FunnelKit paints every span in this cell coupon-green (via an #id-scoped
   rule, hence !important); a product name is not a saving, so it takes the
   label colour — funnelkit-checkout-style's ink token where it resolves, else
   the summary's own label grey — and only the amount stays green. */
body .wfacp_order_summary_container tr.cart-discount .lubiwood-bogo-line__item,
body .wfacp_mini_cart_reviews tr.cart-discount .lubiwood-bogo-line__item,
body .cart_totals tr.cart-discount .lubiwood-bogo-line__item,
body .shop_table tr.cart-discount .lubiwood-bogo-line__item {
	flex: 1 0 100%;
	min-width: 0;
	text-align: right;
	white-space: normal;
	overflow-wrap: anywhere;
	color: var(--lw-ink, #353030) !important;
}

body .wfacp_order_summary_container tr.cart-discount .lubiwood-bogo-line__amount,
body .wfacp_mini_cart_reviews tr.cart-discount .lubiwood-bogo-line__amount,
body .cart_totals tr.cart-discount .lubiwood-bogo-line__amount,
body .shop_table tr.cart-discount .lubiwood-bogo-line__amount {
	flex: 0 0 auto;
	white-space: nowrap;
}

/* [Remove]: after the amount, quiet, never on a line of its own. The theme
   positions/floats it (that is what stranded it before) — reset first. */
body .wfacp_order_summary_container tr.cart-discount > td:has(.lubiwood-bogo-line) .woocommerce-remove-coupon,
body .wfacp_mini_cart_reviews tr.cart-discount > td:has(.lubiwood-bogo-line) .woocommerce-remove-coupon,
body .cart_totals tr.cart-discount > td:has(.lubiwood-bogo-line) .woocommerce-remove-coupon,
body .shop_table tr.cart-discount > td:has(.lubiwood-bogo-line) .woocommerce-remove-coupon {
	flex: 0 0 auto;
	position: static !important;
	float: none !important;
	inset: auto !important;
	margin: 0 !important;
	display: inline-block;
	font-size: .82em;
	white-space: nowrap;
	opacity: .75;
}


/* lubiwood-bogo-cart-summary */
/* ------------------------------------------------------------------ *
 * Side-cart: Advanced Coupons deal breakdown.
 *
 * ACFW appends its per-item summary INTO FunnelKit's coupon amount cell:
 *
 *   <div class="fkcart-summary-amount">-<ul class="acfw-bogo-summary">…</ul></div>
 *
 * That cell is `display:flex; align-items:center` and (via the child theme's
 * price rule) `white-space: nowrap`, so the list sits on the same line as the
 * amount and the product name runs off the right edge of the panel.
 *
 * Fix: drop the cell onto its own full-width line and lay each deal out as a
 * name/price pair — name free to wrap, price never.
 *
 * The `-` in the markup above is hardcoded by FunnelKit's own template
 * (templates/cart/order-summary.php) and is meaningless once bootstrap.php has
 * removed the always-zero BOGO amount. It is a bare text node with no element
 * to target, so `font-size: 0` on the cell swallows it and the element children
 * get their size back. Normal (non-BOGO) coupon rows keep their minus sign —
 * they never carry one of these lists, so `:has()` leaves them alone.
 *
 * `:has()` is the load-bearing selector here. Where it is unsupported the row
 * simply renders as it does today: no regression, just no fix.
 * ------------------------------------------------------------------ */

#fkcart-modal .fkcart-coupon-applied:has(.acfw-bogo-summary),
#fkcart-modal .fkcart-coupon-applied:has(.acfw-add-products-summary),
#fkcart-modal .fkcart-coupon-applied:has(.acfw-shipping-overrides-summary) {
	flex-wrap: wrap;
}

#fkcart-modal .fkcart-coupon-applied .fkcart-summary-amount:has(.acfw-bogo-summary),
#fkcart-modal .fkcart-coupon-applied .fkcart-summary-amount:has(.acfw-add-products-summary),
#fkcart-modal .fkcart-coupon-applied .fkcart-summary-amount:has(.acfw-shipping-overrides-summary) {
	flex: 1 0 100%;
	display: block;
	min-width: 0;
	/* Beat the child theme's `#fkcart-modal .fkcart-summary-amount { white-space: nowrap }`. */
	white-space: normal;
	/* Swallows FunnelKit's hardcoded "-" text node. */
	font-size: 0;
}

#fkcart-modal .fkcart-coupon-applied .fkcart-summary-amount:has(.acfw-bogo-summary) > *,
#fkcart-modal .fkcart-coupon-applied .fkcart-summary-amount:has(.acfw-add-products-summary) > *,
#fkcart-modal .fkcart-coupon-applied .fkcart-summary-amount:has(.acfw-shipping-overrides-summary) > * {
	font-size: 14px;
}

#fkcart-modal .acfw-bogo-summary,
#fkcart-modal .acfw-add-products-summary,
#fkcart-modal .acfw-shipping-overrides-summary {
	/* ACFW hardcodes style="margin: 10px" on the <ul>. */
	margin: 6px 0 0 !important;
	padding: 0;
	width: 100%;
	list-style: none;
}

#fkcart-modal .acfw-bogo-summary li,
#fkcart-modal .acfw-add-products-summary li,
#fkcart-modal .acfw-shipping-overrides-summary li {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	gap: 8px;
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: 12px;
	line-height: 1.35;
	color: var(--fkcart-secondary-text-color, #6b6b6b);
}

#fkcart-modal .acfw-bogo-summary li + li,
#fkcart-modal .acfw-add-products-summary li + li,
#fkcart-modal .acfw-shipping-overrides-summary li + li {
	margin-top: 2px;
}

/* Product names are long and localized — let them wrap instead of overflowing. */
#fkcart-modal .acfw-bogo-summary .label,
#fkcart-modal .acfw-add-products-summary .label,
#fkcart-modal .acfw-shipping-overrides-summary .label {
	flex: 1 1 auto;
	min-width: 0;
	text-align: left;
	white-space: normal;
	overflow-wrap: anywhere;
}

#fkcart-modal .acfw-bogo-summary .discount,
#fkcart-modal .acfw-add-products-summary .discount,
#fkcart-modal .acfw-shipping-overrides-summary .discount {
	flex: 0 0 auto;
	white-space: nowrap;
	font-weight: 500;
	color: var(--fkcart-coupon-text-price-color, #5ba238);
}


/* lubiwood-sidecart-total */
/* Side-cart totals: say the discount once, on one line.
 *
 * fkcart's drawer already prints the coupon's amount itself:
 *     templates/cart/order-summary.php
 *     <div class="fkcart-summary-amount">-<?php echo $coupon['value'] ?></div>
 *
 * Advanced Coupons appends its own deal blurb into that same value —
 * <ul class="acfw-bogo-summary"> "Cosmic Owl Puzzle - S x 1: -19,99 €" — so the
 * row wrapped and the saving was stated twice:
 *
 *     Coupon  lch1
 *     19,99 €
 *     Cosmic Owl Puzzle - S x 1:        -19,99 €
 *     Total                              37,99 €
 *
 * The blurb is the redundant half: the coupon row states the amount, and the
 * line item it refers to is listed above with its own price. Hidden here so the
 * row collapses to "Coupon lch1   -19,99 €".
 *
 * NOTE: the checkout stylesheet carries the same rule, but it is enqueued ONLY on
 * the Aero checkout — the drawer lives on product and cart pages, so it never
 * received it. This file loads wherever the drawer can appear.
 */
.acfw-bogo-summary {
	display: none !important;
}

/* Keep fkcart's coupon row on one line once the blurb is gone. */
.fkcart-summary-line-item.fkcart-coupon-applied .fkcart-summary-amount {
	white-space: nowrap;
}

/* The Total row this feature adds: same weight as Subtotal, clearly the bottom line. */
.fkcart-summary-line-item.lubiwood-sidecart-total {
	margin-top: 2px;
}


/* lubiwood-funnelkit-cart-colors */
/**
 * Lubiwood — FunnelKit slide-cart free-shipping bar color.
 *
 * FunnelKit (Cart Pro) emits its cart colors as CSS custom properties on :root
 * (mirrored on #fkcart-modal). The free-shipping reward bar ships a vivid kelly
 * green (#2DA815) that clashes with the site's sage palette. Redefine the bar
 * variables to the brand sage so the fill (partial + full) and the active
 * truck-icon circle match the Checkout button. !important wins over FunnelKit's
 * own (non-important) var declarations regardless of load order.
 *
 * NOTE: FunnelKit Cart v1.9.1.2 paints the fill (.fkcart-progress-bar) from
 * `--fkcart-progressbar-active-color` (one word) — NOT the older hyphenated
 * `--fkcart-progress-bar-active-color`. Set BOTH so the recolor survives the
 * rename and any version skew between environments.
 *
 * Lives in the product-page mu-plugin so all product/cart-page tweaks stay
 * together, but is enqueued site-wide because the slide cart opens from any page.
 */
:root,
#fkcart-modal {
	--fkcart-progressbar-active-color: #7AB38A !important;          /* v1.9.x: the bar fill */
	--fkcart-progress-bar-active-color: #7AB38A !important;         /* older spelling / other elements */
	--fkcart-progress-bar-bg-color-active-icon: #7AB38A !important; /* active truck-icon circle */
}

/**
 * Free-shipping reward-bar message ("Spend €X more…" / "Congrats! You have
 * unlocked all the rewards"). FunnelKit ships it at 12px / weight 400 in the
 * faint secondary text colour, which is hard to read against the light cart
 * panel. Make it larger, bold, and use the primary (darker) text colour for
 * contrast. Targets BOTH reward-bar designs: design-1 `.fkcart-reward-message`
 * and design-2 `.fkcart-progress-title`. The `#fkcart-modal` scope already wins
 * on specificity; `!important` guards against the plugin's inline styles.
 */
#fkcart-modal .fkcart-reward-message,
#fkcart-modal .fkcart-progress-title {
	font-size: 15px !important;
	font-weight: 700 !important;
	color: var(--fkcart-primary-text-color) !important;
	margin-bottom: 12px !important; /* breathing room above the bar (default 2-6px) */
}

/**
 * The whole reward block sits cramped between the cart header and the first
 * product. FunnelKit's modern panel only pads 8px top/bottom — give it more
 * vertical room so the "Add items worth … to unlock FREE Shipping" message and
 * the bar/labels don't feel jammed.
 */
#fkcart-modal .fkcart-reward-panel.fkcart-progress-container,
#fkcart-modal .fkcart-progress-container {
	padding-top: 18px !important;
	padding-bottom: 18px !important;
}

/* Keep the inline milestone label (e.g. "free shipping") bold to match. */
#fkcart-modal .fkcart-reward-milestone {
	font-weight: 700 !important;
}

/**
 * Modern reward-bar milestone label under each icon — the "Free shipping" text
 * by the truck. FunnelKit ships it at 10px / weight 400, which is tiny and hard
 * to read (and cramped to two lines). Enlarge, bold, and widen so it reads
 * cleanly. `.active` state keeps the plugin's #000 colour for contrast.
 */
#fkcart-modal .fkcart-milestone .fkcart-label {
	font-size: 13px !important;
	line-height: 15px !important;
	font-weight: 700 !important;
	max-width: 96px !important;
}


/* lubiwood-geo */
/* Geo language-suggestion bar. Fixed to the top; shown only after JS reveals it.
   WoodMart green palette to match the store. Coexists with the free-shipping bar
   by stacking above it; final z-index / offset vs the sticky header is confirmed
   during manual verification (Task 10). */
.lw-geo-bar {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 100000;
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 10px 16px;
	background: #7ab38b;
	color: #ffffff;
	font-size: 15px;
	line-height: 1.3;
	box-shadow: 0 1px 6px rgba(0, 0, 0, 0.18);
	transform: translateY(-100%);
}
.lw-geo-bar[hidden] { display: none; }
.lw-geo-bar.lw-geo-in { transform: translateY(0); }

.lw-geo-bar__flag { font-size: 18px; line-height: 0; flex: 0 0 auto; display: flex; align-items: center; }
.lw-geo-bar__flagimg {
	display: block;
	height: 16px;
	width: auto;
	border-radius: 2px;
	box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.12);  /* subtle outline so light-edged flags read on the green bar */
}

.lw-geo-bar__msg {
	margin: 0;
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.lw-geo-bar__go {
	flex: 0 0 auto;
	display: inline-block;
	padding: 7px 14px;
	min-height: 40px;
	box-sizing: border-box;
	background: #ffffff;
	color: #2f5d3f;
	font-weight: 600;
	text-decoration: none;
	border-radius: 4px;
	line-height: 26px;
}
.lw-geo-bar__go:hover { background: #eef6f0; }

/* WoodMart themes every <button> (grey #f3f3f3 box, dark 13px text) with rules that
   out-rank a plain class selector, so the reset below uses !important to force the
   dismiss control back to the bar's intended look: a big WHITE × on the green bar,
   no box. Tap target stays 40×40 — only the glyph grows. */
.lw-geo-bar__dismiss,
.lw-geo-bar__dismiss:hover,
.lw-geo-bar__dismiss:focus {
	flex: 0 0 auto;
	display: flex;               /* flex-center so the enlarged glyph sits dead-centre, never clips */
	align-items: center;
	justify-content: center;
	width: 40px;                 /* button/tap target unchanged */
	height: 40px;
	min-height: 0;
	padding: 0;
	margin: 0;
	background: transparent !important;   /* kill WoodMart's grey button box */
	border: 0 !important;
	box-shadow: none !important;
	color: #ffffff !important;            /* white × to match the bar text */
	font-size: 44px !important;           /* bigger × GLYPH only; &times; fills ~half its em box */
	font-weight: 300 !important;
	line-height: 1 !important;
	cursor: pointer;
	opacity: 0.9;
}
.lw-geo-bar__dismiss:hover { opacity: 1; }

/* Page offset while the bar is open is set inline by JS from the bar's measured
   height (document.documentElement.style.paddingTop). The lw-geo-open class on
   <html> is now just a JS state marker — no declarations needed here. */

@media (max-width: 480px) {
	.lw-geo-bar { font-size: 14px; gap: 8px; padding: 8px 12px; }
}

@media (prefers-reduced-motion: no-preference) {
	.lw-geo-bar { transition: transform 0.22s ease-out; }
}


/* lubiwood-sato */
/* Side cart: cart icon before the drawer heading — FunnelKit's own cart_1 icon (the same one the
   drawer's Checkout button uses), applied as a mask so it takes the title's text colour in every
   language and needs no template override. */
.fkcart-title::before {
	content: '';
	display: inline-block;
	width: 22px;
	height: 22px;
	margin-inline-end: 10px;
	vertical-align: -5px;
	background-color: currentColor;
	-webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M2 2.71411C2 2.31972 2.31972 2 2.71411 2H3.34019C4.37842 2 4.97454 2.67566 5.31984 3.34917C5.55645 3.8107 5.72685 4.37375 5.86764 4.86133H20.5709C21.5186 4.86133 22.2035 5.7674 21.945 6.67914L19.809 14.2123C19.4606 15.4413 18.3384 16.2896 17.0609 16.2896H9.80665C8.51866 16.2896 7.39 15.4276 7.05095 14.185L6.13344 10.8225C6.12779 10.8073 6.12262 10.7917 6.11795 10.7758L4.64782 5.78023C4.59738 5.61449 4.55096 5.45386 4.50614 5.29878C4.36354 4.80529 4.23716 4.36794 4.04891 4.00075C3.82131 3.55681 3.61232 3.42822 3.34019 3.42822H2.71411C2.31972 3.42822 2 3.1085 2 2.71411ZM7.49529 10.3874L8.4288 13.8091C8.59832 14.4304 9.16266 14.8613 9.80665 14.8613H17.0609C17.6997 14.8613 18.2608 14.4372 18.435 13.8227L20.5709 6.28955H6.28975L7.49529 10.3874ZM12.0017 19.8577C12.0017 21.0408 11.0426 22 9.85941 22C8.67623 22 7.71708 21.0408 7.71708 19.8577C7.71708 18.6745 8.67623 17.7153 9.85941 17.7153C11.0426 17.7153 12.0017 18.6745 12.0017 19.8577ZM10.5735 19.8577C10.5735 19.4633 10.2538 19.1436 9.85941 19.1436C9.46502 19.1436 9.1453 19.4633 9.1453 19.8577C9.1453 20.2521 9.46502 20.5718 9.85941 20.5718C10.2538 20.5718 10.5735 20.2521 10.5735 19.8577ZM19.1429 19.8577C19.1429 21.0408 18.1837 22 17.0005 22C15.8173 22 14.8582 21.0408 14.8582 19.8577C14.8582 18.6745 15.8173 17.7153 17.0005 17.7153C18.1837 17.7153 19.1429 18.6745 19.1429 19.8577ZM17.7146 19.8577C17.7146 19.4633 17.3949 19.1436 17.0005 19.1436C16.6061 19.1436 16.2864 19.4633 16.2864 19.8577C16.2864 20.2521 16.6061 20.5718 17.0005 20.5718C17.3949 20.5718 17.7146 20.2521 17.7146 19.8577Z'/></svg>") no-repeat center / contain;
	mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M2 2.71411C2 2.31972 2.31972 2 2.71411 2H3.34019C4.37842 2 4.97454 2.67566 5.31984 3.34917C5.55645 3.8107 5.72685 4.37375 5.86764 4.86133H20.5709C21.5186 4.86133 22.2035 5.7674 21.945 6.67914L19.809 14.2123C19.4606 15.4413 18.3384 16.2896 17.0609 16.2896H9.80665C8.51866 16.2896 7.39 15.4276 7.05095 14.185L6.13344 10.8225C6.12779 10.8073 6.12262 10.7917 6.11795 10.7758L4.64782 5.78023C4.59738 5.61449 4.55096 5.45386 4.50614 5.29878C4.36354 4.80529 4.23716 4.36794 4.04891 4.00075C3.82131 3.55681 3.61232 3.42822 3.34019 3.42822H2.71411C2.31972 3.42822 2 3.1085 2 2.71411ZM7.49529 10.3874L8.4288 13.8091C8.59832 14.4304 9.16266 14.8613 9.80665 14.8613H17.0609C17.6997 14.8613 18.2608 14.4372 18.435 13.8227L20.5709 6.28955H6.28975L7.49529 10.3874ZM12.0017 19.8577C12.0017 21.0408 11.0426 22 9.85941 22C8.67623 22 7.71708 21.0408 7.71708 19.8577C7.71708 18.6745 8.67623 17.7153 9.85941 17.7153C11.0426 17.7153 12.0017 18.6745 12.0017 19.8577ZM10.5735 19.8577C10.5735 19.4633 10.2538 19.1436 9.85941 19.1436C9.46502 19.1436 9.1453 19.4633 9.1453 19.8577C9.1453 20.2521 9.46502 20.5718 9.85941 20.5718C10.2538 20.5718 10.5735 20.2521 10.5735 19.8577ZM19.1429 19.8577C19.1429 21.0408 18.1837 22 17.0005 22C15.8173 22 14.8582 21.0408 14.8582 19.8577C14.8582 18.6745 15.8173 17.7153 17.0005 17.7153C18.1837 17.7153 19.1429 18.6745 19.1429 19.8577ZM17.7146 19.8577C17.7146 19.4633 17.3949 19.1436 17.0005 19.1436C16.6061 19.1436 16.2864 19.4633 16.2864 19.8577C16.2864 20.2521 16.6061 20.5718 17.0005 20.5718C17.3949 20.5718 17.7146 20.2521 17.7146 19.8577Z'/></svg>") no-repeat center / contain;
}

/* Upsell tile button while the picker form is being fetched. */
.fkcart-select-product.lubiwood-sato-loading {
	opacity: 0.6;
	pointer-events: none;
}

/* Off-screen mount for the fetched variation form: it must stay in the DOM (WooCommerce's
   variation script and the picker act on it) but never be seen. */
.lubiwood-sato-mount {
	position: fixed;
	left: -9999px;
	top: 0;
	width: 1px;
	height: 1px;
	overflow: hidden;
}


/* lubiwood-swatch-prices */
/**
 * Lubiwood — size swatches with per-variation prices + meta + chooser (50+ friendly)
 * Uses --lwd-* tokens from product-page.css on body.lubiwood-product-page.
 */

.variations_form.lubiwood-swatch-prices-active {
	--lw-swatch-radius: var(--lwd-radius, 12px);
	--lw-swatch-brd: var(--lwd-brd, #e3e6e4);
	--lw-swatch-brd-active: var(--lwd-green, #3d6b47);
	--lw-swatch-bg: #fff;
	--lw-swatch-bg-active: var(--lwd-green-soft, #dceee0);
	--lw-swatch-text: var(--lwd-text, #1f2421);
	--lw-swatch-muted: var(--lwd-text-muted, #3a3f3c);
	--lw-swatch-accent: var(--lwd-green-dark, #2f5c38);
	--lw-swatch-gap: 10px;
	max-width: 100%;
}

/* Slim "Choose your size" header — heading on the left, size-guide link on the
   right (relocated up from WoodMart's default spot below the form). Replaces the
   old high-visibility green banner so the chooser breathes, Wentworth-style. The
   green highlight still flashes on the cards if Add to cart is tapped with no
   size chosen (.lubiwood-chooser-highlight). */
.variations_form.lubiwood-chooser-active .lubiwood-chooser-banner {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 4px 16px;
	margin: 0 0 12px;
}

.variations_form.lubiwood-chooser-active .lubiwood-chooser-banner--hidden {
	display: none;
}

.variations_form.lubiwood-chooser-active .lubiwood-chooser-banner__title {
	margin: 0;
	font-size: clamp(1.1875rem, 3.6vw, 1.375rem);
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: -0.01em;
	color: var(--lw-swatch-text);
}

/* Right-hand slot holding the relocated size-guide trigger. */
.variations_form.lubiwood-chooser-active .lubiwood-chooser-banner__guide {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	white-space: nowrap;
}

/* Size-guide trigger, moved inline into the header: a quiet underlined link with
   WoodMart's icon, turning green on hover — matches the reference "ⓘ Size guide". */
.variations_form.lubiwood-chooser-active .wd-sizeguide-btn.lubiwood-sizeguide-inline {
	margin: 0 !important;
	padding: 0 !important;
	border: 0 !important;
	background: none !important;
}

.variations_form.lubiwood-chooser-active .wd-sizeguide-btn.lubiwood-sizeguide-inline > a {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	margin: 0 !important;
	padding: 0 !important;
	border: 0 !important;
	background: none !important;
	box-shadow: none !important;
	transform: none !important;
	color: var(--lw-swatch-muted);
	font-size: clamp(0.9375rem, 2.8vw, 1rem);
	font-weight: 600;
	line-height: 1.3;
}

.variations_form.lubiwood-chooser-active .wd-sizeguide-btn.lubiwood-sizeguide-inline > a .wd-action-icon::before {
	color: currentColor !important;
	font-size: 1.15em !important;
}

.variations_form.lubiwood-chooser-active .wd-sizeguide-btn.lubiwood-sizeguide-inline > a .wd-action-text {
	text-decoration: underline;
	text-underline-offset: 2px;
}

.variations_form.lubiwood-chooser-active .wd-sizeguide-btn.lubiwood-sizeguide-inline > a:hover,
.variations_form.lubiwood-chooser-active .wd-sizeguide-btn.lubiwood-sizeguide-inline > a:focus-visible {
	color: var(--lw-swatch-accent);
}

/* Phones: the header runs out of room and the size-guide drops below the title,
   which looks lopsided left-aligned (worse when a longer-language title itself
   wraps). Centre it — title on its own centred line, size-guide centred beneath. */
@media (max-width: 479px) {
	.variations_form.lubiwood-chooser-active .lubiwood-chooser-banner {
		justify-content: center;
		text-align: center;
	}
	.variations_form.lubiwood-chooser-active .lubiwood-chooser-banner__title {
		flex-basis: 100%;
	}
	.variations_form.lubiwood-chooser-active .lubiwood-chooser-banner__guide {
		justify-content: center;
	}
}

/* Hide redundant Size rows — swatch cards (+ Step 1 banner) are self-explanatory.
   Applies on page load for every variable puzzle with WoodMart swatches, not only
   after JS adds .lubiwood-swatch-prices-active. Also hides the WoodMart product
   attributes table (Size | A3, A4… or Size | M ?) that sits above the form. */
body.lubiwood-swatch-chooser-page:has(.wd-swatches-product) table.shop_attributes,
body.lubiwood-swatch-chooser-page:has(.wd-swatches-product) .woocommerce-product-attributes-item--attribute_pa_size,
.variations_form:has(.wd-swatches-product) table.variations .label,
.variations_form:has(.wd-swatches-product) table.variations th.label,
.variations_form.lubiwood-swatch-prices-active table.variations .label,
.variations_form.lubiwood-swatch-prices-active table.variations th.label {
	display: none !important;
}

.variations_form:has(.wd-swatches-product) table.variations tr .value,
.variations_form.lubiwood-swatch-prices-active table.variations tr .value {
	padding-top: 0 !important;
}

/* Hide native dropdown — swatches replace it */
.variations_form:has(.wd-swatches-product) table.variations select,
.variations_form.lubiwood-swatch-prices-active table.variations select {
	display: none !important;
}

/* Highlight swatches when user taps disabled Add to cart */
.variations_form.lubiwood-chooser-highlight .wd-swatches-product {
	outline: 3px solid #3d6b47;
	outline-offset: 4px;
	border-radius: 12px;
}

/* Hide confusing “Clear” on chooser pages */
.variations_form.lubiwood-chooser-active .reset_variations,
.variations_form.lubiwood-chooser-active .wd-reset-var {
	display: none !important;
}

/* Hide duplicate price range above the form */
body.lubiwood-swatch-chooser-page:has(.lubiwood-chooser-active) .summary-inner > .price,
body.lubiwood-swatch-chooser-page:has(.lubiwood-chooser-active) .wd-single-price .price,
body.lubiwood-swatch-chooser-page:has(.lubiwood-chooser-active) .product-image-summary > .price {
	display: none !important;
}

.variations_form.lubiwood-swatch-prices-active table.variations td.value {
	width: 100%;
	max-width: 100%;
	padding-top: 0.25em;
}

.variations_form.lubiwood-swatch-prices-active .wd-swatches-single.wd-swatches-product {
	flex-direction: column;
	align-items: stretch;
	gap: var(--lw-swatch-gap);
	width: 100%;
	max-width: 100%;
}

/* Card grid: head (size + price) / meta row */
.variations_form.lubiwood-swatch-prices-active .wd-swatches-single > .wd-swatch.wd-text {
	position: relative; /* anchor for the absolutely-positioned "Most popular" badge */
	display: grid !important;
	grid-template-columns: minmax(0, 1fr) auto;
	grid-template-rows: auto auto;
	align-items: center;
	column-gap: 12px;
	row-gap: 6px;
	width: 100% !important;
	min-width: 0 !important;
	max-width: 100% !important;
	min-height: 0 !important;
	height: auto !important;
	margin: 0 !important;
	padding: 20px 16px 12px !important; /* extra top room so the struck price above the sale price is contained */
	border: 1.5px solid var(--lw-swatch-brd) !important;
	border-radius: var(--lw-swatch-radius) !important;
	background: var(--lw-swatch-bg) !important;
	color: var(--lw-swatch-text) !important;
	box-shadow: none !important;
	box-sizing: border-box;
	cursor: pointer;
	touch-action: manipulation;
	-webkit-tap-highlight-color: transparent;
	transition:
		border-color 0.2s ease,
		background-color 0.2s ease,
		box-shadow 0.2s ease;
}

.variations_form.lubiwood-swatch-prices-active .wd-swatches-single > .wd-swatch.wd-text:hover {
	border-color: #b8c4bb !important;
	background: #f8faf9 !important;
}

/* Selected — very obvious for 50+ */
.variations_form.lubiwood-swatch-prices-active .wd-swatches-single > .wd-swatch.wd-text.wd-active {
	border-color: var(--lw-swatch-brd-active) !important;
	border-width: 2px !important;
	background: var(--lw-swatch-bg-active) !important;
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--lwd-green, #3d6b47) 18%, transparent) !important;
	color: var(--lw-swatch-text) !important;
}

/* Card top row: size label (left) | badge + price (top-right) */
.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-head {
	grid-column: 1 / -1;
	grid-row: 1;
	display: flex;
	align-items: center; /* radio · pieces · price all share one vertical centre-line */
	justify-content: space-between;
	gap: 12px 8px; /* tighter column gap pulls the pieces count closer to the radio */
	min-width: 0;
	/* Push the head down on EVERY card so all cards share the taller "Most
	   popular" height (it needs this nudge to clear its top-left corner ribbon).
	   Applying it uniformly unifies card heights AND gives the struck price above
	   the sale price the same comfortable top margin on every card. */
	margin-top: 6px;
}

.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-label {
	flex: 1 1 auto;
	min-width: 0;
	align-self: center; /* pieces sits centred against the radio dot */
	padding-right: 4px;
	text-align: left; /* left-align the piece count + badge (WoodMart centers by default) */
}

/* Radio indicator at the head's leading edge — an empty ring by default, a filled
   green dot once the card is chosen (.wd-active). Purely visual: the real
   selection is the swatch itself. Stays put when the card expands (it lives in the
   head, above the revealed meta row). */
.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-radio {
	flex: 0 0 auto;
	align-self: center;
	width: 22px;
	height: 22px;
	margin-right: 4px;
	border: 2px solid #c2ccc4;
	border-radius: 50%;
	background: #fff;
	position: relative;
	box-sizing: border-box;
	transition: border-color 0.15s ease, background-color 0.15s ease;
}

.variations_form.lubiwood-swatch-prices-active .wd-swatch.wd-text.wd-active .lubiwood-swatch-radio {
	border-color: var(--lwd-green, #3d6b47);
}

.variations_form.lubiwood-swatch-prices-active .wd-swatch.wd-text.wd-active .lubiwood-swatch-radio::after {
	content: '';
	position: absolute;
	inset: 3px;
	border-radius: 50%;
	background: var(--lwd-green, #3d6b47);
}

/* Out-of-stock card: mute the ring so it reads unavailable. */
.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--oos .lubiwood-swatch-radio {
	border-color: #cfd4d0;
	background: #f1f2f1;
}

.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--oos.wd-active .lubiwood-swatch-radio::after {
	background: #9aa49d;
}

.variations_form.lubiwood-swatch-prices-active .wd-swatch.wd-text .wd-swatch-text {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.2em 0.35em;
	margin: 0 !important;
	padding: 0 !important;
	font-size: clamp(1.0625rem, 3.2vw, 1.25rem) !important;
	font-weight: 700 !important;
	line-height: 1.3 !important;
	color: inherit !important;
	text-transform: none;
	letter-spacing: 0;
}

.variations_form.lubiwood-swatch-prices-active .lubiwood-size-name {
	font-size: clamp(1.125rem, 3.6vw, 1.3125rem);
	font-weight: 700;
	text-transform: none;
	letter-spacing: 0;
	white-space: nowrap;
}

.variations_form.lubiwood-swatch-prices-active .lubiwood-size-code {
	font-size: clamp(1rem, 3vw, 1.125rem);
	font-weight: 600;
	color: var(--lw-swatch-muted);
	text-transform: uppercase;
	white-space: nowrap;
}

/* Top-right: badge above price */
.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-aside {
	flex: 0 0 auto;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	justify-content: flex-start;
	gap: 6px;
	max-width: 52%;
	text-align: right;
}

.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-badge {
	position: absolute; /* overlay in the exact top-left corner — out of flow, no added height */
	top: 0;
	left: 0;
	z-index: 2;
	display: inline-block;
	margin: 0;
	padding: 5px 11px;
	/* Corner tag: top-left nests in the card's rounded corner, bottom-right rounded. */
	border-radius: 11px 0 10px 0;
	background: var(--lwd-green, #3d6b47);
	color: #fff;
	font-size: 0.6875rem;
	font-weight: 700;
	line-height: 1.25;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	white-space: nowrap;
}

.variations_form.lubiwood-swatch-prices-active .wd-swatch.wd-text.wd-active .lubiwood-swatch-badge {
	background: var(--lwd-green-dark, #2f5c38);
}

/* Card heights are unified: the head's margin-top (above) is applied to every
   card, so a badged card ("Most popular" / "Sold out") and a plain card are the
   same height, and the corner ribbon on badged cards clears the leading radio. */

.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-price {
	flex: 0 0 auto;
	min-width: 0;
	margin: 0 !important;
	padding: 0 !important;
	text-align: right;
	line-height: 1.2;
}

.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-price .price {
	position: relative; /* anchor for the struck price floating above */
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	justify-content: flex-end;
	gap: 0;
	margin: 0 !important;
	font-size: clamp(1.125rem, 3.8vw, 1.3125rem) !important;
	line-height: 1.2 !important;
	color: var(--lw-swatch-text) !important;
}

/* On-sale: float the struck price ABOVE the sale price and out of flow, so the
   sale price is the price box's only in-flow line — it then sits level with the
   pieces count (head is centre-aligned). Non-sale prices are a single line
   already, so the regular price lands on the same centre-line automatically. */
.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-price .price del {
	position: absolute;
	right: 0;
	bottom: 100%;
	margin-bottom: 1px !important;
	font-size: clamp(0.8125rem, 2.2vw, 0.875rem) !important;
	font-weight: 500 !important;
	color: var(--lw-swatch-muted) !important;
	opacity: 1 !important;
	white-space: nowrap;
}

.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-price .price del .amount {
	color: inherit !important;
}

.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-price .price ins {
	order: 2;
	font-size: clamp(1rem, 3vw, 1.1875rem) !important;
	font-weight: 800 !important;
	text-decoration: none !important;
	color: var(--lw-swatch-accent) !important;
	background: none !important;
	letter-spacing: -0.02em;
}

/* Simple price (no sale): single amount is prominent */
.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-price .price > .amount,
.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-price .price > bdi {
	font-size: clamp(1rem, 3vw, 1.1875rem) !important;
	font-weight: 800 !important;
	color: var(--lw-swatch-accent) !important;
}

.variations_form.lubiwood-swatch-prices-active .wd-swatch.wd-text.wd-active .lubiwood-swatch-price .price ins {
	color: #3d5c43 !important;
}

/* Piece count — prominent line inside the label column */
.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-pieces {
	display: block;
	margin-top: 5px;
	font-size: 1rem;
	font-weight: 700;
	color: var(--lw-swatch-accent);
	letter-spacing: 0;
	line-height: 1.3;
	text-transform: none; /* "245 pieces" — lower-case, calmer (Wentworth-style) */
}

.variations_form.lubiwood-swatch-prices-active .wd-swatch.wd-text.wd-active .lubiwood-swatch-pieces {
	color: #1f4428;
}

/* ── Pieces-count headline layout ───────────────────────────────────────────
   When a swatch's variation has a defined puzzle pieces count, the JS adds
   `lubiwood-swatch--has-pieces`. The count becomes the headline; the size name
   (.wd-swatch-text) drops to a small muted eyebrow above it. Dimensions stay in
   the meta row. Placed after the base rules so source order wins (equal
   specificity for .wd-swatch-text). Swatches without the class are unaffected. */
.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--has-pieces .wd-swatch-text {
	font-size: clamp(0.8125rem, 2.4vw, 0.9375rem) !important;
	font-weight: 600 !important;
	color: var(--lw-swatch-muted) !important;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	line-height: 1.25 !important;
}

/* Nested size name/code inherit the eyebrow sizing instead of their own larger sizes. */
.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--has-pieces .lubiwood-size-name,
.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--has-pieces .lubiwood-size-code {
	font-size: inherit;
	font-weight: inherit;
	color: inherit;
	text-transform: inherit;
	letter-spacing: inherit;
}

/* In the pieces-headline layout the eyebrow shows only the role name (e.g. "Small");
   the parenthetical size code (e.g. "(A5)") is redundant with the dimensions row. */
.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--has-pieces .lubiwood-size-code {
	display: none;
}

/* The count is the headline: larger + bolder than the price so the piece count reads first. */
.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--has-pieces .lubiwood-swatch-pieces {
	margin-top: 0;
	font-size: clamp(1.0625rem, 3.1vw, 1.3125rem);
	font-weight: 800;
	line-height: 1.2;
	letter-spacing: -0.01em;
	white-space: nowrap; /* keep "100 pieces" on one line, level with the price */
}

/* Single-size products: nothing to choose, so the size-name eyebrow is hidden
   entirely (no "Single size" label). The piece count (if any), dimensions, and
   price still render. */
.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--single .wd-swatch-text {
	display: none;
}

/* Meta row: finished size (inside card). Collapsed by default — only the chosen
   card reveals it (see the .wd-active rule below), so cards stay to just the
   pieces + price until tapped. */
.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-meta {
	display: none;
	grid-column: 1 / -1;
	grid-row: 2;
	min-width: 0;
	font-size: clamp(0.875rem, 2.6vw, 0.9375rem);
	line-height: 1.45;
	color: var(--lw-swatch-muted);
	border-top: 1px solid rgba(31, 36, 33, 0.08);
	padding-top: 8px;
	margin-top: 2px;
}

/* Revealed on the selected card (and on the auto-selected single-size card). */
.variations_form.lubiwood-swatch-prices-active .wd-swatch.wd-text.wd-active .lubiwood-swatch-meta {
	display: block;
	border-top-color: rgba(95, 127, 102, 0.2);
	color: #4a5550;
}

.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-meta p {
	margin: 0 !important;
	padding: 0 !important;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5em 1em;
}

.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-meta p:empty {
	display: none;
}

/* Bottom meta row, left-aligned in order: SMALL - [icon] 36 × 25 cm */
.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-size {
	display: flex;
	align-items: center;
	justify-content: flex-start;
	gap: 6px;
	font-size: clamp(0.875rem, 2.6vw, 0.9375rem);
	line-height: 1.3;
}

.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-size__icon {
	flex: 0 0 auto;
	color: #7a8a80;
}

.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-size__name {
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var(--lw-swatch-muted);
}

.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-size__sep {
	color: var(--lw-swatch-muted);
}

.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-size__dims {
	font-weight: 700;
	color: #4a5550;
	white-space: nowrap;
}

/* Pieces-headline cards: the size name now lives in the bottom row, so hide the
   top eyebrow — the top holds just the piece count + price. */
.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--has-pieces .wd-swatch-text {
	display: none;
}

.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-desc {
	margin-top: 2px;
}

/* ── Out of stock ────────────────────────────────────────────────────────────
   The "Sold out" pill (below) carries the message, so the card stays legible and
   obviously tappable — it must be tapped to reveal the waitlist form. A grey wash
   + muted price signal unavailability, not a heavy fade.

   IMPORTANT: these selectors mirror the base/active swatch rules' structure
   (`.wd-swatches-single > .wd-swatch.wd-text[.wd-active]`) and add the OOS class,
   so they out-specify them. A plainer `.wd-swatch.lubiwood-swatch--oos` selector
   loses the cascade to the 5-class base rule (background var(--lw-swatch-bg)) and
   the 6-class active rule (green --lw-swatch-bg-active / --lwd-green border), which
   is why the card previously stayed white/green and only its text greyed. */
.variations_form.lubiwood-swatch-prices-active .wd-swatches-single > .wd-swatch.wd-text.lubiwood-swatch--oos {
	opacity: 1 !important;
	background: #f1f2f1 !important;
	border-color: #d4d8d5 !important;
}

/* Selected sold-out card: stay grey (not the green active tint) so a sold-out
   size always reads as unavailable, even when it is the selected card. The extra
   .wd-active makes this beat the active rule above it. */
.variations_form.lubiwood-swatch-prices-active .wd-swatches-single > .wd-swatch.wd-text.wd-active.lubiwood-swatch--oos {
	background: #f1f2f1 !important;
	border-color: #d4d8d5 !important;
}

/* Grey out ALL the card content so the card plainly reads "unavailable" and the
   red badge stands out — but keep it legible/tappable (it opens the waitlist). */
.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--oos .lubiwood-swatch-pieces,
.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--oos .wd-swatch-text,
.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--oos .lubiwood-size-name,
.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--oos .lubiwood-size-code,
.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--oos .lubiwood-swatch-price .price,
.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--oos .lubiwood-swatch-price .price ins,
.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--oos .lubiwood-swatch-price .price > .amount,
.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--oos .lubiwood-swatch-price .price > bdi {
	color: #9aa49d !important;
}

.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--oos .lubiwood-swatch-meta {
	opacity: 0.7;
}

/* Sold-out pill: solid near-black so it reads "unavailable" without shouting,
   distinct from the green "Most popular" pill, with a bell hinting you can get
   notified. Kept at the base badge size so prices stay aligned with the other
   cards via the badge-height placeholder. */
.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-badge--oos {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	background: #1a1a1a !important; /* hold the black even when the card is selected */
	color: #fff;
	font-weight: 800;
}

.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-badge--oos .lubiwood-bell {
	flex: 0 0 auto;
	margin-top: -1px;
}

/* Hide duplicate blocks below (shown on each card) */
.variations_form.lubiwood-swatch-prices-active .single_variation_wrap .woocommerce-variation-price,
.variations_form.lubiwood-swatch-prices-active .single_variation_wrap .woocommerce-variation-description {
	display: none !important;
}

/* —— Single size: one option, auto-selected — present it, don't ask to "choose" —— */
.variations_form.lubiwood-swatch-prices-active.lubiwood-single-size .wd-swatches-single > .wd-swatch.wd-text {
	cursor: default;
}

.variations_form.lubiwood-swatch-prices-active.lubiwood-single-size .wd-swatches-single > .wd-swatch.wd-text:hover {
	border-color: var(--lw-swatch-brd-active) !important;
	background: var(--lw-swatch-bg-active) !important;
}

/* —— Tablet —— */
@media (max-width: 1024px) {
	.variations_form.lubiwood-swatch-prices-active {
		--lw-swatch-gap: 8px;
		--lw-swatch-radius: 13px;
	}
}

/* —— Mobile —— */
@media (max-width: 767px) {
	.variations_form.lubiwood-swatch-prices-active {
		--lw-swatch-radius: 12px;
	}

	.variations_form.lubiwood-swatch-prices-active .wd-swatches-single > .wd-swatch.wd-text {
		padding: 20px 14px 12px !important;
		column-gap: 10px;
		row-gap: 6px;
	}

	.variations_form.lubiwood-swatch-prices-active table.variations tr {
		display: block;
	}

	.variations_form.lubiwood-swatch-prices-active table.variations .value {
		display: block;
		width: 100%;
		padding-inline: 0;
	}
}

/* —— Narrow phones: keep size left, price top-right —— */
@media (max-width: 479px) {
	.variations_form.lubiwood-swatch-prices-active .wd-swatches-single > .wd-swatch.wd-text {
		grid-template-columns: minmax(0, 1fr);
		padding: 20px 14px 12px !important;
	}

	.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-head {
		grid-column: 1;
		gap: 8px 10px;
	}

	.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-aside {
		max-width: 58%;
	}

	/* Count is the headline on phones too — bigger than the price row. */
	.variations_form.lubiwood-swatch-prices-active .wd-swatch.lubiwood-swatch--has-pieces .lubiwood-swatch-pieces {
		font-size: clamp(1rem, 4.2vw, 1.125rem);
	}

	.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-price .price ins {
		font-size: clamp(0.875rem, 3.4vw, 0.9375rem) !important;
	}

	.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-price .price del {
		font-size: clamp(0.6875rem, 2.6vw, 0.75rem) !important;
	}

	.variations_form.lubiwood-swatch-prices-active .lubiwood-swatch-meta {
		grid-column: 1;
	}

	.variations_form.lubiwood-swatch-prices-active .lubiwood-chooser-banner {
		padding: 18px 16px 20px;
	}
}

@media (max-width: 359px) {
	.variations_form.lubiwood-swatch-prices-active .wd-swatches-single > .wd-swatch.wd-text {
		padding: 18px 12px 12px !important;
	}
}

@media (prefers-reduced-motion: reduce) {
	.variations_form.lubiwood-swatch-prices-active .wd-swatches-single > .wd-swatch.wd-text {
		transition: none;
	}
}

/* ---------------------------------------------------------------------------
 * "Choose a size" modal — an in-place size picker styled like the product page.
 * Opened when an active "Add to cart" (main button or mobile sticky bar) is
 * tapped before a size is chosen; clones the on-page size cards so tapping one
 * selects it + adds to cart. Message + OK is a fallback when no sizes exist.
 * ------------------------------------------------------------------------- */

.lubiwood-size-modal {
	position: fixed;
	inset: 0;
	z-index: 100000;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 16px;
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition: opacity 0.18s ease, visibility 0.18s ease;
}

.lubiwood-size-modal--open {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
}

.lubiwood-size-modal__overlay {
	position: absolute;
	inset: 0;
	background: rgba(15, 23, 18, 0.46);
	-webkit-backdrop-filter: blur(2px);
	backdrop-filter: blur(2px);
}

.lubiwood-size-modal__dialog {
	position: relative;
	display: flex;
	flex-direction: column;
	width: 100%;
	max-width: 420px;
	max-height: min(88vh, 760px);
	box-sizing: border-box;
	padding: 0;
	overflow: hidden;
	text-align: left;
	background: #fff;
	color: var(--lwd-text, #1f2421);
	border-radius: var(--lwd-radius-lg, 16px);
	box-shadow: 0 22px 60px rgba(15, 23, 18, 0.28);
	transform: translateY(10px) scale(0.985);
	transition: transform 0.18s ease;
}

.lubiwood-size-modal__dialog:focus {
	outline: none;
}

.lubiwood-size-modal--open .lubiwood-size-modal__dialog {
	transform: translateY(0) scale(1);
}

/* Green header band — echoes the on-page "Choose your size" chooser banner. */
.lubiwood-size-modal__head {
	flex: 0 0 auto;
	padding: 20px 52px 18px 22px;
	background: var(--lwd-green-soft, #f0f7f2);
	border-bottom: 1px solid var(--lwd-green-line, #b8d4be);
}

.lubiwood-size-modal__title {
	margin: 0 0 6px;
	font-size: clamp(1.25rem, 4.6vw, 1.5rem);
	font-weight: 800;
	line-height: 1.2;
	letter-spacing: -0.01em;
	color: var(--lwd-text, #1f2421);
}

.lubiwood-size-modal__hint {
	margin: 0;
	font-size: clamp(0.95rem, 3.2vw, 1.0625rem);
	font-weight: 500;
	line-height: 1.4;
	color: var(--lwd-green-dark, #2f5c38);
}

/* Cloned size cards live here; the wrapper carries the swatch-prices scope
   classes so the cards inherit the exact on-page look. */
.lubiwood-size-modal__sizes {
	flex: 1 1 auto;
	padding: 16px 18px 18px;
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
}

.lubiwood-size-modal__sizes .wd-swatches-product {
	margin: 0 !important;
}

.lubiwood-size-modal__sizes .wd-swatch {
	cursor: pointer;
}

/* Modal cards show the finished-size row up front. On the page the row is
   revealed on select, but tapping a modal card adds it straight to cart, so the
   shopper would never see it otherwise — show every card's details here. */
.lubiwood-size-modal__sizes .lubiwood-swatch-meta {
	display: block !important;
}

.lubiwood-size-modal:not(.lubiwood-size-modal--has-sizes) .lubiwood-size-modal__sizes {
	display: none;
}

/* Message + OK fallback (only when there are no sizes to show). */
.lubiwood-size-modal__fallback {
	padding: 18px 22px 22px;
	text-align: center;
}

.lubiwood-size-modal--has-sizes .lubiwood-size-modal__fallback {
	display: none;
}

.lubiwood-size-modal__body {
	margin: 0 0 18px;
	font-size: 15px;
	font-weight: 500;
	line-height: 1.5;
	color: var(--lwd-text-muted, #3a3f3c);
}

/* Buttons — force our styling over the theme's generic button rules. */
.lubiwood-size-modal .lubiwood-size-modal__close {
	position: absolute;
	top: 10px;
	right: 12px;
	z-index: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	min-width: 0;
	margin: 0;
	padding: 0;
	border: 0 !important;
	border-radius: 50% !important;
	background: rgba(255, 255, 255, 0.7) !important;
	color: var(--lwd-green-dark, #2f5c38) !important;
	font-size: 22px;
	line-height: 1;
	box-shadow: none !important;
	cursor: pointer;
	transition: background 0.15s ease, color 0.15s ease;
}

.lubiwood-size-modal .lubiwood-size-modal__close:hover,
.lubiwood-size-modal .lubiwood-size-modal__close:focus-visible {
	background: #fff !important;
	color: var(--lwd-green, #3d6b47) !important;
	outline: none;
}

.lubiwood-size-modal .lubiwood-size-modal__ok {
	display: inline-block;
	width: 100%;
	min-width: 0;
	margin: 0;
	padding: 13px 26px;
	border: 0 !important;
	border-radius: var(--lwd-radius, 12px) !important;
	background: var(--lwd-green, #3d6b47) !important;
	color: #fff !important;
	font-size: 15px;
	font-weight: 700;
	box-shadow: none !important;
	cursor: pointer;
	transition: background 0.15s ease;
}

.lubiwood-size-modal .lubiwood-size-modal__ok:hover,
.lubiwood-size-modal .lubiwood-size-modal__ok:focus-visible {
	background: var(--lwd-green-dark, #2f5c38) !important;
	outline: none;
}

body.lubiwood-size-modal-open {
	overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
	.lubiwood-size-modal,
	.lubiwood-size-modal__dialog {
		transition: none;
	}
}

/* ---------------------------------------------------------------------------
 * "Adding…" feedback — the fixed bar (and modal cards) spin while adding so the
 * tap clearly registers. Cleared on added_to_cart / FunnelKit open, or a timeout.
 * ------------------------------------------------------------------------- */

@keyframes lubiwood-spin {
	to { transform: rotate(360deg); }
}

/* Tactile press on the mobile bottom bar. */
.wd-sticky-btn .wd-sticky-add-to-cart {
	transition: transform 0.12s ease, opacity 0.12s ease;
}

.wd-sticky-btn .wd-sticky-add-to-cart:active {
	transform: scale(0.975);
}

/* Bottom-bar spinner: hide the label, drop in a spinner, block re-taps. */
.wd-sticky-btn .wd-sticky-add-to-cart.lubiwood-adding {
	position: relative;
	pointer-events: none;
}

/* Fully hide the label under the spinner — WoodMart sets -webkit-text-fill-color
   on its buttons, which beats plain `color`, and the text may sit in a child span. */
.wd-sticky-btn .wd-sticky-add-to-cart.lubiwood-adding,
.wd-sticky-btn .wd-sticky-add-to-cart.lubiwood-adding * {
	color: transparent !important;
	-webkit-text-fill-color: transparent !important;
}

.wd-sticky-btn .wd-sticky-add-to-cart.lubiwood-adding::after {
	content: '';
	position: absolute;
	top: 50%;
	left: 50%;
	width: 20px;
	height: 20px;
	margin: -10px 0 0 -10px;
	border: 2px solid rgba(255, 255, 255, 0.45);
	border-top-color: #fff;
	border-radius: 50%;
	animation: lubiwood-spin 0.6s linear infinite;
}

/* Modal size card spinner while it selects + adds. */
.lubiwood-size-modal__sizes .wd-swatch.lubiwood-adding {
	pointer-events: none;
}

.lubiwood-size-modal__sizes .wd-swatch.lubiwood-adding::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 3;
	background: rgba(255, 255, 255, 0.6);
	border-radius: inherit;
}

.lubiwood-size-modal__sizes .wd-swatch.lubiwood-adding::after {
	content: '';
	position: absolute;
	top: 50%;
	left: 50%;
	z-index: 4;
	width: 24px;
	height: 24px;
	margin: -12px 0 0 -12px;
	border: 2.5px solid color-mix(in srgb, var(--lwd-green, #3d6b47) 25%, transparent);
	border-top-color: var(--lwd-green, #3d6b47);
	border-radius: 50%;
	animation: lubiwood-spin 0.6s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
	.wd-sticky-btn .wd-sticky-add-to-cart.lubiwood-adding::after,
	.lubiwood-size-modal__sizes .wd-swatch.lubiwood-adding::after {
		animation-duration: 1.4s;
	}
	.wd-sticky-btn .wd-sticky-add-to-cart:active {
		transform: none;
	}
}

