/* Single product summary column - title, SKU, price, availability, quantity,
 * buy buttons and the SD Dollars note.
 * Enqueued on is_product() by functions/product-page.php.
 *
 * Same dispatch-dock language as the legal / funding / quoting / AIMS page
 * systems (css/sd-quotes.css et al): chalk ground, hairline borders, no
 * radius, Archivo set as dock stencil for labels, and figures on tabular
 * numerals. This panel had been left out of that 2026-08 redesign wave; this
 * brings it in.
 *
 * The one bold move is the PURCHASE TRAY: the availability line stops being a
 * sentence floating above the controls and becomes the tray's head, with a 3px
 * top rule in the state's colour that also sets the tray's border. Stock state
 * is what a school buying kit against a tournament date actually needs to read
 * first, so it is the loudest structure in the panel rather than the price.
 * Every other element is deliberately quiet type.
 *
 * Colours come from the house palette already defined across css/sd-*.css.
 * The --pi-state-* trio is switched by :has() on the availability paragraph's
 * own classes, which functions/product-page.php and
 * functions/product-availability.php already emit - so all eight availability
 * states drive the tray without any new markup.
 *
 * Supersedes blocks removed from style.css on 2026-09-01 (each left a pointer
 * comment at its old position): the product title/price margins, the price
 * font-size, the SD Dollars notice typography, the in-stock / low-stock /
 * out-of-stock badges and the eight sd-eta state badges. The form.cart flex
 * layout, the progress-btn animation rules, the SKU de-duplication rules and
 * the p.stock.sd-eta un-hide rule all stay in style.css and are extended, not
 * replaced, here.
 */

.single-product .product_infos {
	--pi-ink: #1b1b1a;
	--pi-ink-soft: #4a4746;
	--pi-border: #e4e0d8;
	--pi-chalk: #f7f5ef;
	--pi-gold: #f5a623;
	--pi-gold-ink: #8a5600;
	--pi-gold-tint: #fbf1e1;
	--pi-gold-line: #eddcb9;
	--pi-red: #ef4135;          /* brand red - buttons only */
	--pi-red-dark: #c62d1f;
	--pi-red-ink: #b8240c;      /* AA-safe red for text/links on white */
	--pi-blue: #0066b4;         /* YITH quote button colour, matched here */
	--pi-blue-dark: #044a80;

	--pi-font-head: 'Archivo', Arial, Helvetica, sans-serif;
	--pi-font-body: 'Montserrat', Arial, Helvetica, sans-serif;
	--pi-font-code: ui-monospace, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;

	/* Width of the redesigned quantity stepper (34 + 42 + 34 + 2px border).
	   The narrow-screen quote-button offset in style.css was written against
	   the old 85px widget, so it is recalculated from this at the bottom of
	   this file - keep the two in step. */
	--pi-qty-w: 112px;

	/* Fallback availability state: anything the map below doesn't recognise
	   (a bare .available-on-backorder, say) still gets a complete tray. */
	--pi-state: #4a4746;
	--pi-state-tint: #f7f5ef;
	--pi-state-line: #e4e0d8;
}

/* ---- SKU: the panel's eyebrow -------------------------------------------
   Moved above the H1. A product code is the first thing a school or club
   buyer matches against a catalogue page or a previous order, so it leads the
   panel rather than trailing the title as a footnote. The gold tick + stencil
   label is the same eyebrow device the sd-quotes / sd-funding / sd-legal page
   systems use, and the code itself is set in the house mono stack because it
   is data, not prose.

   Variable products lead with it too. Their .sku is rendered empty and only
   filled by WooCommerce's variation JS (see sd_sku_below_title()), so the
   chip holds its place with a dash until a variation is picked rather than
   being hidden and dropped in afterwards - which would have shoved the title
   and everything under it down mid-interaction. The dash is also true: on this
   catalogue every size carries its own code (AIMS-ETXS, AIMS-ETS ...), so
   there is no product-level answer to give until one is chosen. */
.single-product .product_summary_middle {
	display: flex;
	flex-direction: column;
}
.single-product .product_meta.product_meta--below-title {
	order: -1;
	margin: 0 0 16px;
	padding: 0;
	font-size: inherit;
	line-height: 1.2;
}

/* style.css hides the wrapper outright while the code is empty, which was
   right when the chip sat under the title and could simply appear. Now that it
   leads the panel it has to keep its place instead. */
.single-product .product_infos .product_meta--below-title .sku_wrapper:has(.sku:empty) {
	display: inline-flex;
}
.single-product .product_infos .product_meta--below-title .sku:empty::before {
	content: "\2014"; /* em dash - the code is pending, not missing */
	color: #9c968c;
	font-weight: 400;
}

.single-product .product_meta--below-title .sku_wrapper {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	font-size: inherit;
}

.single-product .product_meta--below-title .sd-sku-label {
	display: inline-flex;
	align-items: center;
	gap: 9px;
	font-family: var(--pi-font-head);
	font-weight: 700;
	font-size: 11px;
	line-height: 1;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--pi-ink-soft);
}
.single-product .product_meta--below-title .sd-sku-label::before {
	content: "";
	flex: none;
	width: 20px;
	height: 3px;
	background: var(--pi-gold);
}

.single-product .product_meta--below-title .sku {
	font-family: var(--pi-font-code);
	font-variant-numeric: tabular-nums;
	font-weight: 700;
	font-size: 13px;
	line-height: 1;
	letter-spacing: 0.04em;
	text-transform: none;
	color: var(--pi-ink);
	background: var(--pi-chalk);
	border: 1px solid var(--pi-border);
	padding: 5px 9px;
}

/* ---- Title --------------------------------------------------------------
   Down from the theme's 44px, which pushed this product's name onto three
   lines and made the title compete with the price and the buy controls for
   the top of the panel. Archivo at a tight 1.12 keeps it to two lines at
   every desktop width while still reading as the panel's headline.
   The #content variants are not decoration: the Customizer prints its title
   size as '.woocommerce #content div.product .product_title' inside a
   min-width:1024px media query, and an ID selector cannot be out-specified by
   classes alone. Matching its shape and adding to it is cheaper to read than
   an !important. */
.woocommerce #content div.product .product_summary_middle h1.product_title.entry-title,
.woocommerce-page #content div.product .product_summary_middle h1.product_title.entry-title,
.woocommerce div.product .product_summary_middle h1.product_title.entry-title,
.woocommerce-page div.product .product_summary_middle h1.product_title.entry-title {
	font-family: var(--pi-font-head);
	font-weight: 700;
	font-size: clamp(24px, 2.1vw, 30px);
	line-height: 1.14;
	letter-spacing: -0.015em;
	text-transform: none;
	color: var(--pi-ink);
	margin: 0 0 20px;
}

/* ---- Price --------------------------------------------------------------
   The figure is the panel's one display number, so it stays in Archivo (the
   display face) on tabular numerals, not in the mono stack the house uses for
   data cells - the GST line under it is the data cell, and the two are set
   apart deliberately. The currency symbol drops to half size and rides the
   cap line so "$" reads as a mark on the figure rather than a character in
   it; the negative word-spacing closes the non-breaking space WooCommerce's
   "left with space" currency position writes between them. */
.product_layout_classic .product_content_wrapper .product_infos p.price {
	font-family: var(--pi-font-head);
	font-variant-numeric: tabular-nums;
	font-weight: 700;
	/* !important only because the parent theme's
	   wc-product-layout-default.css sets '.product_layout_classic
	   .product_content_wrapper .product_infos .price {font-size:22px
	   !important}' - the rule this file's price block replaces carried the
	   same flag for the same reason. */
	font-size: clamp(26px, 2.4vw, 32px) !important;
	line-height: 1;
	letter-spacing: -0.02em;
	color: var(--pi-ink);
	margin: 0;
	padding: 0 0 13px;
}
.product_layout_classic .product_content_wrapper .product_infos p.price bdi {
	/* Closes the non-breaking space WooCommerce's "left with space" currency
	   position writes between the symbol and the figure. */
	word-spacing: -0.22em;
}
.product_layout_classic .product_content_wrapper .product_infos p.price .woocommerce-Price-currencySymbol {
	font-size: 0.55em;
	font-weight: 700;
	vertical-align: 0.5em;
	color: var(--pi-ink-soft);
	word-spacing: normal;
}

/* The price is ink, not brand red.
   WooCommerce ships '.woocommerce div.product p.price {color:#77a464}' and the
   Customizer's inline accent CSS repaints it #ef4135 at the same (0,3,2)
   specificity this file's layout rule above cannot beat. Red here also put the
   figure at ~4.2:1 on white - under AA for text - and set it shouting against
   the Add to Cart button, which is the only thing on the panel that should be
   red. Body class included purely to out-specify both. */
body.single-product.woocommerce .product_layout_classic div.product .product_infos p.price,
body.single-product.woocommerce .product_layout_classic div.product .product_infos p.price .woocommerce-Price-amount,
body.single-product.woocommerce .product_layout_classic div.product .product_infos p.price bdi {
	color: var(--pi-ink);
}
body.single-product.woocommerce .product_layout_classic div.product .product_infos p.price .woocommerce-Price-currencySymbol {
	color: var(--pi-ink-soft);
}
body.single-product.woocommerce .product_layout_classic div.product .product_infos p.price ins,
body.single-product.woocommerce .product_layout_classic div.product .product_infos p.price ins .woocommerce-Price-amount,
body.single-product.woocommerce .product_layout_classic div.product .product_infos p.price ins bdi {
	color: var(--pi-red-ink);
}

/* Sale prices: the struck-through original is data about the discount, so it
   goes to the mono stack at a size that cannot be mistaken for the figure. */
.product_layout_classic .product_content_wrapper .product_infos p.price del {
	font-family: var(--pi-font-code);
	font-size: 0.42em;
	font-weight: 400;
	color: var(--pi-ink-soft);
	opacity: 1;
	margin-right: 10px;
	vertical-align: 0.32em;
}
.product_layout_classic .product_content_wrapper .product_infos p.price ins {
	background: none;
	text-decoration: none;
	color: var(--pi-red-ink);
}

/* ---- GST line -----------------------------------------------------------
   A hairline-ruled row under the figure carrying both GST readings: incl on
   the left because that is the figure above it, excl on the right because
   that is the number a GST-registered school or club puts on a budget line.
   Rendered by sd_price_gst_breakdown() in functions/product-page.php, which
   only runs where a single settled price exists - see the note there. */
.single-product .product_infos .sd-price-gst {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 4px 18px;
	margin: 0 0 24px;
	padding: 10px 0 0;
	border-top: 1px solid var(--pi-border);
	font-family: var(--pi-font-head);
	font-weight: 700;
	font-size: 11px;
	line-height: 1.2;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--pi-ink-soft);
}
.single-product .product_infos .sd-price-gst__amount {
	margin-right: 7px;
	font-family: var(--pi-font-code);
	font-variant-numeric: tabular-nums;
	font-size: 12.5px;
	letter-spacing: 0.02em;
	color: var(--pi-ink);
}
.single-product .product_infos .sd-price-gst__amount .woocommerce-Price-amount,
.single-product .product_infos .sd-price-gst__amount bdi {
	word-spacing: -0.45em;
	font-size: inherit;
	font-weight: inherit;
	color: inherit;
}
.single-product .product_infos .sd-price-gst__amount .woocommerce-Price-currencySymbol {
	word-spacing: normal;
}

/* Same trap as the line total: the display:flex above outranks [hidden]. */
.single-product .product_infos .sd-price-gst[hidden] {
	display: none;
}

/* ---- Waiting on a choice ------------------------------------------------
   WooCommerce marks both buy buttons .disabled until a variation is picked,
   and the theme fades them to 50% opacity - which leaves white lettering at
   about 2:1 on a washed brand red, and reads as a rendering fault rather than
   as "not yet". An inert control should look inert: chalk ground, muted ink,
   the same hairline as everything else in the tray. */
.woocommerce div.product form.cart .single_add_to_cart_button.disabled,
.woocommerce div.product form.cart .single_add_to_cart_button.wc-variation-selection-needed,
.woocommerce div.product form.cart .yith-ywraq-add-to-quote .add-request-quote-button.disabled,
.woocommerce div.product .product_infos > .yith-ywraq-add-to-quote .add-request-quote-button.disabled {
	background: var(--pi-chalk) !important;
	/* Border and opacity carry the flag for the same reason the background
	   does: YITH sets both on this button with !important, which left the
	   inert state at 50% opacity behind a blue edge - the one thing the
	   treatment was there to stop. */
	border: 1px solid var(--pi-border) !important;
	color: #8d877e !important;
	opacity: 1 !important;
	cursor: not-allowed;
}
.woocommerce div.product form.cart .single_add_to_cart_button.disabled:hover,
.woocommerce div.product form.cart .single_add_to_cart_button.wc-variation-selection-needed:hover,
.woocommerce div.product form.cart .yith-ywraq-add-to-quote .add-request-quote-button.disabled:hover {
	background: var(--pi-chalk) !important;
	color: #8d877e;
}

/* The theme's own "inc GST" suffix would repeat what the row above already
   says, so it is dropped wherever the row rendered - and restyled as a
   stencil label wherever it did not (variable products, whose price is
   rewritten by WooCommerce's variation JS and so has no static breakdown). */
.single-product .product_infos:has(.sd-price-gst) p.price .woocommerce-price-suffix {
	display: none;
}
.single-product .product_infos p.price small.woocommerce-price-suffix {
	font-family: var(--pi-font-head);
	font-weight: 700;
	font-size: 11px;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--pi-ink-soft);
	vertical-align: 0.42em;
	margin-left: 9px;
	word-spacing: normal;
}
.single-product .product_infos:not(:has(.sd-price-gst)) p.price {
	padding-bottom: 0;
	margin-bottom: 24px;
}

/* ---- Price breaks ------------------------------------------------------
   The quantity ladder, moved up under the price it explains (see
   functions/quantity-pricing.php) from where it used to sit as a loose table
   below the buy button. A rung is a target, not a caption: each row sets the
   quantity to its lower bound, and the rung the current quantity falls on is
   marked. js/sd-price-ladder.js does the re-pricing; without it the rows are
   the same server-rendered figures, inert.

   Numbers in the mono stack on tabular figures, headers in Archivo stencil
   caps - the house treatment for a data table, and the reason the ladder can
   sit this close to the display-face price figure without the two competing. */
.single-product .product_infos .sd-ladder {
	margin: 0 0 24px;
	border: 1px solid var(--pi-border);
	background: #fff;
}
/* Deliberately no coloured top rule, unlike the availability board below it.
   Gold is the panel's money thread - the SKU tick, the SD Dollars note, and
   here the rung the quantity actually falls on. Giving the whole table a gold
   edge as well would stack two coloured rules a few pixels apart and spend the
   accent where it carries nothing. */

.single-product .product_infos .sd-ladder__title {
	margin: 0;
	padding: 11px 14px 10px;
	border-bottom: 1px solid var(--pi-border);
	font-family: var(--pi-font-head);
	font-weight: 700;
	font-size: 11px;
	line-height: 1;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--pi-ink-soft);
}

.single-product .product_infos table.sd-ladder__table {
	width: 100%;
	margin: 0;
	border: 0;
	border-collapse: collapse;
	table-layout: fixed;
	font-family: var(--pi-font-code);
	font-variant-numeric: tabular-nums;
}

.single-product .product_infos table.sd-ladder__table th,
.single-product .product_infos table.sd-ladder__table td {
	border: 0;
	padding: 9px 14px;
	text-align: left;
	vertical-align: middle;
}

.single-product .product_infos table.sd-ladder__table th {
	font-family: var(--pi-font-head);
	font-weight: 700;
	font-size: 10px;
	line-height: 1;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--pi-ink-soft);
	padding-top: 11px;
	padding-bottom: 7px;
}

.single-product .product_infos table.sd-ladder__table td {
	font-size: 13px;
	line-height: 1.2;
	color: var(--pi-ink-soft);
	border-top: 1px solid var(--pi-rule, #f0ede6);
}

.single-product .product_infos .sd-ladder__qty {
	font-weight: 700;
	color: var(--pi-ink);
}
.single-product .product_infos .sd-ladder__each {
	text-align: right;
	font-weight: 700;
	color: var(--pi-ink);
}
.single-product .product_infos table.sd-ladder__table th:last-child {
	text-align: right;
}

/* The rung the current quantity falls on. A tinted row plus one gold marker
   in the gutter - enough to find at a glance, quiet enough that four of these
   stacked do not read as four buttons. */
.single-product .product_infos .sd-ladder__row.is-active td {
	background: var(--pi-gold-tint);
	color: var(--pi-ink);
}
.single-product .product_infos .sd-ladder__row.is-active .sd-ladder__qty {
	position: relative;
	box-shadow: inset 3px 0 0 var(--pi-gold);
}

.single-product .product_infos .sd-ladder__row.is-clickable {
	cursor: pointer;
	transition: background-color 0.12s ease;
}
.single-product .product_infos .sd-ladder__row.is-clickable:hover td {
	background: var(--pi-chalk);
}
.single-product .product_infos .sd-ladder__row.is-clickable.is-active:hover td {
	background: var(--pi-gold-tint);
}
.single-product .product_infos .sd-ladder__row.is-clickable:focus-visible {
	outline: 3px solid var(--pi-ink);
	outline-offset: -3px;
}

.single-product .product_infos .sd-ladder__note {
	margin: 0;
	padding: 9px 14px 11px;
	border-top: 1px solid var(--pi-border);
	background: var(--pi-chalk);
	font-family: var(--pi-font-body);
	font-size: 11.5px;
	line-height: 1.4;
	color: var(--pi-ink-soft);
}

/* ---- Line total --------------------------------------------------------
   Printed inside the tray, under the controls, only once the quantity passes
   one - the panel's answer to the question the ladder raises. Kept as plain
   arithmetic rather than a labelled "subtotal": the multiplication says what
   it is, and this is not the cart. */
.single-product form.cart .sd-line-total {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 8px 16px;
	flex: 1 0 100%;
	margin: 12px 0 0;
	padding: 11px 0 0;
	border-top: 1px solid var(--pi-border);
	font-family: var(--pi-font-code);
	font-variant-numeric: tabular-nums;
	font-size: 13px;
	line-height: 1.2;
	color: var(--pi-ink-soft);
}
.single-product form.cart .sd-line-total__value {
	font-weight: 700;
	color: var(--pi-ink);
}
/* display:flex above outranks the [hidden] attribute's own display:none, so
   the empty total left a stray rule across the tray at quantity one. */
.single-product form.cart .sd-line-total[hidden] {
	display: none;
}

/* ---- Variable products -------------------------------------------------
   The stock select becomes a row of chips, built over the top of it by
   js/sd-price-ladder.js. The select keeps its name and stays the source of
   truth, so this is presentation only: with the script blocked the page falls
   back to the select, which is why the hide is scoped to .sd-has-chips - a
   class the script only adds once the chips exist. */
.single-product .product_infos form.variations_form.sd-has-chips select.sd-select-replaced,
.single-product .product_infos form.variations_form.sd-has-chips .reset_variations {
	position: absolute !important;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
	white-space: nowrap;
}

.single-product .product_infos table.variations,
.single-product .product_infos table.variations tbody,
.single-product .product_infos table.variations tr,
.single-product .product_infos table.variations th,
.single-product .product_infos table.variations td {
	display: block;
	width: auto;
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
}
.single-product .product_infos table.variations {
	margin: 0 0 12px;
}
.single-product .product_infos table.variations tr + tr {
	margin-top: 14px;
}
.single-product .product_infos table.variations th.label label {
	display: block;
	margin: 0 0 9px;
	font-family: var(--pi-font-head);
	font-weight: 700;
	font-size: 11px;
	line-height: 1;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--pi-ink-soft);
}

.single-product .product_infos .sd-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
}

.single-product .product_infos .sd-chip {
	min-width: 46px;
	min-height: 42px;
	padding: 0 12px;
	border: 1px solid var(--pi-border);
	border-radius: 0;
	background: #fff;
	box-shadow: none;
	font-family: var(--pi-font-head);
	font-variant-numeric: tabular-nums;
	font-weight: 700;
	font-size: 13px;
	line-height: 1;
	letter-spacing: 0.02em;
	text-transform: none;
	color: var(--pi-ink);
	cursor: pointer;
	transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.single-product .product_infos .sd-chip:hover:not(:disabled) {
	border-color: var(--pi-ink);
}
.single-product .product_infos .sd-chip.is-selected {
	background: var(--pi-ink);
	border-color: var(--pi-ink);
	color: #fff;
}
/* Struck through rather than merely greyed: at a glance the row should read
   as "these sizes, not those", which a 40% opacity does not carry on its own. */
.single-product .product_infos .sd-chip.is-unavailable,
.single-product .product_infos .sd-chip:disabled {
	background: var(--pi-chalk);
	border-color: var(--pi-border);
	color: #a9a49b;
	text-decoration: line-through;
	cursor: not-allowed;
}
.single-product .product_infos .sd-chip:focus-visible {
	outline: 3px solid var(--pi-ink);
	outline-offset: 2px;
}

/* ---- Variable products: the buy row -------------------------------------
   style.css pins the quote button at a fixed 170px inside a variations form.
   That was right when it was written - it was the only thing there that could
   be sized - but its neighbour is not fixed: .variations_button is
   flex:1 1 auto, so as the panel widens Add to Cart grows and the quote button
   does not. They drift further apart the wider the column gets, and at the
   widths where the pair stops fitting the quote drops to a short, left-aligned
   row of its own.

   The cause is nesting, not sizing. The quantity and Add to Cart live inside
   .variations_button while the quote button is that div's sibling, so the two
   buttons are never items of the same flex row and cannot share it as equals.
   display:contents dissolves that box - the same move .bundle_wrap already
   uses in style.css for the identical problem on bundles - after which both
   buttons take the flex:1 1 0 a simple product gives them and the row matches
   a simple product's exactly. Verified safe: WooCommerce writes no inline
   display to .variations_button or .single_variation_wrap through
   found_variation or reset_data. */
.single-product .product_infos form.cart.variations_form .variations_button {
	display: contents;
}
.single-product .product_infos form.cart.variations_form .variations_button .quantity {
	flex: 0 0 auto;
	margin: 0 !important;
}
.single-product .product_infos form.cart.variations_form .variations_button .single_add_to_cart_button,
.single-product .product_infos form.cart.variations_form .single_variation_wrap > .yith-ywraq-add-to-quote {
	flex: 1 1 0;
	width: auto !important;
	min-width: 0 !important;
	margin: 0 !important;
}

/* style.css pads this button to 18px/15px to reach the height the old fixed
   layout needed. The button is a 50px flex box centring its own label now, and
   the extra padding only makes it taller than the one beside it. */
.single-product .product_infos form.cart.variations_form .yith-ywraq-add-to-quote .add-request-quote-button {
	padding: 0 10px !important;
}

/* Narrow screens: the quote button takes its own row, indented so its left
   edge lines up under Add to Cart rather than under the stepper - the same
   treatment simple products get. style.css states this as a bare 85px, which
   was the old quantity widget's width; the redesigned stepper is --pi-qty-w. */
@media all and (max-width: 640px) {
	.single-product .product_infos form.cart.variations_form .single_variation_wrap > .yith-ywraq-add-to-quote {
		flex: 1 0 calc(100% - (var(--pi-qty-w) + 8px));
		margin-left: calc(var(--pi-qty-w) + 8px) !important;
	}
}

/* ---- The variation's state band ----------------------------------------
   One slot, two occupants. Before a choice it holds the prompt; after one it
   holds that variation's own availability line, written in from
   variation.availability_html by the script - the same <p class="stock ...">
   markup a simple product renders, so it arrives carrying the state class and
   picks up the state colours already defined on p.stock further up this file.
   Nothing has to be duplicated onto the wrapper.

   It sits below the attribute row, because the stock being reported is the
   stock of the size you just picked - stating it above the sizes put the
   answer before the question. Rendered first (the only hook inside the form
   above the attribute table) and moved down with order, which is free here:
   form.cart is already a flex container.

   Every child of that flex container needs flex-basis:100%, or it shrinks to
   its content and the band stops halfway across the tray. */
.single-product .product_infos form.variations_form > table.variations {
	flex: 1 0 100%;
	order: 1;
}
.single-product .product_infos form.variations_form > .sd-variation-head {
	flex: 1 0 100%;
	order: 2;
}
.single-product .product_infos form.variations_form > .single_variation_wrap {
	flex: 1 0 100%;
	order: 3;
}
/* Appended by the script, so it has no order of its own and would otherwise
   default to 0 and jump above the attribute row. */
.single-product .product_infos form.variations_form > .sd-line-total {
	order: 4;
}

.single-product .product_infos .sd-variation-head.is-empty {
	display: none;
}

.single-product .product_infos .sd-variation-head p.stock,
.single-product .product_infos form.variations_form .sd-variation-prompt {
	/* Full-bleed to the tray's inner edges (it has 12px of padding), so the
	   band reads as a division of the tray rather than a paragraph inside it.
	   The 4px verticals ride on the flex container's own 8px gap. */
	margin: 4px -12px;
	padding: 13px 15px;
	border-top: 1px solid var(--pi-border);
	border-bottom: 1px solid var(--pi-border);
}
.single-product .product_infos .sd-variation-head p.stock {
	background: var(--pi-state-tint);
	border-top: 3px solid var(--pi-state);
}

/* The original copy, three levels down inside .single_variation. Hidden only
   once the script has actually filled the head, so a blocked script leaves
   WooCommerce's own rendering intact rather than swallowing it. */
.single-product .product_infos.sd-has-variation .woocommerce-variation-availability {
	display: none;
}

.single-product .product_infos form.variations_form .sd-variation-prompt {
	display: flex;
	align-items: center;
	gap: 10px;
	background: var(--pi-chalk);
	font-family: var(--pi-font-body);
	font-weight: 700;
	font-size: 13px;
	line-height: 1.35;
	color: var(--pi-ink-soft);
}
.single-product .product_infos form.variations_form .sd-variation-prompt::before {
	content: "\f0ca"; /* FA5 list-ul - a choice to make, not a warning */
	font-family: "Font Awesome 5 Free";
	font-weight: 900;
	font-size: 14px;
	line-height: 1;
	flex: none;
}

/* WooCommerce prints the chosen variation's own price inside the tray. The
   headline figure above is now that same number (the script writes it there on
   found_variation), so this one would be the page saying it twice. */
.single-product .product_infos .woocommerce-variation-price {
	display: none;
}

.single-product .product_infos .woocommerce-variation.single_variation {
	margin: 0;
}
.single-product .product_infos .woocommerce-variation-availability {
	margin: 0 0 12px;
}

/* ---- Availability ------------------------------------------------------
   Two treatments off one colour map. The paragraph that sits directly in the
   summary column becomes the head of the purchase tray - state tint, a 3px
   top rule in the state's colour, neutral sides that line up with the tray
   below it. This is the same board chrome the quoting and funding pages use
   (neutral hairline, one coloured rule along the top), so the panel reads as
   part of the same document family.

   The same paragraph also renders nested - inside a variations form, a
   bundled item's cart details, a composited product's details - where a box
   inside a box would be wrong. Those get the colour and the icon only.

   The state colours live on the paragraph rather than on the panel so both
   treatments inherit them, and so a variation's own state can differ from the
   parent product's without a second map. */
.single-product .product_infos p.stock {
	--pi-state: #55606e;
	--pi-state-tint: #f1f3f5;
}
.single-product .product_infos p.stock.in-stock {
	/* The house green (#018436) lands at 4.40:1 on its own tint - just under
	   AA for text this size, since 13.5px bold is not "large" by WCAG. The
	   dark variant already in the palette clears it at 6.2:1 and is close
	   enough that the rule and the text still read as one colour. */
	--pi-state: #01682b;
	--pi-state-tint: #eaf4ee;
}
.single-product .product_infos p.stock.in-stock.low-stock {
	--pi-state: #8a5600;
	--pi-state-tint: #fbf1e1;
}
.single-product .product_infos p.stock.out-of-stock {
	--pi-state: #b02a2a;
	--pi-state-tint: #fbeded;
}
.single-product .product_infos p.stock.sd-eta--on-order {
	--pi-state: #a2551b;
	--pi-state-tint: #fbf0e6;
}
.single-product .product_infos p.stock.sd-eta--lead-days,
.single-product .product_infos p.stock.sd-eta--lead-weeks {
	--pi-state: #a3481b;
	--pi-state-tint: #fbeee6;
}
.single-product .product_infos p.stock.sd-eta--made-to-order {
	--pi-state: #5f4490;
	--pi-state-tint: #f1edf8;
}
.single-product .product_infos p.stock.sd-eta--unknown {
	--pi-state: #55606e;
	--pi-state-tint: #f1f3f5;
}

/* Shared: layout, type and the icon. */
.product_layout_classic .product_content_wrapper .product_infos p.stock {
	/* !important on display alone: style.css un-hides the delivery-estimate
	   paragraph with 'p.stock.sd-eta {display:block !important}' (Shopkeeper
	   hides p.out-of-stock in all five of its product layouts, so that rule
	   has to shout), which would otherwise drop every out-of-stock state out
	   of flex and collapse the icon onto the first word. */
	display: flex !important;
	align-items: center;
	gap: 11px;
	color: var(--pi-state);
	font-family: var(--pi-font-body);
	font-weight: 700;
	font-size: 13.5px;
	line-height: 1.35;
	letter-spacing: 0;
	text-transform: none;
}
.product_layout_classic .product_content_wrapper .product_infos p.stock::before {
	content: "\f05a"; /* FA5 info-circle - fallback for unmapped states */
	font-family: "Font Awesome 5 Free";
	font-weight: 900;
	font-size: 15px;
	line-height: 1;
	flex: none;
	margin: 0;
}

/* Per-state icons, carried over unchanged from the badges this replaces. The
   low-stock state loses its amber disc: the strip it now heads is already
   tinted amber, and one urgency signal is enough. */
.product_layout_classic .product_content_wrapper .product_infos p.stock.in-stock::before {
	content: "\f0d1"; /* truck */
}
.product_layout_classic .product_content_wrapper .product_infos p.stock.in-stock.low-stock::before {
	content: "\f0e7"; /* bolt */
	width: auto;
	height: auto;
	border-radius: 0;
	background: none;
	color: inherit;
	font-size: 15px;
	margin: 0;
}
.product_layout_classic .product_content_wrapper .product_infos p.stock.out-of-stock::before {
	content: "\f057"; /* times-circle */
}
.product_layout_classic .product_content_wrapper .product_infos p.stock.sd-eta.sd-eta--on-order::before {
	content: "\f48b"; /* shipping-fast */
}
.product_layout_classic .product_content_wrapper .product_infos p.stock.sd-eta.sd-eta--lead-days::before,
.product_layout_classic .product_content_wrapper .product_infos p.stock.sd-eta.sd-eta--lead-weeks::before {
	content: "\f017"; /* clock */
}
.product_layout_classic .product_content_wrapper .product_infos p.stock.sd-eta.sd-eta--no-order::before {
	content: "\f057"; /* times-circle */
}
.product_layout_classic .product_content_wrapper .product_infos p.stock.sd-eta.sd-eta--made-to-order::before {
	content: "\f0c4"; /* cut */
}
.product_layout_classic .product_content_wrapper .product_infos p.stock.sd-eta.sd-eta--unknown::before {
	content: "\f059"; /* question-circle */
}

/* Treatment 1: the tray head. Direct children of the summary column only. */
.product_layout_classic .product_content_wrapper .product_infos > p.stock {
	margin: 0 0 24px;
	padding: 13px 15px;
	background: var(--pi-state-tint);
	border: 1px solid var(--pi-border);
	border-top: 3px solid var(--pi-state);
}

/* YITH Min/Max Quantity prints an .ywmmq-rules-wrapper into every product
   summary and leaves it holding nothing but whitespace unless a min/max rule
   applies to that product. Empty it still counts as a sibling, so it breaks
   the adjacency between the availability head and the buy control - and adds
   30px of its own margins on the way through. Collapse it when it has no
   element children, and let the join selectors below step over it.
   :not(:has(*)) rather than :empty, which the whitespace defeats. */
.single-product .product_infos > .ywmmq-rules-wrapper:not(:has(*)) {
	display: none;
}

/* Joined to whatever buy control follows it, so head and body read as one
   board. Products that can be quoted but not bought render no cart form at
   all, so the quote wrapper is named here too. */
.product_layout_classic .product_content_wrapper .product_infos > p.stock:has(+ form.cart:not(.bundle_form)),
.product_layout_classic .product_content_wrapper .product_infos > p.stock:has(+ .yith-ywraq-add-to-quote),
.product_layout_classic .product_content_wrapper .product_infos > p.stock:has(+ .ywmmq-rules-wrapper:not(:has(*)) + form.cart:not(.bundle_form)),
.product_layout_classic .product_content_wrapper .product_infos > p.stock:has(+ .ywmmq-rules-wrapper:not(:has(*)) + .yith-ywraq-add-to-quote) {
	margin-bottom: 0;
}

/* Treatment 2: nested. Colour and icon, no box. */
.product_layout_classic .product_content_wrapper .product_infos form.cart > p.stock,
.product_layout_classic .product_content_wrapper .product_infos .woocommerce-variation-availability p.stock,
.product_layout_classic .product_content_wrapper .product_infos .bundled_item_cart_details p.stock,
.product_layout_classic .product_content_wrapper .product_infos .composited_product_details_wrapper .details p.stock {
	margin: 0 0 12px;
	padding: 0;
	background: none;
	border: 0;
	font-size: 13px;
}

/* ---- Purchase tray -----------------------------------------------------
   Neutral hairline, joined to the availability head above it wherever there
   is one. Bundles are excluded throughout: their form.cart wraps the whole
   bundled-item list, not just the buy controls, so a box around it would be a
   box around half the page.

   The standalone quote wrapper gets the same tray: WooCommerce renders no
   cart form at all for a product that can be quoted but not bought, and the
   button was left floating at its own width under a boxed availability head. */
.single-product form.cart:not(.bundle_form),
.single-product .product_infos > .yith-ywraq-add-to-quote {
	border: 1px solid var(--pi-border);
	background: #fff;
	padding: 12px;
	margin: 0 0 24px;
}
/* The standalone wrapper is shrink-to-fit by default, which drew the tray
   around the button rather than around the row. The Customizer's inline CSS
   sets that as '.woocommerce.single-product .product .yith-ywraq-add-to-quote
   {display:inline-block;margin-top:5px}' at (0,4,0), so this has to reach
   past it rather than merely restate the properties. */
body.single-product.woocommerce div.product .product_infos > .yith-ywraq-add-to-quote {
	display: block;
	width: 100%;
	box-sizing: border-box;
	margin: 0 0 24px;
}
.single-product .product_infos > p.stock + form.cart:not(.bundle_form),
.single-product .product_infos > p.stock + .yith-ywraq-add-to-quote,
.single-product .product_infos > p.stock + .ywmmq-rules-wrapper:not(:has(*)) + form.cart:not(.bundle_form),
.single-product .product_infos > p.stock + .ywmmq-rules-wrapper:not(:has(*)) + .yith-ywraq-add-to-quote {
	border-top: 0;
}
.single-product .product_infos > .yith-ywraq-add-to-quote .yith-ywraq-add-button {
	display: block !important;
	width: 100%;
	margin: 0 !important;
}
.single-product .product_infos > .yith-ywraq-add-to-quote .add-request-quote-button {
	display: flex !important;
	align-items: center;
	justify-content: center;
	width: 100% !important;
	min-width: 0 !important;
	min-height: 50px;
	margin: 0 !important;
	padding: 0 6px !important;
	box-sizing: border-box;
}

/* ---- Quantity ----------------------------------------------------------
   The bare minus / number / plus of the stock widget reads as three loose
   glyphs rather than a control. Bounded, chalk-capped and set at the buttons'
   own height, it reads as one instrument with them - and the figure moves to
   the mono stack so 1, 12 and 120 all sit on the same stem.

   The long selector prefix is load-bearing, not defensive habit. The parent
   theme sizes this widget from
   '.woocommerce div.product form.cart div.quantity:not(.hidden).custom
   input.custom-qty' and two siblings of it - (0,7,4) and (0,7,3) - so a
   shorter selector here silently loses the widths and the arrows collapse
   back to 16px. Matching its shape and adding body.single-product.woocommerce
   clears it without an !important on every property. */
body.single-product.woocommerce div.product form.cart div.quantity:not(.hidden).custom {
	display: flex;
	align-items: stretch;
	width: var(--pi-qty-w);
	height: 50px;
	border: 1px solid var(--pi-border);
	background: #fff;
	overflow: hidden;
}
body.single-product.woocommerce div.product form.cart div.quantity:not(.hidden).custom a.minus-btn,
body.single-product.woocommerce div.product form.cart div.quantity:not(.hidden).custom a.plus-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: none;
	position: static;
	width: 34px;
	height: auto;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: var(--pi-chalk);
	color: var(--pi-ink-soft);
	font-size: 12px;
	line-height: 1;
	text-decoration: none;
	transition: background-color 0.15s ease, color 0.15s ease;
}
body.single-product.woocommerce div.product form.cart div.quantity:not(.hidden).custom a.minus-btn i,
body.single-product.woocommerce div.product form.cart div.quantity:not(.hidden).custom a.plus-btn i {
	color: inherit;
	font-size: 12px;
	line-height: 1;
}
body.single-product.woocommerce div.product form.cart div.quantity:not(.hidden).custom a.minus-btn:hover,
body.single-product.woocommerce div.product form.cart div.quantity:not(.hidden).custom a.plus-btn:hover {
	background: var(--pi-ink);
	color: #fff;
}
body.single-product.woocommerce div.product form.cart div.quantity:not(.hidden).custom input.qty.custom-qty {
	flex: 1 1 auto;
	width: auto;
	min-width: 0;
	height: auto;
	margin: 0;
	padding: 0 2px;
	border: 0;
	border-left: 1px solid var(--pi-border);
	border-right: 1px solid var(--pi-border);
	border-radius: 0;
	background: #fff;
	box-shadow: none;
	text-align: center;
	font-family: var(--pi-font-code);
	font-variant-numeric: tabular-nums;
	font-weight: 700;
	font-size: 15px;
	line-height: 1;
	color: var(--pi-ink);
	-moz-appearance: textfield;
	appearance: textfield;
}
body.single-product.woocommerce div.product form.cart div.quantity:not(.hidden).custom input.qty.custom-qty::-webkit-outer-spin-button,
body.single-product.woocommerce div.product form.cart div.quantity:not(.hidden).custom input.qty.custom-qty::-webkit-inner-spin-button {
	-webkit-appearance: none;
	margin: 0;
}

/* ---- Buy buttons -------------------------------------------------------
   Both paths stay solid and the same size: buying and quoting are both real
   routes for this audience, and demoting the quote button to an outline would
   quietly discourage the half of the customer base that orders on a PO. They
   are separated by colour and by nothing else - brand red for the cart, the
   store's own quote blue for the quote - so neither reads as the fallback.
   Zero radius, Archivo caps on wide tracking: the same button chrome as the
   route buttons on the quoting and funding pages. */
.woocommerce div.product form.cart .single_add_to_cart_button,
.woocommerce div.product form.cart .yith-ywraq-add-to-quote .add-request-quote-button,
.woocommerce div.product .product_infos > .yith-ywraq-add-to-quote .add-request-quote-button {
	min-height: 50px;
	border: 0;
	border-radius: 0;
	box-shadow: none;
	font-family: var(--pi-font-head);
	font-weight: 700;
	font-size: 12px;
	line-height: 1;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	transition: background-color 0.15s ease;
}
.woocommerce div.product form.cart .single_add_to_cart_button .btn,
.woocommerce div.product form.cart .yith-ywraq-add-to-quote .add-request-quote-button .btn,
.woocommerce div.product .product_infos > .yith-ywraq-add-to-quote .add-request-quote-button .btn {
	font-family: var(--pi-font-head);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}
.woocommerce div.product form.cart .single_add_to_cart_button {
	background: var(--pi-red);
	color: #fff;
	/* Both actions are flex:1 1 0 items, so their widths are only equal if
	   their box models are. This button carried 6px of horizontal padding
	   while the quote button's wrapper carried none, so flex-basis:0 resolved
	   against different boxes and left Add to Cart exactly 12px wider than Add
	   to Quote - on every product type, since the two share this row
	   everywhere. Padding on the wrapper instead would not fix it: the cart's
	   padding is inside its button, the quote's would be outside its own, so
	   the two buttons still would not match. Zeroing it here is what makes the
	   boxes identical.

	   The box-model half of this is set below, at a specificity that can
	   actually reach it. */
}

/* The padding, at a weight that wins everywhere.
   wc-product-layout-default.css carries
   '.product_layout_classic .product_content_wrapper .product_infos form.cart
   .button {padding:16px 38px !important}' inside a max-width:64em query - so
   above 1024px a short selector is enough and below it the parent takes the
   button back to 38px a side, which is exactly where the two buttons drifted
   76px apart. Among !important declarations specificity still decides, and
   that one is (0,5,1); this is (0,6,2).

   Only the cart button goes to zero: it IS the flex item, so its padding
   changes its width. The quote button is not - its wrapper is - so padding
   there is free, and it keeps a little to hold a long label off the edges. */
body.single-product .product_layout_classic .product_content_wrapper .product_infos form.cart .single_add_to_cart_button {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0 !important;
}
body.single-product .product_layout_classic .product_content_wrapper .product_infos form.cart .add-request-quote-button {
	padding: 0 10px !important;
}
.woocommerce div.product form.cart .single_add_to_cart_button:hover,
.woocommerce div.product form.cart .single_add_to_cart_button:focus {
	background: var(--pi-red-dark);
	color: #fff;
}
/* YITH ships '.woocommerce .add-request-quote-button.button {background:
   var(--ywraq_layout_button_bg_color) !important}', and an !important
   declaration beats any selector however specific - so every state of this
   button has to answer in kind. The base colour matched by luck (the plugin's
   own setting is the same blue); the hover and disabled states did not, and
   were silently doing nothing. */
.woocommerce div.product form.cart .yith-ywraq-add-to-quote .add-request-quote-button,
.woocommerce div.product .product_infos > .yith-ywraq-add-to-quote .add-request-quote-button {
	background: var(--pi-blue) !important;
	color: #fff;
}
.woocommerce div.product form.cart .yith-ywraq-add-to-quote .add-request-quote-button:hover,
.woocommerce div.product form.cart .yith-ywraq-add-to-quote .add-request-quote-button:focus,
.woocommerce div.product .product_infos > .yith-ywraq-add-to-quote .add-request-quote-button:hover,
.woocommerce div.product .product_infos > .yith-ywraq-add-to-quote .add-request-quote-button:focus {
	background: var(--pi-blue-dark) !important;
	color: #fff;
}

/* One visible focus treatment for every control in the tray. The quantity
   input has no border of its own once it is inside the group, so without this
   a keyboard user loses their place between the two arrows. */
.single-product form.cart .single_add_to_cart_button:focus-visible,
.single-product form.cart .yith-ywraq-add-to-quote .add-request-quote-button:focus-visible,
.single-product form.cart .quantity.custom a:focus-visible,
.single-product form.cart .quantity.custom input.qty.custom-qty:focus-visible {
	outline: 3px solid var(--pi-ink);
	outline-offset: 2px;
	position: relative;
	z-index: 1;
}

/* ---- Back-in-stock alert -----------------------------------------------
   Notifima's form. functions/notifima-backorder.php moves it out of the
   plugin's own slot into the buy row (woocommerce_single_product_summary 31)
   and wraps it in .sd-notifima-box with its own heading; the form markup
   inside stays Notifima's.

   It becomes another segment of the board: same width, same hairline, same
   50px controls as the tray under it. The rules this supersedes in style.css
   sized the box at calc(100% - 232px) so it could sit BESIDE a 224px Add to
   Quote button - correct when that button stood alone, wrong once the redesign
   made it a full-width control in its own tray, which left Notify Me about
   two-thirds the width of the button directly beneath it.

   Renders for signed-in customers only on this store
   (notifima_automation_settings.is_guest_subscriptions_enable = 'logged_in'),
   so none of this is reachable logged out. */
.single-product .product_infos .sd-notifima-box {
	display: block;
	width: auto;
	margin: 0 0 24px;
	padding: 12px;
	border: 1px solid var(--pi-border);
	background: #fff;
}

/* Re-asserted here, louder. Every variation's form starts hidden and
   js/notifima-box.js reveals the box only for a chosen variation that has one;
   style.css states that as '.sd-notifima-box--variable:not(.is-visible)',
   which the display:block above would otherwise outrank and leave the box
   showing with no variation picked. */
.single-product .product_infos .sd-notifima-box--variable:not(.is-visible) {
	display: none;
}

.single-product .product_infos .sd-notifima-box__title {
	font-family: var(--pi-font-head);
	font-weight: 700;
	font-size: 11px;
	line-height: 1.5;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--pi-ink-soft);
	margin: 0 0 10px;
}

.single-product .product_infos .notifima-subscribe-form {
	margin: 0;
}

.single-product .product_infos .notifima-subscribe-form form.login input[type="email"] {
	width: 100%;
	height: 46px;
	margin: 0;
	padding: 0 12px;
	border: 1px solid var(--pi-border);
	border-radius: 0;
	background: #fff;
	box-shadow: none;
	font-family: var(--pi-font-body);
	font-size: 14px;
	line-height: 1.2;
	color: var(--pi-ink);
}
.single-product .product_infos .notifima-subscribe-form form.login input[type="email"]::placeholder {
	color: #9c968c;
}

/* Same geometry and type as Add to Cart and Add to Quote - the three are the
   same control in different colours, and the site owner asked for the widths
   to agree. Shopkeeper's .button carries width:100% and min-width:220px; the
   minimum is cleared so the button tracks the board rather than forcing it
   open on a narrow column. */
.single-product .product_infos .notifima-subscribe-form form.login button {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	min-width: 0;
	min-height: 50px;
	margin: 0;
	padding: 0 10px;
	border: 0;
	border-radius: 0;
	box-shadow: none;
	background: var(--pi-red);
	color: #fff;
	font-family: var(--pi-font-head);
	font-weight: 700;
	font-size: 12px;
	line-height: 1;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	transition: background-color 0.15s ease;
}
.single-product .product_infos .notifima-subscribe-form form.login button:hover,
.single-product .product_infos .notifima-subscribe-form form.login button:focus {
	background: var(--pi-red-dark);
	color: #fff;
}
.single-product .product_infos .notifima-subscribe-form form.login button:focus-visible,
.single-product .product_infos .notifima-subscribe-form form.login input[type="email"]:focus-visible {
	outline: 3px solid var(--pi-ink);
	outline-offset: 2px;
}

/* Board joins. The alert sits between the availability head and the quote
   tray (31 vs YITH's 35), with the empty .ywmmq-rules-wrapper collapsed but
   still countable as a sibling - hence the stepped-over variants, as above.

   The variable-product guard on the second pair matters: that box starts
   hidden, and without it the quote tray below would lose its top border with
   nothing above it to join to. */
.product_layout_classic .product_content_wrapper .product_infos > p.stock:has(+ .sd-notifima-box),
.product_layout_classic .product_content_wrapper .product_infos > p.stock:has(+ .ywmmq-rules-wrapper:not(:has(*)) + .sd-notifima-box) {
	margin-bottom: 0;
}
.single-product .product_infos > p.stock + .sd-notifima-box,
.single-product .product_infos > p.stock + .ywmmq-rules-wrapper:not(:has(*)) + .sd-notifima-box {
	border-top: 0;
}

.single-product .product_infos > .sd-notifima-box:not(.sd-notifima-box--variable):has(+ .yith-ywraq-add-to-quote),
.single-product .product_infos > .sd-notifima-box:not(.sd-notifima-box--variable):has(+ form.cart:not(.bundle_form)),
.single-product .product_infos > .sd-notifima-box--variable.is-visible:has(+ .yith-ywraq-add-to-quote),
.single-product .product_infos > .sd-notifima-box--variable.is-visible:has(+ form.cart:not(.bundle_form)) {
	margin-bottom: 0;
}
.single-product .product_infos > .sd-notifima-box:not(.sd-notifima-box--variable) + .yith-ywraq-add-to-quote,
.single-product .product_infos > .sd-notifima-box:not(.sd-notifima-box--variable) + form.cart:not(.bundle_form),
.single-product .product_infos > .sd-notifima-box--variable.is-visible + .yith-ywraq-add-to-quote,
.single-product .product_infos > .sd-notifima-box--variable.is-visible + form.cart:not(.bundle_form) {
	border-top: 0;
}

/* ---- SD Dollars --------------------------------------------------------
   Was inheriting .product_meta's 10px uppercase treatment, which turned a
   plain sentence into a block of shouted small print with "MORE INFO"
   stranded on its own line. It is a reason to buy here rather than a
   disclaimer, so it gets the house gold: sentence case, a gold edge rule, and
   the link on its own line as a real destination.

   Selectors carry .sd-relocated-info alongside .woocommerce-info because
   sd_output_defanged_product_purchase_message() in functions/sumo-rewards.php
   renames the class to keep Shopkeeper's notification popup from sweeping the
   message into the floating toast - same reason as the cart-page rules in
   style.css. */
.single-product .product_meta .woocommerce-info,
.single-product .product_meta .sd-relocated-info {
	display: block;
	margin: 0;
	padding: 13px 15px;
	background: var(--pi-gold-tint);
	border: 1px solid var(--pi-gold-line);
	font-family: var(--pi-font-body);
	font-size: 13px;
	font-weight: 600;
	line-height: 1.45;
	letter-spacing: 0;
	text-transform: none;
	color: var(--pi-ink);
}
.single-product .product_meta .sd-rewards-note {
	display: flex;
	align-items: center;
	gap: 13px;
}
.single-product .product_meta .sd-rewards-note__coin {
	flex: none;
	width: 34px;
	height: 34px;
	display: block;
}
.single-product .product_meta .sd-rewards-note__body {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 3px;
	min-width: 0;
}
.single-product .product_meta .sd-rewards-note__lead {
	display: block;
	font-weight: 700;
	color: var(--pi-ink);
}
.single-product .product_meta .sd-rewards-note__link,
.single-product .product_meta .woocommerce-info a,
.single-product .product_meta .sd-relocated-info a {
	display: inline-block;
	margin-top: 2px;
	color: var(--pi-red-ink);
	font-family: var(--pi-font-head);
	font-weight: 700;
	font-size: 11px;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	text-decoration: underline;
	text-underline-offset: 3px;
}
.single-product .product_meta .sd-rewards-note__link:hover,
.single-product .product_meta .woocommerce-info a:hover,
.single-product .product_meta .sd-relocated-info a:hover {
	color: var(--pi-ink);
}

/* The SUMO message is admin-editable, so it can be reverted to the plugin's
   original <table> markup at any time (SUMO Reward Points > Messages). Keep
   that layout working: the table's inline cell padding and 54px/40px image
   sizing need !important to be pulled back into line with the flex version
   above. */
.single-product .product_meta .woocommerce-info table,
.single-product .product_meta .sd-relocated-info table {
	width: 100%;
	margin: 0;
}
.single-product .product_meta .woocommerce-info table td,
.single-product .product_meta .sd-relocated-info table td {
	border: 0 !important;
	padding: 0 !important;
	vertical-align: middle;
}
.single-product .product_meta .woocommerce-info table td:first-child,
.single-product .product_meta .sd-relocated-info table td:first-child {
	width: 47px !important;
	padding-right: 13px !important;
}
.single-product .product_meta .woocommerce-info table img,
.single-product .product_meta .sd-relocated-info table img {
	width: 34px !important;
	height: 34px !important;
}

/* ---- Narrow screens ----------------------------------------------------
   style.css drops the quote button onto its own row below 640px and indents
   it to line up under Add to Cart, using the stock widget's old 85px width.
   Recalculated against the redesigned stepper (--pi-qty-w) plus the form's
   8px gap, so the two buttons' left edges still agree. */
@media all and (max-width: 640px) {
	.single-product form.cart:has(> .quantity) .yith-ywraq-add-to-quote {
		flex-basis: calc(100% - (var(--pi-qty-w) + 8px));
		margin-left: calc(var(--pi-qty-w) + 8px) !important;
	}
}

@media all and (max-width: 480px) {
	.single-product form.cart:not(.bundle_form) {
		padding: 10px;
	}
	.single-product .product_infos .sd-price-gst {
		font-size: 10px;
		letter-spacing: 0.12em;
	}
}

@media (prefers-reduced-motion: reduce) {
	.single-product form.cart .quantity.custom a.minus-btn,
	.single-product form.cart .quantity.custom a.plus-btn,
	.woocommerce div.product form.cart .single_add_to_cart_button,
	.woocommerce div.product form.cart .yith-ywraq-add-to-quote .add-request-quote-button {
		transition: none;
	}
}
