/**
 * product-buy.css — the single-product buy rail.
 *
 * Everything the decision needs, in two cards: the tinted buy card (price,
 * availability, quantity, the two CTAs, trust, payment marks) and the white
 * contact card below it. Plus the mobile bar that carries the same CTA once the
 * in-flow one scrolls away.
 *
 * WHY THIS IS ITS OWN FILE. product.css owns the page — the grid, the gallery,
 * the description, the specification fold. The rail is a component group with
 * its own tokens, its own keyframes and its own forced-colors contract, and it
 * is the part of this page most likely to be reworked again. Section 4 of
 * product.css was deleted wholesale when this file arrived; it is not split
 * across two stylesheets.
 *
 * THE RADIUS LADDER IS THREE STEPS AND NEVER FOUR:
 *   18px  card     (--bedi-radius-xl)
 *   12px  control  (--bedi-radius-lg)   stepper shell, aux buttons, tiles,
 *                                       and — since the client asked for it —
 *                                       the CTAs, which were 999px
 *   999px chip     (--bedi-radius-pill) badges and status chips ONLY, never
 *                                       anything you click
 * A fourth value is what makes a stack of controls read as assembled rather
 * than designed.
 *
 * THE MOTION BUDGET. Exactly one looping animation exists in this file — the
 * low-stock dot — because scarcity is the only fact here that is genuinely
 * time-sensitive. Everything else is a transition off a real interaction.
 *
 * @package Bedi\Theme
 */

/* =========================================================================
 * 0. COMPONENT TOKENS
 *
 * Declared on the card rather than :root so the mobile bar can redeclare them
 * at reduced sizes and every rule below follows without a second selector.
 * ====================================================================== */

.bedi-product__buy-card,
.bedi-buybar {
	/* 34px. Large enough to be the first thing read in the rail, small enough
	   that a five-figure lari price still fits 320px of content. */
	--bedi-prod-price: 2.125rem;
	--bedi-prod-cta-h: 52px;

	/*
	 * MUTED TEXT ON THE TINT IS NOT --bedi-ink-muted, AND THIS IS A CONTRAST
	 * FIX RATHER THAN A PREFERENCE.
	 *
	 * #777777 on white is 4.54:1 and passes AA. On this card's #EAF0FA it is
	 * 3.91:1 and fails — and four things are set in it: the quantity label, the
	 * VAT line, the price suffix and the instalment row. #6A6A6A on #EAF0FA is
	 * 4.72:1 and passes. The global token is left alone because it is correct
	 * everywhere it is used on white; this override exists only inside the
	 * tinted card.
	 */
	--bedi-prod-muted: #6A6A6A;

	/*
	 * The low-stock pulse ring. This cannot be a token: --bedi-danger is a hex
	 * and box-shadow needs the alpha. Same pattern product.css already uses for
	 * the accent glow. Source colour: --bedi-danger #F2442C.
	 */
	--bedi-pulse-ring: rgba(242, 68, 44, 0.35);
}

/* =========================================================================
 * 1. THE CARD
 *
 * NO BORDER. A --bedi-rule hairline (#E5E5E5) against the #EAF0FA tint is a
 * 1.02:1 edge — it reads as a rendering artefact, not as an intentional line.
 * The tint IS the separation.
 *
 * NO SHADOW. A shadow under a tinted card on a white page draws a second,
 * softer edge parallel to the first, which is the floating-SaaS-card look the
 * client rejected by name.
 * ====================================================================== */

.bedi-product__buy-card {
	background-color: var(--bedi-bg-2);
	border-radius: var(--bedi-radius-xl);
	padding: var(--bedi-space-6);
}

/*
 * The internal hairlines ARE deliberately faint against the tint. On a tinted
 * card a full-contrast rule chops it into stacked boxes; at this contrast it
 * reads as a crease grouping rows, which is exactly the job.
 */
.bedi-buyrail__sep {
	border-block-start: var(--bedi-border-width) solid var(--bedi-rule);
}

/*
 * Row rhythm is per-row, not a uniform gap, because the groups are not equally
 * related: availability→price is one thought, price→quantity→buy is another.
 */
/*
 * TWO OF THESE USED TO BE WRITTEN TWICE, AND THE SECOND COPY WON.
 *
 * `.bedi-buyrail__trust` is declared again in section 8 as a list reset —
 * `margin: 0; padding: 0` — at the SAME (0,1,0) specificity and later in the
 * file, so it silently overwrote the rhythm set here. The trust rows ended up
 * flush against the Save/Share pair with nothing but a hairline between them,
 * which is the uneven spacing that was visible in the rail.
 *
 * `.bedi-buy-now`'s 8px lost to woocommerce.css's own `margin: 0` on
 * `.woocommerce … button.button`, which is higher specificity than a bare
 * class.
 *
 * Both are now declared once, at a weight that wins, on the rule that also
 * owns the element's box. The list resets stay where they are and no longer
 * carry spacing.
 *
 * THE RHYTHM, stated once so it can be read as a whole:
 *
 *   availability          0     the card's own padding is the space above it
 *   price               +16     same thought as availability — "can I have it,
 *                               what does it cost" — so the smaller step
 *   quantity      hairline +20  a new thought: acting on it
 *   add to cart         +16
 *   buy now              +8     a pair, so the tightest step in the card
 *   save / share        +16
 *   trust         hairline +20  reassurance, consumed after the decision
 *   payment       hairline +20
 *
 * Every gap is a space token. Nothing here is a hand-picked pixel.
 */
/*
 * THE FORM CONTRIBUTES NO SPACING OF ITS OWN.
 *
 * woo.css:692 styles `.woocommerce div.product form.cart` as a WRAPPING ROW —
 * `display: flex; flex-wrap: wrap; align-items: center; gap: --bedi-woo-space-xs;
 * margin: 0 0 --bedi-woo-space-sm` — which is exactly right for WooCommerce's
 * default layout, where the quantity box and the button sit side by side.
 *
 * This card is a vertical stack with a hand-set rhythm, and that `gap` was
 * ADDING to every child's margin: the quantity row, both buttons and the
 * Save/Share pair each came out 12px further apart than the rhythm below says,
 * and the form's own bottom margin added a fourth uneven step. The margins all
 * measured correct in isolation, which is what made it look like a rounding
 * problem rather than a second source of spacing.
 *
 * (0,4,1), so it beats woo.css's (0,3,1) outright rather than on print order.
 * `column` with `gap: 0` rather than `display: block`, so the children's
 * margins cannot collapse through the form's edges into the card.
 */
.woocommerce div.product .bedi-product__buy-card form.cart,
.woocommerce-page div.product .bedi-product__buy-card form.cart {
	align-items: stretch;
	display: flex;
	flex-direction: column;
	flex-wrap: nowrap;
	gap: 0;
	margin: 0;
}

.bedi-product__price { margin-block-start: var(--bedi-space-4); }

/*
 * WOOCOMMERCE'S OWN `p.price` CARRIES A BOTTOM MARGIN, and it was the last
 * uneven gap in the card.
 *
 * `.woocommerce div.product p.price` sets `margin-bottom: 1em` at (0,3,2). The
 * reset in section 2 is `.bedi-product__buy-card .price { margin: 0 }` at
 * (0,2,0), which loses — so 16px escaped through the wrapper (a block box with
 * no padding or border, so the child's margin collapses straight out of it)
 * and the quantity row sat 36px below the price instead of 20.
 *
 * (0,4,2) here, which beats core outright.
 */
.woocommerce div.product .bedi-product__buy-card p.price,
.woocommerce-page div.product .bedi-product__buy-card p.price {
	margin: 0;
}

.bedi-stepper__row {
	margin-block-start: var(--bedi-space-5);
	padding-block-start: var(--bedi-space-5);
}

/*
 * The quantity row for a product whose quantity cannot change. The wrapper is
 * still in the form because it carries WooCommerce's hidden quantity input —
 * that is what posts quantity=1 — it simply takes up no space and adds nothing
 * to form.cart's flex gap. A hidden control still submits; only a disabled one
 * does not.
 */
.bedi-stepper__fixed { display: none; }

.bedi-product__buy-card form.cart .single_add_to_cart_button { margin-block-start: var(--bedi-space-4); }

/* (0,3,2) — beats woocommerce.css's `margin: 0` outright rather than on order. */
.bedi-product form.cart button.bedi-buy-now { margin-block-start: var(--bedi-space-2); }

.bedi-buyrail__instal { margin-block-start: var(--bedi-space-3); }
.bedi-buyrail__aux    { margin-block-start: var(--bedi-space-4); }

.bedi-buyrail__pay {
	margin-block-start: var(--bedi-space-5);
	padding-block-start: var(--bedi-space-4);
}

/*
 * Woo echoes wc_get_stock_html() BEFORE it opens <form class="cart">, so the
 * element is a SIBLING of the form, not a descendant — a `form.cart .stock`
 * rule silently matches nothing. The child combinator off the card is what
 * catches it.
 *
 * The echo is KEPT rather than filtered to empty: woocommerce_get_stock_html is
 * hooked by third parties and returning '' kills theirs too. We hide Woo's and
 * render our own chips.
 */
.bedi-product__buy-card > .stock {
	display: none;
}

/* =========================================================================
 * 2. PRICE
 *
 * Wraps Woo's own <p class="price"> rather than replacing it, so
 * wc_get_price_html() filters and third-party price plugins keep working.
 * ====================================================================== */

.bedi-product__buy-card .price,
.bedi-product__buy-card .woocommerce-variation-price .price {
	align-items: baseline;
	column-gap: 10px;
	display: flex;
	flex-wrap: wrap;
	margin: 0;
	row-gap: 4px;
}

/*
 * ALWAYS --bedi-ink, on sale or not. A red or accent-blue sale price makes a
 * 1250₾ motherboard read as clearance stock or as a hyperlink; the discount is
 * carried by the chip and the struck original instead.
 */
.bedi-product__buy-card .price > .amount,
.bedi-product__buy-card .price > bdi,
.bedi-product__buy-card .price ins,
.bedi-product__buy-card .woocommerce-variation-price .price ins {
	color: var(--bedi-ink);
	font-family: var(--bedi-font-display);
	font-size: var(--bedi-prod-price);
	font-weight: var(--bedi-weight-bold);
	letter-spacing: -0.012em;
	line-height: 1.02;
}

/* Woo and several user agents underline <ins>. */
.bedi-product__buy-card .price ins {
	background: none;
	text-decoration: none;
}

/*
 * The symbol rides at cap height instead of sitting on the baseline at full
 * size. Scoped to :last-child only — a locale that puts the symbol FIRST would
 * otherwise get a shrunken leading glyph.
 */
.bedi-product__buy-card .price .woocommerce-Price-currencySymbol:last-child {
	color: var(--bedi-prod-muted);
	font-size: 0.62em;
	font-weight: var(--bedi-weight-medium);
	vertical-align: 0.3em;
}

/*
 * NO opacity on the struck price. Opacity fades the strike itself and it stops
 * reading as a strike.
 */
.bedi-product__buy-card .price del {
	color: var(--bedi-ink-muted);
	font-size: var(--bedi-text-xl);
	font-weight: var(--bedi-weight-regular);
	margin: 0;
	opacity: 1;
	text-decoration: line-through;
	text-decoration-skip-ink: none;
	text-decoration-thickness: 1px;
}

.bedi-product__buy-card .price del .woocommerce-Price-currencySymbol {
	font-size: inherit;
	vertical-align: baseline;
}

/*
 * NAVY, NOT ACCENT. An accent chip 60px from an accent CTA gives the eye two
 * blue objects competing for the one glance that has to land on the button.
 */
.bedi-product__save {
	align-items: center;
	background-color: var(--bedi-navy);
	block-size: 24px;
	border-radius: var(--bedi-radius-pill);
	color: var(--bedi-on-navy);
	display: inline-flex;
	font-family: var(--bedi-font-display);
	font-size: var(--bedi-text-xs);
	font-variant-numeric: tabular-nums;
	font-weight: var(--bedi-weight-bold);
	letter-spacing: 0.02em;
	padding-inline: 10px;
}

/* Without this a shop-configured "incl. VAT" suffix typesets at 34px. */
.bedi-product__buy-card .woocommerce-price-suffix {
	color: var(--bedi-prod-muted);
	font-size: var(--bedi-text-sm);
	font-weight: var(--bedi-weight-regular);
}

.bedi-product__vat {
	color: var(--bedi-prod-muted);
	display: block;
	font-size: var(--bedi-text-sm);
	margin-block-start: 6px;
}

/* A variable product's "from X – Y" range typesets two prices and overflows a
   320px rail at full size. */
.bedi-product__price--range .price > .amount,
.bedi-product__price--range .price > bdi {
	font-size: clamp(1.5rem, 1.1rem + 1.6vw, var(--bedi-prod-price));
}

/*
 * The ONE motion the price is allowed, and only on variable products: Woo swaps
 * .woocommerce-variation-price instantly, and on a 368px rail the only evidence
 * that anything happened is four characters changing.
 */
.bedi-product__buy-card .woocommerce-variation-price.is-swapped .price {
	animation: bedi-price-swap 180ms var(--bedi-ease-in) 1;
}

@keyframes bedi-price-swap {
	from { opacity: 0; transform: translateY(4px); }
	to   { opacity: 1; transform: translateY(0); }
}

/* =========================================================================
 * 3. AVAILABILITY CHIPS
 *
 * Status, not controls. Not focusable, no hover. The meaning lives in the text
 * — the dot is aria-hidden and never carries it alone.
 * ====================================================================== */

.bedi-product__avail {
	display: flex;
	flex-wrap: wrap;
	gap: var(--bedi-space-2);
	margin: 0;
	padding: 0;
}

.bedi-product__chip {
	align-items: center;
	block-size: 28px;
	border-radius: var(--bedi-radius-pill);
	column-gap: 6px;
	display: inline-flex;
	font-size: var(--bedi-text-sm);
	font-weight: var(--bedi-weight-medium);
	/* Asymmetric: the dot needs less lead-in than the text needs trail. */
	padding-inline: 8px 12px;
	white-space: nowrap;
}

/* A white pill on the #EAF0FA tint reads as raised without a border or a
   shadow — which is why neither is here. */
.bedi-product__chip--in,
.bedi-product__chip--eta {
	background-color: var(--bedi-surface);
	color: var(--bedi-ink);
}

.bedi-product__chip--low {
	background-color: var(--bedi-surface);
	color: var(--bedi-ink);
}

.bedi-product__chip--out {
	background-color: var(--bedi-surface-2);
	color: var(--bedi-ink-muted);
}

.bedi-product__chip--back {
	background-color: var(--bedi-surface-2);
	color: var(--bedi-ink);
}

.bedi-product__dot {
	block-size: 7px;
	border-radius: var(--bedi-radius-round);
	flex: 0 0 auto;
	inline-size: 7px;
}

.bedi-product__chip--in  .bedi-product__dot { background-color: var(--bedi-ok); }
.bedi-product__chip--low .bedi-product__dot { background-color: var(--bedi-danger); }
.bedi-product__chip--out .bedi-product__dot,
.bedi-product__chip--back .bedi-product__dot { background-color: var(--bedi-rule-strong); }

.bedi-product__chip-glyph {
	color: var(--bedi-ink-muted);
	display: inline-flex;
	flex: 0 0 auto;
}

/*
 * THE ONE LOOP IN THIS FILE. Scarcity is the only genuinely time-sensitive fact
 * in the block, and a loop is the only motion vocabulary that says "still true,
 * right now" without a re-render.
 */
.bedi-product__chip--low .bedi-product__dot {
	animation: bedi-pulse 2400ms var(--bedi-ease-out) infinite;
}

@keyframes bedi-pulse {
	0%   { box-shadow: 0 0 0 0 var(--bedi-pulse-ring); }
	70%  { box-shadow: 0 0 0 6px rgba(242, 68, 44, 0); }
	100% { box-shadow: 0 0 0 0 rgba(242, 68, 44, 0); }
}

/* =========================================================================
 * 4. THE STEPPER
 *
 * Minus / value / plus. Never a native number spinner. This is the control the
 * client named, so it is the one that has to be unambiguously better.
 * ====================================================================== */

.bedi-stepper__row {
	align-items: center;
	column-gap: 12px;
	display: flex;
	justify-content: space-between;
}

/*
 * GEORGIAN DOES NOT HYPHENATE, so a label wider than its cell has no fallback
 * but to escape the box. `min-inline-size: 0` lets the flex child actually
 * shrink (the default `auto` refuses to go below the content's intrinsic
 * width), and `overflow-wrap: anywhere` gives the text somewhere to break when
 * it has to. Both are needed; either alone still overflows.
 */
.bedi-stepper__label {
	color: var(--bedi-prod-muted);
	font-size: var(--bedi-text-sm);
	font-weight: var(--bedi-weight-medium);
	margin: 0;
	min-inline-size: 0;
	overflow-wrap: anywhere;
}

.bedi-cta__label,
.bedi-buyrail__auxlabel,
.bedi-contact__value,
.bedi-contact__label {
	min-inline-size: 0;
	overflow-wrap: anywhere;
}

/*
 * This IS Woo's div.quantity, re-skinned — not a wrapper around it. Overriding
 * global/quantity-input.php is what puts the same control on the cart page and
 * on grouped children from one file.
 *
 * NO INTERNAL DIVIDERS. Two hairlines inside a hairline box is what makes a
 * stepper read as a spreadsheet cell; the hover fill does the separating.
 */
.bedi-product__buy-card .quantity,
.bedi-woo .bedi-stepper {
	background-color: var(--bedi-surface);
	block-size: 48px;
	border: var(--bedi-border-width) solid var(--bedi-rule);
	border-radius: var(--bedi-radius-lg);
	display: inline-grid;
	/*
	 * The middle cell is PINNED, not `auto`. With `auto` the shell grows with
	 * its content: at a quantity of 1000 it passes 148px, and the label/stepper
	 * row's `space-between` then collapses the Georgian "რაოდენობა" instead.
	 * 58px holds four digits at 18px tabular, and the max is the hard stop.
	 */
	grid-template-columns: 44px 58px 44px;
	max-inline-size: 148px;
	overflow: hidden;
	transition: border-color var(--bedi-dur-micro) var(--bedi-ease-out);
}

/*
 * :focus-within FIRST, AS THE FALLBACK. `:has()` is unsupported in Safari
 * below 15.4 and Chromium below 105 — which is the same mid-range Android
 * population the mobile bar's IntersectionObserver choice is made for. Without
 * this, those browsers get no focus ring on the field at all.
 *
 * The second rule neutralises the double-up: where :has IS supported, a
 * focused BUTTON must not also light the shell border, because the button
 * already draws its own inset ring.
 */
.bedi-stepper:focus-within {
	border-color: var(--bedi-accent);
}

.bedi-stepper:focus-within:not(:has(.qty:focus-visible)) {
	border-color: var(--bedi-rule);
}

.bedi-stepper:has(.qty:focus-visible) {
	border-color: var(--bedi-accent);
}

/* type="button" is mandatory in the markup — a bare <button> inside form.cart
   is an implicit submit. */
.bedi-stepper__btn {
	appearance: none;
	background: none;
	block-size: 100%;
	border: 0;
	color: var(--bedi-ink);
	cursor: pointer;
	display: grid;
	inline-size: 100%;
	padding: 0;
	place-items: center;
	transition: background-color var(--bedi-dur-micro) var(--bedi-ease-out);
}

.bedi-stepper__btn:hover:not(:disabled) {
	/* The control borrows the rail's own tint rather than introducing a fourth
	   grey. */
	background-color: var(--bedi-bg-2);
}

/*
 * INSET, and this is a real trap: the shell has overflow:hidden, so an outward
 * ring is clipped to nothing and focus looks broken.
 */
.bedi-stepper__btn:focus-visible {
	outline: 3px solid var(--bedi-accent);
	outline-offset: -3px;
}

/*
 * Colour change, never opacity. Opacity fades the whole button box and blurs
 * where the hit area appears to be.
 */
.bedi-stepper__btn:disabled {
	color: var(--bedi-rule-strong);
	cursor: not-allowed;
}

.bedi-stepper__glyph {
	display: inline-flex;
	transition: transform var(--bedi-dur-micro) var(--bedi-ease-out);
}

/*
 * PRESS FEEDBACK ON THE GLYPH, NOT THE BUTTON. The button is a fixed grid cell;
 * scaling the cell makes the 48px shell appear to breathe and the number beside
 * it appear to jump. Scaling the 16px glyph is unambiguous and holds the value
 * — the thing actually being read — perfectly still.
 */
.bedi-stepper__btn:active:not(:disabled) .bedi-stepper__glyph {
	transform: scale(0.82);
}

.bedi-stepper__value {
	block-size: 100%;
	inline-size: 100%;
	position: relative;
}

/*
 * Killing the native spinner arrows is mandatory and is the single most visible
 * improvement to this control. type stays "number" — Woo's own scripts and the
 * no-JS path both need it.
 */
.bedi-product__buy-card .qty,
.bedi-woo .bedi-stepper .qty {
	appearance: textfield;
	background: none;
	block-size: 100%;
	border: 0;
	box-shadow: none;
	color: var(--bedi-ink);
	font-family: var(--bedi-font-body);
	font-size: var(--bedi-text-xl);
	/* Mandatory: without it 9→10 shifts the glyph box and the whole shell
	   appears to twitch. */
	font-variant-numeric: tabular-nums;
	font-weight: var(--bedi-weight-medium);
	inline-size: 100%;
	margin: 0;
	min-inline-size: 0;
	padding: 0;
	text-align: center;
	-webkit-appearance: textfield;
}

.bedi-product__buy-card .qty::-webkit-inner-spin-button,
.bedi-product__buy-card .qty::-webkit-outer-spin-button,
.bedi-woo .bedi-stepper .qty::-webkit-inner-spin-button,
.bedi-woo .bedi-stepper .qty::-webkit-outer-spin-button {
	appearance: none;
	margin: 0;
	-webkit-appearance: none;
}

.bedi-product__buy-card .qty:focus,
.bedi-woo .bedi-stepper .qty:focus {
	outline: none;
}

/*
 * The ghost digit. DIRECTION ENCODES THE OPERATION — the customer learns which
 * way the value went without reading the number, which is what a stepper is
 * for. JS writes the real value immediately, so form state is never behind the
 * animation.
 */
.bedi-stepper__ghost {
	color: var(--bedi-ink);
	display: grid;
	font-family: var(--bedi-font-body);
	font-size: var(--bedi-text-xl);
	font-variant-numeric: tabular-nums;
	font-weight: var(--bedi-weight-medium);
	inset: 0;
	opacity: 0;
	place-items: center;
	pointer-events: none;
	position: absolute;
}

.bedi-stepper.is-up   .bedi-stepper__ghost { animation: bedi-ghost-up   160ms var(--bedi-ease-in) 1; }
.bedi-stepper.is-down .bedi-stepper__ghost { animation: bedi-ghost-down 160ms var(--bedi-ease-in) 1; }
.bedi-stepper.is-up   .qty { animation: bedi-roll-up   160ms var(--bedi-ease-in) 1; }
.bedi-stepper.is-down .qty { animation: bedi-roll-down 160ms var(--bedi-ease-in) 1; }

@keyframes bedi-ghost-up   { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(-7px); } }
@keyframes bedi-ghost-down { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(7px);  } }
@keyframes bedi-roll-up    { from { opacity: 0; transform: translateY(7px);  } to { opacity: 1; transform: translateY(0); } }
@keyframes bedi-roll-down  { from { opacity: 0; transform: translateY(-7px); } to { opacity: 1; transform: translateY(0); } }

/*
 * BOUNDARY REFUSAL. A disabled control that simply does nothing reads as
 * broken; a refusal that moves reads as a limit that was understood and
 * declined.
 */
.bedi-stepper.is-refused {
	animation: bedi-nudge 180ms var(--bedi-ease-out) 1;
}

@keyframes bedi-nudge {
	0%, 100% { transform: translateX(0); }
	30%      { transform: translateX(-3px); }
	70%      { transform: translateX(3px); }
}

/* Sold individually: Woo prints a hidden input and a stepper bound to a hidden
   input is a control that visibly does nothing. */
.bedi-stepper__single {
	color: var(--bedi-ink);
	font-size: var(--bedi-text-lg);
	font-weight: var(--bedi-weight-medium);
	margin: 0;
}

/* =========================================================================
 * 5. THE TWO CTAs
 *
 * SPECIFICITY. `.bedi-product form.cart button.single_add_to_cart_button` is
 * (0,3,2). woocommerce.css's strongest member is `.woocommerce button.button.alt`
 * at (0,3,1), so this wins on specificity outright rather than on source order.
 * (An earlier note in product.css called this a tie — it was off by one element.
 * Two classes alone, at (0,2,0), genuinely lose, which is the bug that made
 * every button on this page render navy.)
 * ====================================================================== */

.bedi-product form.cart button.single_add_to_cart_button {
	align-items: center;
	appearance: none;
	background-color: var(--bedi-accent);
	block-size: var(--bedi-prod-cta-h);
	border: 0;
	border-radius: var(--bedi-radius-lg);
	box-shadow: none;
	color: var(--bedi-on-accent);
	column-gap: 10px;
	cursor: pointer;
	display: inline-flex;
	/* MANDATORY: core woocommerce.css floats this button. */
	float: none;
	font-family: var(--bedi-font-display);
	font-size: var(--bedi-text-lg);
	font-weight: var(--bedi-weight-medium);
	inline-size: 100%;
	justify-content: center;
	letter-spacing: 0.01em;
	padding: 0;
	position: relative;
	transition:
		background-color var(--bedi-dur-micro) var(--bedi-ease-out),
		box-shadow var(--bedi-dur) var(--bedi-ease-out),
		transform var(--bedi-dur-micro) var(--bedi-ease-out);
}

.bedi-product form.cart button.single_add_to_cart_button:hover,
.bedi-product form.cart button.single_add_to_cart_button:focus-visible {
	background-color: var(--bedi-accent-strong);
	/* ONE pixel of lift and a -14px spread. The 2px + 28px bloom this replaces
	   is precisely the floating-SaaS-card signature. */
	box-shadow: 0 10px 24px -14px rgba(45, 129, 255, 0.8);
	transform: translateY(-1px);
}

/* 0.985, not 0.97: on a 52px CTA anything below 0.98 reads as a glitch. */
.bedi-product form.cart button.single_add_to_cart_button:active {
	box-shadow: none;
	transform: translateY(0) scale(0.985);
}

/*
 * NAVY, not accent. An accent ring on an accent fill is invisible — the most
 * common focus bug in blue design systems.
 */
.bedi-product form.cart button.single_add_to_cart_button:focus-visible {
	outline: 3px solid var(--bedi-navy);
	outline-offset: 3px;
}

.bedi-cta__icon,
.bedi-cta__label {
	display: inline-flex;
	transition:
		opacity var(--bedi-dur-micro) var(--bedi-ease-out),
		transform var(--bedi-dur) var(--bedi-ease-in);
}

/*
 * THE PAIR OPENS ON HOVER. 4px total, and nothing else moves inside. The button
 * gains a direction and a small sense of opening, which is specific and cheap,
 * instead of glowing.
 */
.bedi-product form.cart button.single_add_to_cart_button:hover .bedi-cta__icon  { transform: translateX(-2px); }
.bedi-product form.cart button.single_add_to_cart_button:hover .bedi-cta__label { transform: translateX(2px); }

/*
 * The disabled add-to-cart rules that lived here are gone with the element.
 * simple.php no longer renders a disabled button for an out-of-stock product —
 * see `.bedi-oos` above and the note in that template. A `:disabled` rule for a
 * button that is never rendered is how the next reader concludes the state is
 * handled when it is not.
 *
 * The selector IS still worth keeping for the case it was never about: a
 * gateway or plugin disabling the live button mid-request.
 */
.bedi-product form.cart button.single_add_to_cart_button:disabled,
.bedi-product form.cart button.single_add_to_cart_button.disabled {
	background-color: var(--bedi-surface-2);
	box-shadow: none;
	color: var(--bedi-ink-muted);
	cursor: not-allowed;
	transform: none;
}

/* --- loading / done ------------------------------------------------- */

.bedi-cta__spinner,
.bedi-cta__check {
	display: none;
}

.single_add_to_cart_button.is-loading {
	pointer-events: none;
}

.single_add_to_cart_button.is-loading .bedi-cta__icon,
.single_add_to_cart_button.is-loading .bedi-cta__label,
.single_add_to_cart_button.is-done .bedi-cta__icon {
	display: none;
}

.single_add_to_cart_button.is-loading .bedi-cta__spinner {
	align-items: center;
	column-gap: 5px;
	display: inline-flex;
}

/*
 * Dots, not a spinning ring: a ring at 20px inside the 52px CTA is a second
 * circle competing with the button's own corners.
 */
.bedi-cta__dot {
	animation: bedi-dots 900ms var(--bedi-ease-out) infinite;
	background-color: currentColor;
	block-size: 5px;
	border-radius: var(--bedi-radius-round);
	inline-size: 5px;
}

.bedi-cta__dot:nth-child(2) { animation-delay: 120ms; }
.bedi-cta__dot:nth-child(3) { animation-delay: 240ms; }

@keyframes bedi-dots {
	0%, 100% { opacity: 0.35; }
	50%      { opacity: 1; }
}

/*
 * SUCCESS — THE CONFIRMATION IS THE BUTTON. Nothing is inserted into the
 * layout, nothing reflows, nothing has to be dismissed, and the affordance the
 * customer pressed is the one that answers them. That is the client's "don't
 * spawn a view-cart button", solved in place.
 */
.bedi-product form.cart button.single_add_to_cart_button.is-done {
	background-color: var(--bedi-ok);
	box-shadow: none;
	transform: none;
}

.single_add_to_cart_button.is-done .bedi-cta__check {
	display: inline-flex;
}

.single_add_to_cart_button.is-done .bedi-cta__check path {
	animation: bedi-check-draw 280ms var(--bedi-ease-in) 80ms both;
}

@keyframes bedi-check-draw {
	from { stroke-dashoffset: 24; }
	to   { stroke-dashoffset: 0; }
}

/* The button never turns red: a red button invites a second press. The toast
   carries the error text. */
.single_add_to_cart_button.is-error {
	animation: bedi-nudge 180ms var(--bedi-ease-out) 1;
}

/* --- out of stock ---------------------------------------------------- */

/*
 * THE STATE THAT REPLACES THE BUY BUTTON.
 *
 * Deliberately NOT button-shaped and deliberately not the tinted card's own
 * fill: a white well with a hairline, so it reads as a hole where the buy
 * controls were rather than as a control that has been switched off. The
 * availability chip above already carries the fact in the card's own language;
 * this carries what to do about it.
 *
 * No accent anywhere in the block except the phone action, which is the one
 * thing here that does something.
 */
.bedi-oos {
	background-color: var(--bedi-surface);
	border: var(--bedi-border-width) solid var(--bedi-rule);
	border-radius: var(--bedi-radius-lg);
	margin-block-start: var(--bedi-space-5);
	padding: var(--bedi-space-4);
}

.bedi-oos__title {
	color: var(--bedi-ink);
	font-family: var(--bedi-font-display);
	font-size: var(--bedi-text-lg);
	font-weight: var(--bedi-weight-medium);
	margin: 0;
}

.bedi-oos__text {
	color: var(--bedi-prod-muted);
	font-size: var(--bedi-text-sm);
	line-height: 1.45;
	margin: 6px 0 0;
	/* Georgian does not hyphenate and this is a full sentence in a 320px rail. */
	overflow-wrap: anywhere;
}

.bedi-oos__action {
	align-items: center;
	background-color: var(--bedi-surface);
	block-size: 44px;
	border: var(--bedi-border-width) solid var(--bedi-rule);
	border-radius: var(--bedi-radius-lg);
	color: var(--bedi-ink);
	column-gap: 8px;
	display: inline-flex;
	font-family: var(--bedi-font-display);
	font-size: var(--bedi-text-lg);
	font-weight: var(--bedi-weight-medium);
	inline-size: 100%;
	justify-content: center;
	margin-block-start: var(--bedi-space-4);
	text-decoration: none;
	transition:
		border-color var(--bedi-dur-micro) var(--bedi-ease-out),
		color var(--bedi-dur-micro) var(--bedi-ease-out);
}

/* Accent, not navy: this is the only live action in the block, so it is the
   one thing allowed to look like the primary it has temporarily replaced. */
.bedi-oos__action:hover,
.bedi-oos__action:focus-visible {
	border-color: var(--bedi-accent);
	color: var(--bedi-accent);
}

.bedi-oos__action:focus-visible {
	outline: 3px solid var(--bedi-accent);
	outline-offset: 2px;
}

.bedi-oos__icon { display: inline-flex; }

/* --- buy now --------------------------------------------------------- */

/*
 * A WHITE BUTTON, NOT AN ACCENT OUTLINE. An accent-bordered ghost 8px under an
 * accent-filled one puts two blue objects in a 320px column and the eye has to
 * choose. White with a hairline recedes correctly and still reads as pressable
 * precisely because the card behind it is tinted.
 *
 * 48px against the primary's 52px. That height delta IS the hierarchy, and it
 * survives colour-blindness, greyscale printing and forced-colors, which a
 * colour-only distinction does not.
 */
.bedi-product form.cart button.bedi-buy-now {
	align-items: center;
	appearance: none;
	background-color: var(--bedi-surface);
	block-size: 48px;
	border: var(--bedi-border-width) solid var(--bedi-rule);
	border-radius: var(--bedi-radius-lg);
	box-shadow: none;
	color: var(--bedi-ink);
	cursor: pointer;
	display: inline-flex;
	float: none;
	font-family: var(--bedi-font-display);
	font-size: var(--bedi-text-lg);
	font-weight: var(--bedi-weight-medium);
	inline-size: 100%;
	justify-content: center;
	padding: 0;
	transition:
		border-color var(--bedi-dur-micro) var(--bedi-ease-out),
		color var(--bedi-dur-micro) var(--bedi-ease-out),
		transform var(--bedi-dur-micro) var(--bedi-ease-out);
}

/* NO lift. Only the primary lifts; that is the rule that keeps the pair legible
   as a pair. */
.bedi-product form.cart button.bedi-buy-now:hover,
.bedi-product form.cart button.bedi-buy-now:focus-visible {
	border-color: var(--bedi-navy);
	color: var(--bedi-navy);
}

.bedi-product form.cart button.bedi-buy-now:active {
	transform: scale(0.985);
}

/* Accent IS visible here, because the fill is white. */
.bedi-product form.cart button.bedi-buy-now:focus-visible {
	outline: 3px solid var(--bedi-accent);
	outline-offset: 2px;
}

/* =========================================================================
 * 6. INSTALMENTS (განვადება)
 *
 * Renders only when bedi-core supplies a figure. The theme must NOT compute a
 * finance number from price meta: that is a data responsibility and a legal
 * one.
 * ====================================================================== */

.bedi-buyrail__instal-toggle {
	align-items: center;
	appearance: none;
	background: none;
	border: 0;
	color: var(--bedi-prod-muted);
	column-gap: 6px;
	cursor: pointer;
	display: flex;
	font-family: inherit;
	font-size: var(--bedi-text-sm);
	inline-size: 100%;
	padding: 0;
	text-align: start;
}

.bedi-buyrail__instal-toggle strong {
	color: var(--bedi-ink);
	font-weight: var(--bedi-weight-medium);
	transition: color var(--bedi-dur-micro) var(--bedi-ease-out);
}

.bedi-buyrail__instal-chev {
	color: var(--bedi-rule-strong);
	display: inline-flex;
	margin-inline-start: auto;
	transition: transform var(--bedi-dur) var(--bedi-ease-in);
}

.bedi-buyrail__instal-toggle[aria-expanded="true"] .bedi-buyrail__instal-chev {
	transform: rotate(180deg);
}

.bedi-buyrail__instal-toggle:focus-visible {
	border-radius: var(--bedi-radius-md);
	outline: 3px solid var(--bedi-accent);
	outline-offset: 3px;
}

/*
 * grid-template-rows 0fr → 1fr. The correct modern disclosure: no max-height
 * guessing, no measured heights, animates to auto.
 */
.bedi-buyrail__instal-panel {
	display: grid;
	grid-template-rows: 0fr;
	transition: grid-template-rows var(--bedi-dur) var(--bedi-ease-in);
}

.bedi-buyrail__instal-panel[data-open="true"] {
	grid-template-rows: 1fr;
}

.bedi-buyrail__instal-panel > div {
	overflow: hidden;
}

.bedi-buyrail__bank {
	align-items: center;
	block-size: 36px;
	column-gap: 10px;
	display: grid;
	grid-template-columns: 24px 1fr auto;
}

.bedi-buyrail__bank + .bedi-buyrail__bank {
	border-block-start: var(--bedi-border-width) solid var(--bedi-rule);
}

.bedi-buyrail__bank-name { color: var(--bedi-ink); font-size: var(--bedi-text-sm); }
.bedi-buyrail__bank-sum  { color: var(--bedi-ink); font-size: var(--bedi-text-sm); font-weight: var(--bedi-weight-medium); }

.bedi-buyrail__instal-legal {
	color: var(--bedi-ink-muted);
	font-size: 11px;
	margin: 6px 0 0;
}

/* =========================================================================
 * 7. SAVE / SHARE
 *
 * 12px, and now the whole card agrees with it. This pair was the first thing
 * here drawn on --bedi-radius-lg, back when the CTAs above were pills and a
 * third pill row would have turned the stack into a pile of lozenges. The CTAs
 * have since come down to the same 12px, so what was the exception is now the
 * shape — it still matches the stepper, it just no longer contrasts with
 * anything.
 *
 * Rendered OUTSIDE <form class="cart"> — a <button> inside that form without
 * type="button" is an implicit submit.
 * ====================================================================== */

.bedi-buyrail__aux {
	display: grid;
	gap: var(--bedi-space-2);
	grid-template-columns: 1fr 1fr;
}

.bedi-buyrail__auxbtn {
	align-items: center;
	appearance: none;
	/* The tint shows through, so the pair reads as part of the card rather than
	   as two more white objects. */
	background: none;
	block-size: 44px;
	border: var(--bedi-border-width) solid var(--bedi-rule);
	border-radius: var(--bedi-radius-lg);
	color: var(--bedi-ink);
	column-gap: 8px;
	cursor: pointer;
	display: inline-flex;
	font-family: var(--bedi-font-body);
	font-size: var(--bedi-text-sm);
	font-weight: var(--bedi-weight-medium);
	justify-content: center;
	padding: 0;
	position: relative;
	transition:
		background-color var(--bedi-dur-micro) var(--bedi-ease-out),
		border-color var(--bedi-dur-micro) var(--bedi-ease-out),
		color var(--bedi-dur-micro) var(--bedi-ease-out),
		transform var(--bedi-dur-micro) var(--bedi-ease-out);
}

/* Different hover targets because they are different kinds of action — one is
   affective, one is utilitarian. */
.bedi-buyrail__auxbtn--wish:hover  { border-color: var(--bedi-accent); color: var(--bedi-accent); }
.bedi-buyrail__auxbtn--share:hover { border-color: var(--bedi-navy);   color: var(--bedi-navy); }

.bedi-buyrail__auxbtn:active { transform: scale(0.97); }

.bedi-buyrail__auxbtn:focus-visible {
	outline: 3px solid var(--bedi-accent);
	outline-offset: 2px;
}

.bedi-buyrail__auxicon {
	display: inline-flex;
}

/* The same gesture the header's wishlist icon and the catalogue tile make.
   bedi-heartbeat is declared in ui.css — it is reused, never redeclared. */
.bedi-buyrail__auxbtn--wish:hover .bedi-buyrail__auxicon {
	animation: bedi-heartbeat 520ms var(--bedi-ease-out) 1;
}

/*
 * The fill is what carries the state. Colour alone would fail for a
 * colour-blind customer; the filled-vs-outline silhouette does not.
 */
.bedi-buyrail__auxbtn--wish[aria-pressed="true"] {
	background-color: var(--bedi-surface);
	border-color: var(--bedi-accent);
	color: var(--bedi-accent-strong);
}

.bedi-buyrail__auxbtn--wish[aria-pressed="true"] .bedi-buyrail__auxicon svg path {
	fill: currentColor;
}

/*
 * THE POP IS wishlist.css's bedi-wish-pop, NOT A SECOND KEYFRAME, and it fires
 * off `.is-active` rather than off [aria-pressed="true"].
 *
 * Both details matter. The catalogue tile and this button are the same control
 * in two places and must move identically — a keyframe written twice is a
 * keyframe that will eventually be written twice differently. And aria-pressed
 * is TRUE on the server-rendered first paint, so keying the animation to it
 * makes a page of already-saved products stage a fireworks display on load.
 * wishlist.js sets `.is-active` only when the visitor pressed the button; the
 * server sets only the attribute. This is the rule wishlist.css:38 already
 * documents, and it now applies here too.
 */
.bedi-buyrail__auxbtn--wish.is-active .bedi-buyrail__auxicon svg {
	animation: bedi-wish-pop 420ms var(--bedi-ease-out) 1;
}

/*
 * The emission ring: one pseudo-element, zero extra DOM. Expanding PAST the
 * button's own bounds is what makes it read as emission rather than as the
 * button resizing.
 */
.bedi-buyrail__auxbtn--wish::after {
	border: 2px solid var(--bedi-accent);
	border-radius: var(--bedi-radius-lg);
	content: "";
	inset: 0;
	opacity: 0;
	pointer-events: none;
	position: absolute;
}

/* Same `.is-active` rule as the pop above: the ring is emission, and there is
   nothing to emit about a state the server just rendered. */
.bedi-buyrail__auxbtn--wish.is-active::after {
	animation: bedi-ring 420ms var(--bedi-ease-out) 1;
}

@keyframes bedi-ring {
	from { opacity: 1; transform: scale(0.6); }
	to   { opacity: 0; transform: scale(1.9); }
}

/*
 * Optimistic UI is NOT used here: a wishlist that shows saved and then silently
 * isn't is worse than 300ms of honesty.
 */
.bedi-buyrail__auxbtn.is-pending {
	color: var(--bedi-ink-muted);
	pointer-events: none;
}

/* =========================================================================
 * 8. TRUST ROWS
 *
 * Three, not four. The dropped item ("fast and reliable service") is a claim
 * with no verifiable content — exactly the filler that makes a trust block read
 * as generated, and dropping it is what lets the remaining three be read.
 *
 * No hover on non-link rows. A hover on a non-interactive element is the
 * clearest generated-UI tell there is.
 * ====================================================================== */

/*
 * The list reset and the group's spacing are ONE rule, because they were two
 * and the reset won. `margin-inline`/`padding-inline` rather than the
 * shorthands, so the block-direction values set here are not clobbered by a
 * later `margin: 0` the way they were before.
 */
.bedi-buyrail__trust {
	display: flex;
	flex-direction: column;
	list-style: none;
	margin-block: var(--bedi-space-5) 0;
	margin-inline: 0;
	padding-block: var(--bedi-space-5) 0;
	padding-inline: 0;
	row-gap: var(--bedi-space-3);
}

.bedi-buyrail__trustrow {
	align-items: start;
	color: var(--bedi-ink);
	column-gap: 10px;
	display: grid;
	font-size: var(--bedi-text-sm);
	font-weight: var(--bedi-weight-regular);
	grid-template-columns: 18px 1fr;
	line-height: 1.45;
}

.bedi-buyrail__trusticon {
	color: var(--bedi-prod-muted);
	display: inline-flex;
	/* Optically centred against the 13px cap height. */
	margin-block-start: 1px;
	transition: color var(--bedi-dur-micro) var(--bedi-ease-out);
}

.bedi-buyrail__trustrow a {
	color: inherit;
	text-decoration: underline;
	text-decoration-color: var(--bedi-rule-strong);
	text-underline-offset: 2px;
	transition: text-decoration-color var(--bedi-dur-micro) var(--bedi-ease-out);
}

/* Only the icon and the rule move; the text colour holds. In a three-row stack,
   changing the whole row makes the card flicker as the pointer crosses it. */
.bedi-buyrail__trustrow:hover a { text-decoration-color: var(--bedi-accent); }
.bedi-buyrail__trustrow:hover .bedi-buyrail__trusticon--link { color: var(--bedi-accent); }

.bedi-buyrail__trustrow a:focus-visible {
	border-radius: var(--bedi-radius-sm);
	outline: 3px solid var(--bedi-accent);
	outline-offset: 2px;
}

/* =========================================================================
 * 9. PAYMENT MARKS
 *
 * Individual tiles, not the 2286×115 composite. At 320px of rail that strip
 * renders each mark ~11px tall, which is illegible; it cannot reflow, cannot
 * drop a method the shop stops accepting, and cannot gain one without a
 * Photoshop round-trip.
 *
 * NO HOVER, NO FOCUS, NO ACTIVE, by specification. Payment marks are
 * informational; they are not links.
 * ====================================================================== */

.bedi-buyrail__pay-label {
	color: var(--bedi-prod-muted);
	font-size: 11px;
	font-weight: var(--bedi-weight-bold);
	/* Georgian is unicameral, so text-transform:uppercase is a no-op on ka
	   glyphs — the letter-spacing alone does the label work. */
	letter-spacing: 0.08em;
	margin: 0 0 var(--bedi-space-3);
}

/* Keepz gets the privileged row: it is the local wallet and the one mark a
   Georgian customer scans for. */
.bedi-buyrail__keepz {
	block-size: 20px;
	display: block;
	inline-size: auto;
	margin-block-end: var(--bedi-space-3);
}

/* flex-wrap, never a fixed-column grid, so it reflows correctly at 240px. */
.bedi-buyrail__marks {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	list-style: none;
	margin: 0;
	padding: 0;
}

/* 6px: 3px on a 28px tile reads as an accident, 12px makes each mark a
   lozenge. */
.bedi-buyrail__mark {
	background-color: var(--bedi-surface);
	block-size: 28px;
	border: var(--bedi-border-width) solid var(--bedi-rule);
	border-radius: var(--bedi-radius-md);
	display: grid;
	inline-size: 40px;
	place-items: center;
}

/*
 * THE WIDE TILE IS NOT A STYLE CHOICE, IT IS OPTICAL NORMALISATION.
 *
 * These marks are not the same shape. The Mastercard roundel is 1.6:1 and fills
 * its tile's height; Visa, Amex and CityPay are wordmarks at 3:1 and hit the
 * WIDTH limit first, which leaves them rendering about 10px tall next to a 16px
 * roundel. One uniform box makes half the strip look like it failed to load.
 *
 * Widening the tile and raising the width cap for those three brings every mark
 * to roughly the same optical area. Six tiles at 42/50 plus five 6px gaps is
 * 306px, which still fits one row inside the 320px content box of a 368px rail.
 */
.bedi-buyrail__mark--wide { inline-size: 46px; }

.bedi-buyrail__mark img {
	block-size: auto;
	inline-size: auto;
	max-block-size: 18px;
	max-inline-size: 28px;
	object-fit: contain;
}

.bedi-buyrail__mark--wide img { max-inline-size: 36px; }

/* =========================================================================
 * 10. THE CONTACT CARD
 *
 * White on white, separated by a hairline — deliberately the inverse treatment
 * to the tinted buy card, so the two never merge into one long box.
 * ====================================================================== */

.bedi-contact {
	background-color: var(--bedi-surface);
	border: var(--bedi-border-width) solid var(--bedi-rule);
	border-radius: var(--bedi-radius-xl);
	padding: var(--bedi-space-5);
}

.bedi-contact__title {
	color: var(--bedi-ink);
	font-family: var(--bedi-font-display);
	font-size: var(--bedi-text-lg);
	font-weight: var(--bedi-weight-bold);
	margin: 0 0 4px;
}

.bedi-contact__hours {
	color: var(--bedi-ink-muted);
	font-size: var(--bedi-text-sm);
	margin: 0 0 var(--bedi-space-4);
}

.bedi-contact__rows {
	list-style: none;
	margin: 0;
	padding: 0;
}

/* Flush to the card's padding edge, so the hairlines read as card structure. */
.bedi-contact__row {
	align-items: center;
	block-size: 56px;
	color: inherit;
	column-gap: var(--bedi-space-3);
	display: grid;
	grid-template-columns: 40px 1fr 16px;
	text-decoration: none;
}

.bedi-contact__item + .bedi-contact__item .bedi-contact__row {
	border-block-start: var(--bedi-border-width) solid var(--bedi-rule);
}

.bedi-contact__tile {
	background-color: var(--bedi-bg-2);
	block-size: 40px;
	border-radius: var(--bedi-radius-lg);
	color: var(--bedi-navy);
	display: grid;
	inline-size: 40px;
	place-items: center;
	transition:
		background-color var(--bedi-dur-micro) var(--bedi-ease-out),
		color var(--bedi-dur-micro) var(--bedi-ease-out);
}

.bedi-contact__label { color: var(--bedi-ink-muted); display: block; font-size: var(--bedi-text-sm); }

.bedi-contact__value {
	color: var(--bedi-ink);
	display: block;
	font-size: 0.9375rem;
	font-variant-numeric: tabular-nums;
	font-weight: var(--bedi-weight-medium);
	margin-block-start: 2px;
}

.bedi-contact__chev {
	color: var(--bedi-rule-strong);
	display: inline-flex;
	transition:
		color var(--bedi-dur) var(--bedi-ease-in),
		transform var(--bedi-dur) var(--bedi-ease-in);
}

/*
 * THE ROW BACKGROUND DOES NOT CHANGE. In a three-row stack a full-row
 * background change makes the card flicker as the pointer travels down it.
 * Lighting one 40px square is unambiguous about which row is live and costs the
 * card nothing.
 *
 * Two durations on one hover — 120ms colour, 220ms slide — is what makes it
 * feel authored rather than uniformly transitioned: the colour is the
 * acknowledgement, the slide is the invitation.
 */
.bedi-contact__row:hover .bedi-contact__tile,
.bedi-contact__row:focus-visible .bedi-contact__tile {
	background-color: var(--bedi-accent);
	color: var(--bedi-on-accent);
}

.bedi-contact__row:active .bedi-contact__tile {
	background-color: var(--bedi-accent-strong);
}

.bedi-contact__row:hover .bedi-contact__chev,
.bedi-contact__row:focus-visible .bedi-contact__chev {
	color: var(--bedi-ink-muted);
	transform: translateX(3px);
}

/* INSET: the rows are flush to the card's inner edge and an outward ring would
   be clipped by the card's radius on the first and last rows. */
.bedi-contact__row:focus-visible {
	outline: 3px solid var(--bedi-accent);
	outline-offset: -3px;
}

/* =========================================================================
 * 11. THE MOBILE BAR
 * ====================================================================== */

.bedi-buybar {
	display: none;
}

@media (max-width: 47.9375em) {
	.bedi-buybar {
		align-items: center;
		/* THE ONE PLACE GLASS IS EARNED here, and the justification is
		   functional: the bar sits over scrolling product photography (often
		   white-on-white hardware shots) and must stay legible without becoming
		   an opaque slab that visually amputates the page. */
		backdrop-filter: blur(16px) saturate(1.4);
		background-color: var(--bedi-glass-strong);
		border-block-start: var(--bedi-border-width) solid var(--bedi-rule);
		column-gap: var(--bedi-space-3);
		display: grid;
		/*
		 * 1fr FOR THE PRICE, auto FOR THE CONTROLS — the reverse of what this
		 * was. The old `auto 1fr` sized the price to its content and gave every
		 * remaining pixel to a button that then stretched across the bar. The
		 * price is the thing that needs room to breathe and to stack a struck
		 * figure under itself; the stepper and the button have fixed widths and
		 * want no more than those.
		 */
		grid-template-columns: 1fr auto;
		/*
		 * ON TOP OF THE BOTTOM BAR, NOT OVER IT.
		 *
		 * --bedi-bottombar-h is 0px wherever that bar does not exist, so this
		 * expression is `0 + 0` on a desktop and the bar lands flush as before.
		 * Where the bottom bar IS present it takes the safe-area inset itself, so
		 * this reads the inset too — the two stack, and the buy bar's own bottom
		 * padding goes back to a plain 10px because it is no longer the thing
		 * sitting over the home indicator.
		 */
		inset-block-end: calc(var(--bedi-bottombar-h, 0px) + env(safe-area-inset-bottom, 0px));
		inset-inline: 0;
		opacity: 0;
		/*
		 * VERTICALLY CENTRED. The bar used to align its two cells to the top of
		 * a row sized by the tallest of them, so a single-line price sat high
		 * against a 48px button instead of beside it. `center` is the whole fix
		 * and it is also what makes the stacked sale price below sit correctly.
		 */
		align-items: center;
		padding: 10px var(--bedi-gutter);
		pointer-events: none;
		position: fixed;
		transform: translateY(100%);
		/*
		 * Below the drawer (200) and the toast (250): a toast confirming an add
		 * must be able to sit over this bar. The fallback is --bedi-z-rail's
		 * value rather than the token itself — that token is named for the hero
		 * rail, and a future change there should not move the buy bar.
		 */
		z-index: var(--bedi-z-buybar, 40);
		/* Faster out than in — arriving is an offer, leaving should not be
		   dwelt on. */
		transition:
			opacity 180ms var(--bedi-ease-out),
			transform 180ms var(--bedi-ease-out),
			visibility 180ms var(--bedi-ease-out);
		/* visibility is what keeps it out of the tab order while hidden;
		   transform alone leaves it focusable. */
		visibility: hidden;
	}

	.bedi-buybar.is-visible {
		opacity: 1;
		pointer-events: auto;
		transform: translateY(0);
		transition:
			opacity var(--bedi-dur) var(--bedi-ease-in),
			transform var(--bedi-dur) var(--bedi-ease-in);
		visibility: visible;
	}

	@supports not (backdrop-filter: blur(1px)) {
		.bedi-buybar { background-color: var(--bedi-surface); }
	}

	.bedi-buybar__price {
		color: var(--bedi-ink);
		/*
		 * ZERO, AND THIS IS WHAT WAS PUSHING THE PRICE OFF CENTRE.
		 *
		 * It is a <p>, so it carried the 1rem paragraph bottom margin. The grid
		 * centres a MARGIN box, not a border box — so a 21px line with 16px
		 * hanging under it centres as a 37px block and the visible text ends up
		 * eight pixels high. `align-items: center` was already correct; the
		 * margin was the thing making it look wrong.
		 */
		margin: 0;
		/*
		 * A COLUMN, SO A DISCOUNT STACKS INSTEAD OF SITTING BESIDE.
		 *
		 * WooCommerce's price HTML for a sale is <del>old</del> <ins>new</ins>,
		 * which lays out inline — the struck figure ended up to the right of
		 * the real one, reading as a range rather than as a reduction, and it
		 * took horizontal room the bar does not have. Stacked, the new price
		 * leads and the old one is a small line under it, which is the order
		 * the eye wants and costs no width at all.
		 */
		display: flex;
		flex-direction: column;
		align-items: flex-start;
		font-size: var(--bedi-text-xl);
		font-weight: var(--bedi-weight-bold);
		justify-content: center;
		line-height: 1.15;
		min-inline-size: 0;
		row-gap: 1px;
	}

	/*
	 * `del` FIRST IN THE SOURCE, SECOND ON SCREEN. Woo emits the old price
	 * before the new one, so `order` puts the one that matters on top without
	 * touching markup this theme does not own.
	 */
	.bedi-buybar__price del,
	.bedi-buybar__was {
		color: var(--bedi-ink-muted);
		font-size: var(--bedi-text-sm);
		font-weight: var(--bedi-weight-regular);
		line-height: 1.1;
		order: 2;
		text-decoration: line-through;
	}

	.bedi-buybar__price ins {
		background: none;
		color: var(--bedi-ink);
		order: 1;
		text-decoration: none;
	}

	.bedi-buybar__actions {
		align-items: center;
		column-gap: 8px;
		display: flex;
		/* none, not `1 1 auto`: this column is exactly as wide as the controls
		   in it, so everything left over belongs to the price. */
		flex: none;
	}

	/*
	 * BELOW 380px THE BAR DROPS ITS STEPPER, and this is arithmetic rather
	 * than taste. At 320px: 320 − 40 of gutter = 280; the price cell takes
	 * about 60 and the column gap 12, leaving 208 for the actions. A 112px
	 * stepper plus an 8px gap leaves 88px of pill — for a label that sets at
	 * roughly 188px in Georgian. Something has to give, and it is the stepper:
	 * the quantity is still settable in the rail twenty pixels up the page,
	 * whereas the bar exists for exactly one reason, which is the action.
	 */
	@media (max-width: 23.75em) {
		.bedi-buybar .bedi-stepper,
		.bedi-buybar__qty {
			display: none;
		}
	}

	/*
	 * NARROWER. 36px buttons around a 1fr readout with a 112px floor was sized
	 * when the stepper shared the bar with a full-width button and nothing
	 * else; it is 112px of a 375px bar spent on a number that is almost always
	 * "1". 32px touch targets either side of a content-width readout gives the
	 * price back about thirty pixels and still clears the 44px tap height,
	 * because the stepper's own block-size provides that.
	 */
	.bedi-buybar .bedi-stepper {
		block-size: 44px;
		flex: none;
		grid-template-columns: 32px auto 32px;
		min-inline-size: 0;
	}

	/* A <span>, not an input: a cloned input[name=quantity] would give the form
	   two quantity fields and Woo reads the last one. */
	.bedi-buybar__qty {
		align-self: center;
		color: var(--bedi-ink);
		display: grid;
		font-size: var(--bedi-text-base);
		font-variant-numeric: tabular-nums;
		font-weight: var(--bedi-weight-medium);
		/* Two digits' worth and no more. tabular-nums means 1 and 88 occupy the
		   same box, so the bar does not reflow as the quantity climbs. */
		min-inline-size: 22px;
		padding-inline: 2px;
		place-items: center;
	}

	.bedi-buybar__cta {
		align-items: center;
		appearance: none;
		background-color: var(--bedi-accent);
		block-size: 48px;
		border: 0;
		border-radius: var(--bedi-radius-lg);
		color: var(--bedi-on-accent);
		cursor: pointer;
		display: inline-flex;
		/*
		 * A FIXED WIDTH, NOT `1 1 auto`.
		 *
		 * Growing to fill was what made this button different on every product
		 * — wide next to a short price, wider still when the stepper was
		 * hidden — and it was the thing eating the space the price needed.
		 * 124px fits `დამატება` with air around it and is the same on every
		 * page, which is what makes a fixed bar feel fixed.
		 */
		flex: none;
		font-family: var(--bedi-font-display);
		font-size: var(--bedi-text-base);
		font-weight: var(--bedi-weight-medium);
		inline-size: 124px;
		justify-content: center;
		padding-inline: var(--bedi-space-3);
		white-space: nowrap;
	}

	.bedi-buybar__cta:disabled {
		background-color: var(--bedi-surface-2);
		color: var(--bedi-ink-muted);
		cursor: not-allowed;
	}

	.bedi-buybar__cta:focus-visible {
		outline: 3px solid var(--bedi-navy);
		outline-offset: -4px;
	}
}

/* =========================================================================
 * 12. NARROW
 * ====================================================================== */

@media (max-width: 63.9375em) {
	.bedi-product__buy-card { padding: var(--bedi-space-5); }

	/*
	 * At 312 − 40 = 272px of content, a right-aligned 148px stepper leaves the
	 * label 108px and Georgian "რაოდენობა" needs 96px — too close to call. The
	 * row stacks instead.
	 */
	.bedi-stepper__row {
		align-items: stretch;
		flex-direction: column;
		row-gap: var(--bedi-space-2);
	}

	.bedi-product__buy-card .quantity {
		grid-template-columns: 48px 1fr 48px;
		inline-size: 100%;
	}
}

@media (max-width: 47.9375em) {
	.bedi-product__buy-card {
		--bedi-prod-price: 1.75rem;
	}

	.bedi-product__buy-card .quantity {
		block-size: 52px;
		grid-template-columns: 52px 1fr 52px;
	}

	/* The contact card moves to the end of the page and the rows grow for thumb
	   comfort — at 60 × 280 the tap target is comfortably over the 44px
	   minimum. */
	.bedi-contact__row { block-size: 60px; }

	/* Clear the fixed bar so the last thing on the page is reachable. */
	.bedi-product { padding-block-end: 88px; }

	/*
	 * THE CONSULTATION DOCK STEPS OVER THE BUY BAR — AND THAT IS NO LONGER
	 * DECIDED HERE.
	 *
	 * This used to be `body.single-product { --bedi-dock-offset: 80px }`: a
	 * single number covering one bar's height plus a gap, written when the buy
	 * bar was the only thing fixed to the bottom of a phone screen. The mobile
	 * bottom bar is now under it, so 80px put the dock squarely across the
	 * add-to-cart button — and because it was set on `body` it beat the `:root`
	 * value that knew about both bars, by proximity rather than by any intent.
	 *
	 * The value now lives once, in mobile-bar.css, as
	 * `--bedi-bottombar-h + --bedi-buybar-h + a gap`. --bedi-buybar-h is
	 * published by product-buy.js from THIS bar's measured height, so the
	 * mechanism is still owned by the buy bar — it just reports its height
	 * instead of asserting a total. Two bars that each know their own size beat
	 * one constant that has to know both.
	 */
}

/* =========================================================================
 * 13. REDUCED MOTION
 *
 * The COLOURS all remain — they carry the meaning. Only the motion, which
 * carries the pleasure, is removed.
 * ====================================================================== */

@media (prefers-reduced-motion: reduce) {
	.bedi-stepper__glyph,
	.bedi-cta__icon,
	.bedi-cta__label,
	.bedi-buyrail__instal-chev,
	.bedi-buyrail__instal-panel,
	.bedi-contact__tile,
	.bedi-contact__chev,
	.bedi-buyrail__auxbtn,
	.bedi-buybar,
	.bedi-product form.cart button.single_add_to_cart_button,
	.bedi-product form.cart button.bedi-buy-now {
		transition-duration: 1ms !important;
	}

	.bedi-stepper__btn:active:not(:disabled) .bedi-stepper__glyph,
	.bedi-product form.cart button.single_add_to_cart_button:hover,
	.bedi-product form.cart button.single_add_to_cart_button:active,
	.bedi-product form.cart button.single_add_to_cart_button:hover .bedi-cta__icon,
	.bedi-product form.cart button.single_add_to_cart_button:hover .bedi-cta__label,
	.bedi-product form.cart button.bedi-buy-now:active,
	.bedi-buyrail__auxbtn:active,
	.bedi-contact__row:hover .bedi-contact__chev,
	.bedi-contact__row:focus-visible .bedi-contact__chev,
	.bedi-buybar.is-visible,
	.bedi-buybar {
		transform: none !important;
	}

	.bedi-product__chip--low .bedi-product__dot,
	.bedi-stepper.is-up .bedi-stepper__ghost,
	.bedi-stepper.is-down .bedi-stepper__ghost,
	.bedi-stepper.is-up .qty,
	.bedi-stepper.is-down .qty,
	.bedi-stepper.is-refused,
	.bedi-cta__dot,
	.single_add_to_cart_button.is-done .bedi-cta__check path,
	.single_add_to_cart_button.is-error,
	.bedi-buyrail__auxbtn--wish:hover .bedi-buyrail__auxicon,
	.bedi-buyrail__auxbtn--wish.is-active .bedi-buyrail__auxicon svg,
	.bedi-buyrail__auxbtn--wish.is-active::after,
	.bedi-product__buy-card .woocommerce-variation-price.is-swapped .price {
		animation: none !important;
	}

	/* The low-stock state must still be visually distinct from in-stock once the
	   pulse is gone. */
	.bedi-product__chip--low .bedi-product__dot {
		box-shadow: 0 0 0 2px var(--bedi-pulse-ring);
	}

	/* A static ellipsis rather than three pulsing dots. */
	.bedi-cta__dot { opacity: 0.7; }
}

/* =========================================================================
 * 14. FORCED COLOURS
 *
 * Every fill in this file is discarded here, so each object that was defined by
 * its fill needs a border to stay an object.
 * ====================================================================== */

@media (forced-colors: active) {
	.bedi-product__buy-card,
	.bedi-product__buy-card .quantity,
	.bedi-woo .bedi-stepper,
	.bedi-product__chip,
	.bedi-product__dot,
	.bedi-product__save,
	.bedi-buyrail__auxbtn,
	.bedi-buyrail__mark,
	.bedi-contact__tile,
	.bedi-product form.cart button.single_add_to_cart_button,
	.bedi-product form.cart button.bedi-buy-now,
	.bedi-buybar__cta {
		border: 1px solid ButtonText;
	}

	/*
	 * Without this the three zones of the stepper are indistinguishable once
	 * the hover fill is gone. ONE edge each, not `border-inline` on both: the
	 * shell already has a border, and bordering both sides of both buttons
	 * doubles the hairline at the shell's own outer edges.
	 */
	.bedi-stepper__btn--minus { border-inline-end: 1px solid ButtonText; }
	.bedi-stepper__btn--plus  { border-inline-start: 1px solid ButtonText; }

	.bedi-stepper__btn:disabled { color: GrayText; }

	.bedi-buybar { border-block-start: 1px solid ButtonText; }

	.single_add_to_cart_button.is-done,
	.bedi-buyrail__auxbtn--wish[aria-pressed="true"] {
		border: 2px solid Highlight;
	}

	/* Brand marks must not be inverted into illegibility, and filled-vs-outline
	   is the whole wishlist state. */
	.bedi-buyrail__mark img,
	.bedi-buyrail__keepz,
	.bedi-buyrail__auxbtn--wish[aria-pressed="true"] .bedi-buyrail__auxicon svg path {
		forced-color-adjust: none;
	}
}

/* =========================================================================
 * 15. PRINT
 * ====================================================================== */

@media print {
	.bedi-product__buy-card {
		background: none;
		border: 1px solid var(--bedi-rule);
	}

	.bedi-buybar,
	.bedi-buyrail__aux,
	.bedi-stepper__row,
	.bedi-product form.cart button.single_add_to_cart_button,
	.bedi-product form.cart button.bedi-buy-now {
		display: none !important;
	}
}

/* =========================================================================
 * THE BUY CARD ON A PHONE
 *
 * The rail on a phone is one column of a scrolling page rather than a sticky
 * panel beside the photograph, so the rhythm that reads as considered on a
 * desktop reads as padding here: a label, a divider and a full-width row for a
 * number that is almost always 1.
 * ====================================================================== */

@media (max-width: 47.9375em) {

	/*
	 * The label goes. "რაოდენობა" over a stepper with a minus, a number and a
	 * plus is naming something already unmistakable, and it cost a whole line.
	 * The control keeps its accessible name through the group's aria-label, so
	 * nothing is lost to a screen reader.
	 */
	.bedi-stepper__label {
		display: none;
	}

	/*
	 * The hairline above the quantity goes with it. It was separating the price
	 * from the quantity — two things that now sit on ONE line, where a rule
	 * between them would be drawn through the middle of a row.
	 */
	.bedi-stepper__row.bedi-buyrail__sep {
		border-block-start: 0;
		padding-block-start: 0;
	}

	/*
	 * AND THE QUANTITY MOVES UP BESIDE THE PRICE.
	 *
	 * The price row is full width and short — "390,00 ₾" — so the right half of
	 * it is empty. Pulling the quantity row up by its own height puts the
	 * stepper in that space and gives the card back a line.
	 *
	 * A negative margin rather than absolute positioning or `display: contents`
	 * on the form: the first would need a hard-coded offset to the price's
	 * baseline, and the second is known to break form submission in some
	 * engines. This is a checkout path, so neither is worth the cleverness.
	 * The row keeps its own height, so if a long price ever wraps to two lines
	 * the stepper is pushed back down rather than sitting on top of it.
	 */
	.bedi-stepper__row {
		display: flex;
		/*
		 * `row`, STATED. The desktop rule makes this column — label above
		 * control — and not restating it here was the whole problem: in a
		 * column flex `justify-content` runs vertically and `align-items` runs
		 * horizontally, so the `flex-end` below did nothing to the horizontal
		 * placement and the `center` two lines down was what kept parking the
		 * stepper in the middle of the price.
		 */
		flex-direction: row;
		justify-content: flex-end;
		/*
		 * -36px, and the arithmetic is: with the divider's padding removed the
		 * row already sits flush under the price, so it has to come up by the
		 * price's own line box (29px at --bedi-text-2xl) and then half the
		 * difference between the two heights — (44 − 29) / 2 ≈ 7px — to sit
		 * centred on it rather than hanging off the bottom. 29 + 7 = 36.
		 *
		 * The first attempt pulled up by the row's height plus the row gap and
		 * overshot by 28px, landing the stepper ABOVE the price instead of
		 * beside it.
		 */
		margin-block-start: -36px;
		min-block-size: 44px;
		align-items: center;
	}

	/* Smaller, for the same reason as the floating bar's: a two-digit number
	   does not need 112px of chrome around it. */
	/*
	 * PINNED TRACKS AND A MATCHING max-inline-size.
	 *
	 * `auto` for the middle track does not mean "as small as the content" when
	 * the grid has room to spare: the base rule caps the shell at 148px, the
	 * two 32px buttons take 64, and the auto track absorbed the remaining 82 —
	 * so the stepper stayed 148px wide and sat on top of the price.
	 *
	 * 36px holds three digits at 16px tabular, which is more quantity than this
	 * shop's stock allows on any line.
	 */
	.bedi-stepper__row .bedi-stepper {
		block-size: 40px;
		flex: none;
		grid-template-columns: 32px 36px 32px;
		/*
		 * `auto 0`, NOT the row's justify-content.
		 *
		 * The shell carries `margin-inline: auto` from its desktop rule, and an
		 * auto margin wins over justify-content in flex — so the row said
		 * flex-end, the margin said centre, and the margin won: the stepper sat
		 * in the middle of the row on top of the price. Setting the start
		 * margin to auto and the end margin to zero pushes it right through the
		 * same mechanism that was fighting it.
		 */
		margin-inline: auto 0;
		max-inline-size: 100px;
		min-inline-size: 0;
	}

	/*
	 * And the price is stopped short of it. Without this a four-figure price on
	 * a discounted line would run underneath the stepper rather than wrapping,
	 * because the two are on the same line by a negative margin and neither
	 * knows the other is there.
	 */
	.bedi-product__buy-card .price {
		max-inline-size: calc(100% - 116px);
	}

	.bedi-stepper__row .bedi-stepper .qty {
		font-size: var(--bedi-text-base);
		inline-size: 2.25rem;
	}

	/*
	 * The price steps down one notch. It is still the biggest thing in the
	 * card, but it no longer has the row to itself and a 30px figure beside a
	 * 40px control was top-heavy.
	 */
	.woocommerce div.product .bedi-product__buy-card p.price,
	.woocommerce-page div.product .bedi-product__buy-card p.price,
	.bedi-product__buy-card .price {
		font-size: var(--bedi-text-2xl);
	}

	/*
	 * Room above the title. It was sitting hard against the breadcrumb with
	 * nothing between them, so the two read as one block of small text with a
	 * big line in it.
	 */
	.bedi-product__head {
		margin-block-start: var(--bedi-space-4);
	}
}
