/**
 * sst-checkout-ab — shared checkout STRUCTURE (WS-2). Variant-agnostic.
 *
 * Layout, anatomy and state plumbing only. Every colour, radius, shadow and
 * spacing value is a `--co-*` custom property with a neutral default; the skins
 * (assets/variant-a.css / -b / -c, WS-3) redefine the tokens under
 * `body.sst-co-v-a|-b|-c` and add their own typography.
 *
 * Everything is scoped to `body.sst-co-ab` so nothing can leak outside checkout.
 */

body.sst-co-ab {
	--co-bg: #ffffff;
	--co-ink: #121212;
	--co-mute: #5f6570;
	--co-rule: #e2e4e7;
	--co-card: #ffffff;
	--co-radius: 12px;
	--co-shadow: 0 1px 2px rgba( 18, 18, 18, .06 );
	--co-primary: #111111;
	--co-primary-ink: #ffffff;
	--co-wise: #163300;        /* brand ink — the wordmark */
	--co-wise-tint: #f0fbe6;   /* pale wash behind the selected card */
	--co-wise-accent: #9fe870; /* the lime — the wordmark pill, badges, check */
	--co-paypal: #003087;        /* brand navy — "Pay" */
	--co-paypal-tint: #eaf1fb;   /* pale wash behind the selected card */
	--co-paypal-accent: #0070e0; /* brand blue — "Pal" */

	--co-gap: 40px;
	--co-rail: 420px;
	--co-rail-min: 320px;
	--co-sticky-top: 16px;
	--co-card-pad: 16px;
	--co-card-gap: 12px;
	--co-check-size: 22px;
	--co-details-max: 340px;
	--co-motion: 150ms;
	--co-bar-height: 96px;
	/* MEASURED height of the fixed bar, published by checkout-ab.js on every show/hide/resize.
	   `--co-bar-height` above is a SPACING token — what the page reserves under itself — and a
	   skin may legitimately set it to 0 while still painting a bar (variant B does, for its
	   single-row bar). Anything that needs to clear the bar physically must use this one. The
	   value here is only the pre-measurement default; a skin may seed a better one. */
	--co-bar-real: 96px;
}

/* ------------------------------------------------------------------ *
 * 1. Page shell — one column ≤1023, form + rail side by side ≥1024.
 * ------------------------------------------------------------------ */

@media ( min-width: 1024px ) {
	body.sst-co-ab form.checkout.woocommerce-checkout {
		display: grid;
		grid-template-columns: minmax( 0, 1fr ) minmax( var( --co-rail-min ), var( --co-rail ) );
		/* Two-value `gap` for the same reason as the cart (C-1): `#customer_details` spans
		   99 rows, so ANY inherited row-gap would be multiplied by 98. `form.checkout`
		   computes `row-gap: normal` today, so this is a no-op that stays a no-op. */
		gap: 0 var( --co-gap );
		align-items: start;
	}

	body.sst-co-ab form.checkout.woocommerce-checkout > * {
		grid-column: 1;
		min-width: 0;
	}

	/* All three of the form, the heading and the rail are placed EXPLICITLY.
	   `#customer_details` must span the rows too: left auto-placed it into row 1,
	   row 1 then grew to the full height of the form, and the rail — pinned to
	   row 2 — rendered BELOW the form instead of beside it (measured at 1440 px:
	   form ended y=2000, rail started y=2000). Reported by WS-3b, who had to
	   patch it in all three skins; those workarounds can now be deleted.

	   The span has to be LARGE, not tight: a multi-track item distributes its
	   surplus height evenly over the tracks it spans, so `1 / 100` leaves row 1
	   about 1/99 of the form taller than the heading (~20 px, invisible) whereas
	   a tight `1 / 3` would put half the form's height into row 1. Anything the
	   form prints after `#customer_details` auto-flows into row 100 and beyond. */
	body.sst-co-ab form.checkout.woocommerce-checkout > #customer_details {
		grid-column: 1;
		grid-row: 1 / 100;
	}

	body.sst-co-ab form.checkout.woocommerce-checkout > #order_review_heading {
		grid-column: 2;
		grid-row: 1;
		align-self: start;
	}

	/* The rail is NOT pinned and is NOT an inner scroller. With a real cart it is
	   routinely TALLER than the form (WS-3c measured 2,605 px of rail against
	   1,494 px of form), and a sticky rail capped at 100vh then parks the pay
	   button inside a nested scrollbar, off screen. It scrolls with the page
	   instead, and the CTA below is what stays reachable. A skin whose rail
	   genuinely fits the viewport can opt in with `--co-rail-position: sticky`
	   (and set its own max-height/overflow). */
	body.sst-co-ab form.checkout.woocommerce-checkout > #order_review {
		grid-column: 2;
		grid-row: 2 / 100;
		align-self: start;
		position: var( --co-rail-position, static );
		top: var( --co-sticky-top );
	}

	/* The pay button sticks to the bottom of the viewport while the consent card
	   is on screen, so a long rail never hides the CTA. A skin may opt out with
	   `--co-rail-cta: static` (mock C keeps the CTA in normal flow). */
	body.sst-co-ab #order_review .place-order {
		position: var( --co-rail-cta, sticky );
		bottom: 0;
		z-index: 2;
		background: var( --co-card );
	}
}

@media ( max-width: 1023px ) {
	body.sst-co-ab .woocommerce-checkout {
		padding-bottom: var( --co-bar-height );
	}
}


/* ------------------------------------------------------------------ *
 * 1b. Collisions with account-checkout.css (ACF) — hotfix 2026-08-21.
 * ------------------------------------------------------------------ */

/* ACF's "Review and place order" express card pins itself to grid-row 1 of
   form.checkout; with #customer_details on row 1 as well (§1) the two render
   on top of each other for every member who has a complete saved address.
   The redesign has no express card: the saved address is prefilled in the
   form and the rail CTA places the order. */
body.sst-co-ab form.checkout.woocommerce-checkout > .sst-express-checkout {
	display: none;
}

/* ACF styles every <li> under #payment ul.payment_methods (padding 15px 16px,
   border-bottom) and that descends into the payment cards' bullet lists,
   pushing each bullet's text a line below its marker. The member DOM prints the
   unboxing agreement OUTSIDE .sst-consent (div.sst-unboxing-agreement), hence
   the second scope on every rule. */
body.sst-co-ab.woocommerce-checkout #payment ul.payment_methods .sst-pm__bullets li,
body.sst-co-ab.woocommerce-checkout #payment ul.payment_methods .sst-pm__details-list li {
	margin: 0;
	padding-top: 0;
	padding-right: 0;
	padding-bottom: 0;
	border: 0;
}


/* 1c. FedEx rate rows — hotfix 2026-08-21 (0.1.2). The shipping plugin
   (samurai-fedex-shipping, inline CSS) appends a `.samurai-fedex-package-ui`
   block after every rate label and expects the <li> to be a grid: radio in
   column 1, label in column 2, package block on row 2 / column 2. The skins'
   flex rows squeeze that block beside the label (A/B) or over it (C). */
body.sst-co-ab.woocommerce-checkout #order_review ul#shipping_method > li {
	display: grid;
	grid-template-columns: auto minmax( 0, 1fr );
	column-gap: 10px;
	row-gap: 4px;
	align-items: start;
	justify-content: start;
	text-align: left;
}

body.sst-co-ab.woocommerce-checkout #order_review ul#shipping_method > li > input.shipping_method {
	grid-column: 1;
	grid-row: 1;
	margin: 2px 0 0;
}

body.sst-co-ab.woocommerce-checkout #order_review ul#shipping_method > li > label {
	grid-column: 2;
	grid-row: 1;
	margin: 0;
	text-align: left;
}

body.sst-co-ab.woocommerce-checkout #order_review ul#shipping_method > li > .samurai-fedex-package-ui {
	grid-column: 2;
	grid-row: 2;
	margin: 0;
	min-width: 0;
	text-align: left;
}

/* When rate options are present the row stacks: heading above, options across
   the full rail width. Skin A keeps the row as table cells, which hands the
   heading column ~60% of a 328px rail and leaves 125px for the options. */
body.sst-co-ab.woocommerce-checkout #order_review tr.woocommerce-shipping-totals:has(ul#shipping_method) {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: 6px;
	width: 100%;
}

body.sst-co-ab.woocommerce-checkout #order_review tr.woocommerce-shipping-totals:has(ul#shipping_method) > th,
body.sst-co-ab.woocommerce-checkout #order_review tr.woocommerce-shipping-totals:has(ul#shipping_method) > td {
	display: block;
	float: none;
	width: auto;
	max-width: none;
	margin-left: 0;
	text-align: left;
}

body.sst-co-ab.woocommerce-checkout #order_review tr.woocommerce-shipping-totals:has(ul#shipping_method) ul#shipping_method {
	display: flex;
	flex-direction: column;
	gap: 8px;
	width: 100%;
	max-width: none;
	text-align: left;
}

/* Single rate: WooCommerce prints a hidden input + label without a radio. */
body.sst-co-ab.woocommerce-checkout #order_review ul#shipping_method > li > input[type="hidden"] + label,
body.sst-co-ab.woocommerce-checkout #order_review ul#shipping_method > li > input[type="hidden"] + label + .samurai-fedex-package-ui {
	grid-column: 1 / -1;
}

/* ------------------------------------------------------------------ *
 * 1d. FedEx rate rows on the CART — mirror of §1c (REVIEW-CO-2 H-2).
 *
 * §1c is scoped to `#order_review`, which the cart has no equivalent of, so the
 * identical regression appeared on /cart: all three skins turn the rate <li>
 * into a flex row (variant-a.css:4356, variant-b.css:1300 — not even page-scoped,
 * variant-c.css:1498), which puts the `.samurai-fedex-package-ui` block BESIDE the
 * label instead of under it. Measured before the fix: C crushed the label to 73px.
 *
 * SPECIFICITY, deliberately: the prefix chains `.cart_totals.sst-cart-totals` (both
 * land on the same element from templates/cart/cart-totals.php) inside
 * `.cart-collaterals`, giving (1,5,3) against variant A's (1,4,3) — the highest of
 * the three skins. The base sheet is enqueued BEFORE the variant sheet, so it must
 * win on specificity, not order. tests/render-contract.php computes both sides and
 * asserts the base is strictly higher.
 * ------------------------------------------------------------------ */

body.sst-co-ab.woocommerce-cart .cart-collaterals .cart_totals.sst-cart-totals ul#shipping_method > li {
	display: grid;
	grid-template-columns: auto minmax( 0, 1fr );
	column-gap: 10px;
	row-gap: 4px;
	align-items: start;
	justify-content: start;
	text-align: left;
}

body.sst-co-ab.woocommerce-cart .cart-collaterals .cart_totals.sst-cart-totals ul#shipping_method > li > input.shipping_method {
	grid-column: 1;
	grid-row: 1;
	margin: 2px 0 0;
}

body.sst-co-ab.woocommerce-cart .cart-collaterals .cart_totals.sst-cart-totals ul#shipping_method > li > label {
	grid-column: 2;
	grid-row: 1;
	margin: 0;
	flex: none;
	text-align: left;
}

body.sst-co-ab.woocommerce-cart .cart-collaterals .cart_totals.sst-cart-totals ul#shipping_method > li > .samurai-fedex-package-ui {
	grid-column: 2;
	grid-row: 2;
	margin: 0;
	min-width: 0;
	text-align: left;
}

/* Row stacking: heading above, options across the full rail width. */
body.sst-co-ab.woocommerce-cart .cart-collaterals .cart_totals.sst-cart-totals tr.woocommerce-shipping-totals:has( ul#shipping_method ) {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: 6px;
	width: 100%;
}

body.sst-co-ab.woocommerce-cart .cart-collaterals .cart_totals.sst-cart-totals tr.woocommerce-shipping-totals:has( ul#shipping_method ) > th,
body.sst-co-ab.woocommerce-cart .cart-collaterals .cart_totals.sst-cart-totals tr.woocommerce-shipping-totals:has( ul#shipping_method ) > td {
	display: block;
	float: none;
	width: auto;
	max-width: none;
	margin-left: 0;
	text-align: left;
}

body.sst-co-ab.woocommerce-cart .cart-collaterals .cart_totals.sst-cart-totals tr.woocommerce-shipping-totals:has( ul#shipping_method ) ul#shipping_method {
	display: flex;
	flex-direction: column;
	gap: 8px;
	width: 100%;
	max-width: none;
	text-align: left;
}

/* Single rate: WooCommerce prints a hidden input + label without a radio. */
body.sst-co-ab.woocommerce-cart .cart-collaterals .cart_totals.sst-cart-totals ul#shipping_method > li > input[type="hidden"] + label,
body.sst-co-ab.woocommerce-cart .cart-collaterals .cart_totals.sst-cart-totals ul#shipping_method > li > input[type="hidden"] + label + .samurai-fedex-package-ui {
	grid-column: 1 / -1;
}


/* 1e. Consent rows printed by the mu-plugins (native checkbox + loose text +
   a link, e.g. the unboxing-video agreement) must not be flex containers: the
   anonymous text runs and the <a> become separate flex items and the link
   collapses to one word per line (skin B at 390 px: 35×147 px). Block flow
   with the control parked in the padding instead. `#order_review` anchors the
   specificity above the skins' (0,5,2) label rules. */
body.sst-co-ab #order_review .sst-consent .form-row label.checkbox:not( .sst-check__label ),
body.sst-co-ab .sst-unboxing-agreement .sst-unboxing-agreement__field label.checkbox:not( .sst-check__label ) {
	display: block;
	position: relative;
	padding-left: calc( var( --co-check-size ) + 10px );
	min-width: 0;
}

body.sst-co-ab #order_review .sst-consent .form-row label.checkbox:not( .sst-check__label ) > input[ type="checkbox" ],
body.sst-co-ab .sst-unboxing-agreement .sst-unboxing-agreement__field label.checkbox:not( .sst-check__label ) > input[ type="checkbox" ] {
	position: absolute;
	left: 0;
	top: 2px;
	margin: 0;
}

body.sst-co-ab #order_review .sst-consent .form-row label.checkbox:not( .sst-check__label ) a,
body.sst-co-ab .sst-unboxing-agreement .sst-unboxing-agreement__field label.checkbox:not( .sst-check__label ) a {
	display: inline;
	overflow-wrap: normal;
	word-break: normal;
}

/* ------------------------------------------------------------------ *
 * 2. Step band. Rendered for every variant, revealed by the variant-C skin.
 * ------------------------------------------------------------------ */

body.sst-co-ab .sst-co-steps {
	display: none;
}

body.sst-co-ab .sst-co-steps__list {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 10px;
	margin: 0;
	padding: 0;
	list-style: none;
}

body.sst-co-ab .sst-co-steps__step {
	display: flex;
	align-items: center;
	gap: 10px;
}

body.sst-co-ab .sst-co-steps__step:not( :last-child )::after {
	content: "\2192";
	display: inline-block;
}

/* ------------------------------------------------------------------ *
 * 3. Mobile items strip (JS-filled from the review table).
 * ------------------------------------------------------------------ */

body.sst-co-ab .sst-co-strip {
	display: block;
	border: 1px solid var( --co-rule );
	border-radius: var( --co-radius );
	background: var( --co-card );
	margin: 0 0 20px;
}

body.sst-co-ab .sst-co-strip[hidden] {
	display: none;
}

@media ( min-width: 1024px ) {
	body.sst-co-ab .sst-co-strip {
		display: none;
	}
}

/* `flex-wrap` is BASE, not a skin patch: the head carries five items (title, count, total,
   toggle label, chevron) and only the title may shrink, so on a narrow rail their combined
   min-content overflows — WS-3a measured 319px of content in a 264px rail at ≤375. That is
   shared anatomy, so B and C have it too; letting the tail wrap is the fix for all three. */
body.sst-co-ab .sst-co-strip__head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	width: 100%;
	padding: 12px 14px;
	background: none;
	border: 0;
	text-align: left;
	cursor: pointer;
	color: inherit;
	font: inherit;
}

body.sst-co-ab .sst-co-strip__title {
	flex: 1 1 auto;
	min-width: 0;
}

body.sst-co-ab .sst-co-strip__count,
body.sst-co-ab .sst-co-strip__total,
body.sst-co-ab .sst-co-strip__toggle {
	flex: 0 0 auto;
}

body.sst-co-ab .sst-co-strip__chev {
	flex: 0 0 auto;
	display: inline-flex;
	transition: transform var( --co-motion ) ease;
}

body.sst-co-ab .sst-co-strip.is-open .sst-co-strip__chev {
	transform: rotate( 180deg );
}

body.sst-co-ab .sst-co-strip__body {
	padding: 0 14px 12px;
}

body.sst-co-ab .sst-co-strip__body[hidden] {
	display: none;
}

body.sst-co-ab .sst-co-strip__row {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 10px 0;
	border-top: 1px solid var( --co-rule );
}

body.sst-co-ab .sst-co-strip__thumb {
	flex: 0 0 auto;
	width: 44px;
	height: 44px;
	overflow: hidden;
	border-radius: 6px;
}

body.sst-co-ab .sst-co-strip__thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

body.sst-co-ab .sst-co-strip__name {
	flex: 1 1 auto;
	min-width: 0;
}

body.sst-co-ab .sst-co-strip__qty {
	display: block;
}

body.sst-co-ab .sst-co-strip__line {
	flex: 0 0 auto;
	white-space: nowrap;
}

/* ------------------------------------------------------------------ *
 * 4. Payment section head + method list.
 * ------------------------------------------------------------------ */

body.sst-co-ab .sst-co-payhead {
	margin: 0 0 12px;
}

body.sst-co-ab ul.wc_payment_methods.sst-pm-list {
	list-style: none;
	margin: 0 0 20px;
	padding: 0;
	border: 0;
}

body.sst-co-ab li.wc_payment_method.sst-pm-item {
	position: relative;
	list-style: none;
	margin: 0 0 var( --co-card-gap );
	padding: 0;
}

body.sst-co-ab li.wc_payment_method.sst-pm-item::before {
	content: none;
}

/* The native radio stays in the DOM, in the tab order and in the accessibility
   tree — only its pixels are removed. Never `display: none`. */
body.sst-co-ab .sst-pm__radio {
	position: absolute;
	top: 0;
	left: 0;
	width: 1px;
	height: 1px;
	margin: 0;
	padding: 0;
	opacity: 0;
	pointer-events: none;
}

/* WooCommerce's own gateway description box: kept in the DOM (checkout.js
   slides it) but never shown — the readable copy lives in `.sst-pm__details`. */
body.sst-co-ab .sst-co-payment .payment_box {
	display: none !important;
}

/* ------------------------------------------------------------------ *
 * 5. Payment card anatomy.
 * ------------------------------------------------------------------ */

body.sst-co-ab .sst-pm {
	position: relative;
	display: block;
	padding: var( --co-card-pad );
	border: 1px solid var( --co-rule );
	border-radius: var( --co-radius );
	background: var( --co-card );
	box-shadow: var( --co-shadow );
	cursor: pointer;
	transition: border-color var( --co-motion ) ease, box-shadow var( --co-motion ) ease, background-color var( --co-motion ) ease;
}

body.sst-co-ab .sst-pm__radio:focus-visible + .sst-pm,
body.sst-co-ab .sst-pm__radio:focus + .sst-pm {
	outline: 2px solid var( --co-primary );
	outline-offset: 2px;
}

body.sst-co-ab .sst-pm__label {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px 12px;
	padding-right: 32px;
	cursor: pointer;
	margin: 0;
}

body.sst-co-ab .sst-pm__logo {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
}

/* Official trademark artwork (assets/brands/*.svg), rendered as <img>. Skins must NOT
   recolour these; `--co-logo-tile` is the hook for a background plate when a skin's card
   surface does not give the mark enough contrast. */
body.sst-co-ab .sst-pm__logo-img {
	display: block;
	height: 26px;
	width: auto;
	max-width: 100%;
	background: var( --co-logo-tile, transparent );
}

body.sst-co-ab .sst-pm__brand {
	display: block;
	width: 34px;
	height: 22px;
	object-fit: contain;
	background: var( --co-logo-tile, transparent );
	border-radius: 4px;
}

body.sst-co-ab .sst-pm__id {
	display: flex;
	flex-direction: column;
	min-width: 0;
	flex: 1 1 auto;
}

body.sst-co-ab .sst-pm__title,
body.sst-co-ab .sst-pm__sub {
	display: block;
}

body.sst-co-ab .sst-pm__badges {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	flex: 1 1 100%;
}

body.sst-co-ab .sst-pm__badge {
	display: inline-flex;
	align-items: center;
	border-radius: 999px;
	padding: 3px 9px;
	border: 1px solid var( --co-rule );
	white-space: nowrap;
}

body.sst-co-ab .sst-pm__check {
	position: absolute;
	top: var( --co-card-pad );
	right: var( --co-card-pad );
	width: 22px;
	height: 22px;
	border-radius: 50%;
	border: 1px solid var( --co-rule );
	display: inline-flex;
	align-items: center;
	justify-content: center;
	color: transparent;
	transition: color var( --co-motion ) ease, background-color var( --co-motion ) ease, border-color var( --co-motion ) ease;
}

body.sst-co-ab .sst-pm.is-selected .sst-pm__check,
body.sst-co-ab li.wc_payment_method--selected .sst-pm__check {
	color: currentColor;
}

body.sst-co-ab .sst-pm__bullets,
body.sst-co-ab .sst-pm__details-list {
	list-style: none;
	margin: 12px 0 0;
	padding: 0;
	display: grid;
	gap: 6px;
}

body.sst-co-ab .sst-pm__bullets li,
body.sst-co-ab .sst-pm__details-list li {
	position: relative;
	padding-left: 18px;
}

body.sst-co-ab .sst-pm__bullets li::before,
body.sst-co-ab .sst-pm__details-list li::before {
	content: "";
	position: absolute;
	left: 4px;
	top: .62em;
	width: 5px;
	height: 5px;
	border-radius: 50%;
	background: currentColor;
	opacity: .45;
}

body.sst-co-ab .sst-pm__brands {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin-top: 12px;
}



body.sst-co-ab .sst-pm__fee {
	margin: 12px 0 0;
}

/* P2-3 — the reveal-on-select mechanism that used to live here is GONE.
   `.sst-pm__details` is a native `<details>` now (see §13): its own open state
   is the mechanism, so a `max-height` reveal would only clip it. The rules are
   removed rather than left inert because a leftover `max-height: 0` on a
   `<details>` hides the summary too — and the summary is the whole affordance.
   Skins carrying their own copy of the old reveal must drop it; §13 defends
   against that with `!important` until they do (variant-a.css:3186 / 3228). */

body.sst-co-ab .sst-pm__details-inner {
	padding-top: 4px;
}

body.sst-co-ab .sst-pm__details-text p:last-child {
	margin-bottom: 0;
}

/* ------------------------------------------------------------------ *
 * 6. Consent card + custom checkbox.
 * ------------------------------------------------------------------ */

body.sst-co-ab .sst-consent {
	border: 1px solid var( --co-rule );
	border-radius: var( --co-radius );
	background: var( --co-card );
	padding: var( --co-card-pad );
}

body.sst-co-ab .sst-consent__title {
	margin: 0 0 12px;
}

body.sst-co-ab .sst-consent__error[hidden] {
	display: none;
}

body.sst-co-ab .sst-consent__boxes > .form-row,
body.sst-co-ab .sst-consent .sst-check {
	margin: 0 0 12px;
	padding: 0;
}

/* Our terms checkbox: native input hidden behind a drawn box. Only inputs that
   carry `.sst-check__input` are hidden — a mu-plugin checkbox without the
   `.sst-check__box` sibling must never lose its own control. */
body.sst-co-ab .sst-check__label,
body.sst-co-ab .sst-consent .form-row label.checkbox {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	margin: 0;
	cursor: pointer;
}

body.sst-co-ab .sst-check__input {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	margin: 0;
	pointer-events: none;
}

body.sst-co-ab .sst-check__box {
	flex: 0 0 auto;
	width: var( --co-check-size );
	height: var( --co-check-size );
	margin-top: 1px;
	border: 1.5px solid var( --co-rule );
	border-radius: 6px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	color: transparent;
	background: var( --co-card );
	transition: background-color var( --co-motion ) ease, border-color var( --co-motion ) ease, color var( --co-motion ) ease;
}

body.sst-co-ab .sst-check__input:checked ~ .sst-check__box {
	background: var( --co-primary );
	border-color: var( --co-primary );
	color: var( --co-primary-ink );
}

body.sst-co-ab .sst-check__input:focus-visible ~ .sst-check__box,
body.sst-co-ab .sst-check__input:focus ~ .sst-check__box {
	outline: 2px solid var( --co-primary );
	outline-offset: 2px;
}

body.sst-co-ab .sst-check__text {
	flex: 1 1 auto;
	min-width: 0;
}

/* Consent checkboxes printed by the mu-plugins keep their native control; only
   its size and accent are normalised so the card reads as one set. */
body.sst-co-ab .sst-consent .form-row input[ type="checkbox" ]:not( .sst-check__input ) {
	flex: 0 0 auto;
	width: var( --co-check-size );
	height: var( --co-check-size );
	margin: 1px 0 0;
	accent-color: var( --co-primary );
}

body.sst-co-ab .sst-check--flash {
	animation: sst-co-flash 900ms ease-in-out 2;
	border-radius: 8px;
}

@keyframes sst-co-flash {
	0%, 100% { box-shadow: 0 0 0 0 transparent; }
	50% { box-shadow: 0 0 0 3px var( --co-primary ); }
}

/* ------------------------------------------------------------------ *
 * 7. Pay button spans.
 * ------------------------------------------------------------------ */

body.sst-co-ab .place-order {
	margin: 16px 0 0;
	padding: 0;
}

body.sst-co-ab #place_order .sst-pay,
body.sst-co-ab .sst-co-bar__btn .sst-pay {
	display: inline-flex;
	align-items: baseline;
	justify-content: center;
	flex-wrap: wrap;
}

/* The sentence is split at its placeholders, so the spacing lives inside the
   translated string — `pre-wrap` is what preserves it. */
body.sst-co-ab .sst-pay__label,
body.sst-co-ab .sst-pay__with {
	white-space: pre-wrap;
}

body.sst-co-ab .sst-pay__amount {
	font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------ *
 * 8. Fixed bottom bar (JS-built, appended to <body>).
 * ------------------------------------------------------------------ */

body.sst-co-ab .sst-co-bar {
	display: none;
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 60;
	padding: 10px 14px;
	padding-bottom: calc( 10px + env( safe-area-inset-bottom, 0px ) );
	background: var( --co-card );
	border-top: 1px solid var( --co-rule );
}

@media ( max-width: 1023px ) {
	body.sst-co-ab .sst-co-bar:not( [hidden] ) {
		display: block;
	}
}

body.sst-co-ab .sst-co-bar__inner {
	display: flex;
	align-items: center;
	gap: 12px;
	max-width: var( --co-max, 1200px );
	margin: 0 auto;
}

body.sst-co-ab .sst-co-bar__total {
	flex: 0 0 auto;
	display: flex;
	flex-direction: column;
	line-height: 1.2;
}

body.sst-co-ab .sst-co-bar__btn {
	flex: 1 1 auto;
	min-width: 0;
	min-height: 52px;
}

/* ------------------------------------------------------------------ *
 * 9. Reduced motion.
 * ------------------------------------------------------------------ */

@media ( prefers-reduced-motion: reduce ) {
	body.sst-co-ab .sst-pm,
	body.sst-co-ab .sst-pm__check,
	body.sst-co-ab .sst-pm__details,
	body.sst-co-ab .sst-check__box,
	body.sst-co-ab .sst-co-strip__chev {
		transition: none;
	}

	body.sst-co-ab .sst-check--flash {
		animation: none;
		outline: 3px solid var( --co-primary );
		outline-offset: 2px;
	}
}

/* ------------------------------------------------------------------ *
 * 10. Cart page (DESIGN section 8). Structure only; skins under
 *     body.sst-co-ab.sst-co-v-* .woocommerce-cart do the rest.
 *
 *     The <table> stays because WooCommerce's own cart.js bails out of the
 *     form entirely without `.woocommerce-cart-form__contents` (cart.js:550),
 *     so the rows are turned into cards with `display:grid` instead — the same
 *     technique WooCommerce's `shop_table_responsive` uses on mobile.
 * ------------------------------------------------------------------ */

body.sst-co-ab.woocommerce-cart .sst-cart-items,
body.sst-co-ab.woocommerce-cart .sst-cart-items tbody,
body.sst-co-ab.woocommerce-cart .sst-cart-item,
body.sst-co-ab.woocommerce-cart .sst-cart-item > td,
body.sst-co-ab.woocommerce-cart .sst-cart-actions-row,
body.sst-co-ab.woocommerce-cart .sst-cart-actions-row > td {
	display: block;
	width: auto;
	border: 0;
	padding: 0;
}

body.sst-co-ab.woocommerce-cart .sst-cart-items {
	border-collapse: collapse;
	margin: 0;
}

/* Column headers are meaningless once the rows are cards. */
body.sst-co-ab.woocommerce-cart .sst-cart-items__head {
	display: none;
}

body.sst-co-ab.woocommerce-cart .sst-cart-item {
	display: grid;
	grid-template-columns: 64px minmax( 0, 1fr ) auto;
	grid-template-areas:
		"thumb main   remove"
		"thumb unit   unit"
		"thumb qty    line";
	column-gap: 14px;
	row-gap: 6px;
	align-items: start;
	padding: var( --co-card-pad ) 0;
	border-bottom: 1px solid var( --co-rule );
}

body.sst-co-ab.woocommerce-cart .sst-cart-item__thumb { grid-area: thumb; }
body.sst-co-ab.woocommerce-cart .sst-cart-item__main { grid-area: main; min-width: 0; }
body.sst-co-ab.woocommerce-cart .sst-cart-item__unit { grid-area: unit; }
body.sst-co-ab.woocommerce-cart .sst-cart-item__qty { grid-area: qty; align-self: center; }
body.sst-co-ab.woocommerce-cart .sst-cart-item__line { grid-area: line; align-self: center; text-align: right; }
body.sst-co-ab.woocommerce-cart .sst-cart-item__remove { grid-area: remove; text-align: right; }

body.sst-co-ab.woocommerce-cart .sst-cart-item__thumb img {
	display: block;
	width: 64px;
	height: 64px;
	object-fit: cover;
	border-radius: 8px;
}

body.sst-co-ab.woocommerce-cart .sst-cart-item__remove .remove {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	border-radius: 50%;
	text-decoration: none;
	line-height: 1;
}

/* Quantity stepper: the +/- buttons are added by JS around WooCommerce's own input. */
body.sst-co-ab.woocommerce-cart .sst-cart-qty {
	display: inline-flex;
	align-items: stretch;
	border: 1px solid var( --co-rule );
	border-radius: 8px;
	overflow: hidden;
}

body.sst-co-ab.woocommerce-cart .sst-cart-qty .quantity {
	margin: 0;
	display: flex;
}

body.sst-co-ab.woocommerce-cart .sst-cart-qty input.qty {
	width: 3.2em;
	min-width: 0;
	height: var( --co-qty-size, 36px );
	border: 0;
	border-radius: 0;
	text-align: center;
	background: transparent;
	-moz-appearance: textfield;
	appearance: textfield;
}

body.sst-co-ab.woocommerce-cart .sst-cart-qty input.qty::-webkit-outer-spin-button,
body.sst-co-ab.woocommerce-cart .sst-cart-qty input.qty::-webkit-inner-spin-button {
	-webkit-appearance: none;
	margin: 0;
}

body.sst-co-ab.woocommerce-cart .sst-cart-qty__btn {
	flex: 0 0 auto;
	width: var( --co-qty-size, 36px );
	height: var( --co-qty-size, 36px );
	padding: 0;
	border: 0;
	background: transparent;
	color: inherit;
	font: inherit;
	line-height: 1;
	cursor: pointer;
}

/* Only hidden once the stepper exists — a JS-less cart keeps the real button. */
body.sst-co-ab.woocommerce-cart .sst-cart-form.sst-cart--auto .sst-cart-update {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset( 50% );
	white-space: nowrap;
}

body.sst-co-ab.woocommerce-cart .sst-cart-actions {
	padding-top: var( --co-card-pad );
}

body.sst-co-ab.woocommerce-cart .sst-cart-coupon {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	align-items: center;
}

body.sst-co-ab.woocommerce-cart .sst-cart-coupon__input {
	flex: 1 1 12em;
	min-width: 0;
}

body.sst-co-ab.woocommerce-cart .sst-cart-totals {
	border: 1px solid var( --co-rule );
	border-radius: var( --co-radius );
	background: var( --co-card );
	padding: var( --co-card-pad );
	margin-top: 24px;
}

body.sst-co-ab.woocommerce-cart .sst-cart-totals__title {
	margin: 0 0 12px;
}

body.sst-co-ab.woocommerce-cart .sst-cart-totals__table {
	width: 100%;
	margin: 0;
	border-collapse: collapse;
}

body.sst-co-ab.woocommerce-cart .sst-cart-totals__table th,
body.sst-co-ab.woocommerce-cart .sst-cart-totals__table td {
	padding: 8px 0;
	border: 0;
	vertical-align: top;
	text-align: left;
}

body.sst-co-ab.woocommerce-cart .sst-cart-totals__table td {
	text-align: right;
}

body.sst-co-ab.woocommerce-cart .sst-cart-proceed {
	margin-top: 16px;
}

body.sst-co-ab.woocommerce-cart .sst-cart-cta {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	min-height: 52px;
	text-align: center;
	text-decoration: none;
}

/* Bottom bar is shared with checkout; on the cart it shadows the CTA.
   The height reservation lives in §10b, gated on `.sst-co-bar-on` (L-8). */

/* Desktop: items + coupon left, totals card sticky right. */
@media ( min-width: 1024px ) {
	body.sst-co-ab.woocommerce-cart .woocommerce {
		display: grid;
		grid-template-columns: minmax( 0, 1fr ) minmax( var( --co-rail-min ), var( --co-rail ) );
		/* MUST stay a two-value `gap`, never `column-gap` alone. The theme grids this same
		   element with a `gap: 22px` SHORTHAND (style.css:6011-6017); a column-gap-only rule
		   leaves row-gap:22px in place, and the rail's `grid-row: 1 / 100` then bought 98
		   gutters = 2,156 px of dead white space below the cart (REVIEW-CO-2 C-1). */
		gap: 0 var( --co-gap );
		align-items: start;
	}

	/* Column 1 is AUTO-PLACED on purpose: nothing here may pin the cart form to a row.
	   Pinning it to `grid-row: 1 / 100` filled every cell of column 1, so any member-only
	   or notice child of `.woocommerce` — a policy notice on `woocommerce_before_cart`, a
	   points nudge — auto-placed at row 100 and rendered BELOW the form even when it sits
	   ABOVE it in the DOM. Only the rail is placed; column 1 then follows document order. */
	body.sst-co-ab.woocommerce-cart .woocommerce > * {
		grid-column: 1;
		min-width: 0;
	}

	/* P1-3 — the step band now also renders on the cart, from `woocommerce_before_cart`,
	   so on this page it is a `.woocommerce >` child and therefore a grid item here.
	   It is left AUTO-PLACED (column 1, row 1) on purpose, and the rail keeps rows 1-99.
	   The desktop placement of the band belongs to the only skin that shows it:

	     - A and B hide it outright (variant-a.css:3922 `display: none !important`,
	       variant-b.css:2790 `display: none`). A `display: none` element is not a grid
	       item at all, so for those two arms nothing here changes by even a pixel.
	     - C shows it. Pinning it to `grid-column: 1 / -1` from the BASE cannot work:
	       a full-width auto-placed item cannot fit any row while the rail holds column 2
	       of rows 1-99, so it would be pushed to row 100 and render below the cart. And
	       pinning it to row 1 while shifting the rail to row 2 breaks A and B, where the
	       band is not an item and the cart form would take row 1 with the rail below it.
	       The fix has to know whether the band is displayed, which only the skin does.

	   WS-3c: see NOTES-WS2 §14. variant-c.css:390 already has the hook
	   (`.woocommerce > .sst-co-steps`) and NOTES-WS3c §11 already anticipated this. */
	body.sst-co-ab.woocommerce-cart .woocommerce > .cart-collaterals {
		grid-column: 2;
		grid-row: 1 / 100;
		align-self: start;
		position: var( --co-rail-position, sticky );
		top: var( --co-sticky-top );
	}

	body.sst-co-ab.woocommerce-cart .sst-cart-totals {
		margin-top: 0;
	}

	body.sst-co-ab.woocommerce-cart .sst-cart-item {
		grid-template-columns: 64px minmax( 0, 1fr ) auto auto auto auto;
		grid-template-areas: "thumb main unit qty line remove";
		align-items: center;
		column-gap: 18px;
	}

	body.sst-co-ab.woocommerce-cart .sst-cart-item__unit { grid-area: unit; }
	body.sst-co-ab.woocommerce-cart .sst-cart-item__remove { grid-area: remove; }
}

/* Empty cart. */
body.sst-co-ab.woocommerce-cart .cart-empty,
body.sst-co-ab.woocommerce-cart .return-to-shop {
	text-align: center;
}

body.sst-co-ab.woocommerce-cart .return-to-shop {
	margin-top: 16px;
}

/* ------------------------------------------------------------------ *
 * 10b. Cart page — collisions with the theme (REVIEW-CO-2 H-1, M-1, M-2, L-8).
 * ------------------------------------------------------------------ */

/* H-1 — the theme prints its OWN fixed mobile bar (`samurai_sword_cart_mobile_checkout_bar()`,
   functions.php:4332 on `woocommerce_after_cart`) at z-index 70, which painted over our
   `.sst-co-bar` at 60 and swallowed the arm's CTA. `SST_CO_AB_Render` removes that callback in
   PHP so the node is never printed; this rule is the belt-and-braces half, in case the theme
   re-registers it at a different priority or a fragment re-injects it. The redesign owns the
   mobile CTA on the cart under the test — identically in A, B and C, or the test is unfair. */
body.sst-co-ab.woocommerce-cart .sst-cart-mobile-checkout {
	display: none !important;
}

/* …and the theme reserves room for its bar on <body>. With that bar gone, ours is the single
   source of the reservation (see the `.sst-co-bar-on` rule below). */
@media ( max-width: 760px ) {
	body.sst-co-ab.woocommerce-cart {
		padding-bottom: 0;
	}
}

/* L-8 — reserve bar height only when a bar actually exists. An empty cart has no form, so
   `initCart()` builds no bar, and the old unconditional rule left 96-150px of dead space. */
@media ( max-width: 1023px ) {
	body.sst-co-ab.woocommerce-cart .woocommerce {
		padding-bottom: 0;
	}

	body.sst-co-ab.woocommerce-cart.sst-co-bar-on .woocommerce {
		padding-bottom: var( --co-bar-height );
	}
}

/* M-1 — the theme's <=760px card CSS out-specifies §10 and re-adds `td::before` data-title
   labels (A and C showed them, B did not: the arms differed by accident, not by design) and
   stretches the remove/thumbnail cells into full-width strips. Neutralised in the BASE so all
   three arms match. (0,5,3) beats the theme's (0,2,2). */
@media ( max-width: 760px ) {
	body.sst-co-ab.woocommerce-cart .sst-cart-items tr.sst-cart-item > td::before {
		content: none !important;
	}

	body.sst-co-ab.woocommerce-cart .sst-cart-items tr.sst-cart-item > td.product-remove,
	body.sst-co-ab.woocommerce-cart .sst-cart-items tr.sst-cart-item > td.product-thumbnail,
	body.sst-co-ab.woocommerce-cart .sst-cart-items tr.sst-cart-item > td.product-name,
	body.sst-co-ab.woocommerce-cart .sst-cart-items tr.sst-cart-item > td.product-price,
	body.sst-co-ab.woocommerce-cart .sst-cart-items tr.sst-cart-item > td.product-quantity,
	body.sst-co-ab.woocommerce-cart .sst-cart-items tr.sst-cart-item > td.product-subtotal {
		display: block;
		width: auto;
		min-width: 0;
		float: none;
		text-align: inherit;
	}
}

/* M-2 — `overflow:hidden` plus the theme's `td { display:flex; justify-content:space-between }`
   squeezed the stepper below its content width: at 390px in variant A only ~11px of the `+`
   was visible and hittable. Never let the box shrink below its content. */
body.sst-co-ab.woocommerce-cart .sst-cart-qty {
	flex: 0 0 auto;
	min-width: max-content;
}

/* …and keep the buttons inside the box: A sized them 40px inside a 36px shell. */
body.sst-co-ab.woocommerce-cart .sst-cart-qty__btn,
body.sst-co-ab.woocommerce-cart .sst-cart-qty input.qty {
	height: var( --co-qty-size, 36px );
	box-sizing: border-box;
}


/* ------------------------------------------------------------------ *
 * 11. Notices — the region must never be able to hide a payment error.
 *
 * checkout_rates.md F9 measured the add-to-cart notice in 13/13 arm-A
 * captures and 0/26 arm-B/C captures and asked whether B and C were
 * suppressing `.woocommerce-notices-wrapper`, because that region also
 * carries validation and payment errors.
 *
 * They are not. Audited 2026-08-21: the ONLY rules any skin has on that
 * region are `…-wrapper:empty { display: none }` (variant-b.css:2769,
 * variant-c.css:2624) — which by definition cannot hide a notice that has
 * content — plus margins and a tablet max-width. No skin sets `display`,
 * `visibility` or `opacity` on `.woocommerce-error` / `-message` / `-info`
 * at all. The 13/0/0 split is a capture artefact: WooCommerce notices live
 * in the session and `wc_print_notices()` clears them after the first
 * print, so whichever page a capture run loaded first consumed the notice.
 *
 * The rule below is nonetheless kept as a floor, because the cost of being
 * wrong about this is a customer who cannot see why their payment failed.
 * It is deliberately narrow: only the WRAPPER's `display` is forced, since
 * skin A lays the notice elements themselves out as `display: flex`
 * (variant-a.css:336) and a blanket `display: block !important` would
 * flatten that. `ul.woocommerce-error` is additionally pinned because an
 * error list is always a `<ul>` and no skin lays it out as anything else.
 * ------------------------------------------------------------------ */

html body.sst-co-ab .woocommerce-notices-wrapper:not( :empty ),
html body.sst-co-ab .woocommerce-NoticeGroup {
	display: block !important;
	visibility: visible !important;
	opacity: 1 !important;
	max-height: none !important;
	overflow: visible !important;
}

html body.sst-co-ab ul.woocommerce-error {
	display: block !important;
	visibility: visible !important;
	opacity: 1 !important;
}

/* ------------------------------------------------------------------ *
 * 12. The support chat launcher vs the cart's total and CTA (P1-1).
 *
 * `sst-order-help-chat` pins a 56x56 launcher (3.5rem, order-help-chat.css:82)
 * into the bottom-right corner at a 16px inset (`bottom/right: max(1rem,
 * safe-area)`) with `z-index: 1200` — twenty times ours. It excludes itself
 * from checkout (`sst_ohc_is_checkout_context()`, sst-order-help-chat.php:118)
 * but NOT from the cart, so on the cart it lands on live content: it covers
 * `Total ¥54,000` in B and C at 412/430, `~270 pts` in A, the Calculate
 * shipping link at 412, the CTA corner in C at 1024x768, and the right end of
 * `Proceed to checkout · ¥27,000` in all three arms at 1280
 * (cart.md F6, member_cart.md MC-03).
 *
 * Two layers, because neither alone is sufficient: the launcher is fixed to
 * the VIEWPORT, so raising it only helps while our bar is on screen — and the
 * bar hides exactly when the CTA is visible, which is the reported case.
 *   (a) lift it clear of our fixed bar whenever that bar exists;
 *   (b) keep a 56px corner of the totals card free at every width, so the
 *       launcher rests on padding rather than on a number.
 * Top-anchored placements are excluded: the widget is draggable and
 * `data-position` can be `top-left` / `top-right`.
 * ------------------------------------------------------------------ */

@media ( max-width: 1023px ) {
	body.sst-co-ab.woocommerce-cart.sst-co-bar-on .sst-order-help-chat:not( [data-position^="top"] ) {
		bottom: calc( var( --co-bar-real ) + 12px + env( safe-area-inset-bottom, 0px ) );
	}
}

/* (b) — also the ">=72px bottom clearance at >=1280" cart.md F6 asks for: with
   the sticky rail the CTA is the card's last child, so this is what stops it
   resting in the launcher's corner. */
body.sst-co-ab.woocommerce-cart .sst-cart-totals {
	padding-bottom: calc( var( --co-card-pad ) + 56px );
}

/* …and below 480 no right-aligned value may sit in the launcher's column. */
@media ( max-width: 479px ) {
	body.sst-co-ab.woocommerce-cart .sst-cart-totals {
		padding-right: calc( var( --co-card-pad ) + 48px );
	}
}

/* ------------------------------------------------------------------ *
 * 13. Payment details disclosure (P2-3) + the fee companion (P2-6).
 *
 * The details block is now a native `<details>`, so section 5's max-height
 * reveal — which opened it on SELECT — is replaced by the element's own open
 * state. Choosing a payment method must not require reading the small print
 * that only matters after the order is placed (checkout.md D1-2).
 * ------------------------------------------------------------------ */

/* `!important` on purpose, and only on these two: all three skins were written
   against the old reveal-on-select block and variant A still carries its own
   `max-height` pair (variant-a.css:3186 / 3228) at (0,4,3), which outranks
   anything reasonable here. A stale `max-height: 0` on a `<details>` hides the
   summary as well as the content, i.e. the disclosure disappears entirely.
   Remove once the skins have dropped their copies. */
body.sst-co-ab details.sst-pm__details {
	margin-top: 12px;
	max-height: none !important;
	overflow: visible !important;
}

body.sst-co-ab .sst-pm__details-summary {
	cursor: pointer;
	list-style: none;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	min-height: 32px;
}

body.sst-co-ab .sst-pm__details-summary::-webkit-details-marker {
	display: none;
}

body.sst-co-ab .sst-pm__details-summary::after {
	content: "";
	width: 7px;
	height: 7px;
	border-right: 1.5px solid currentColor;
	border-bottom: 1.5px solid currentColor;
	transform: rotate( 45deg ) translate( -2px, -2px );
	transition: transform var( --co-motion ) ease;
}

body.sst-co-ab details.sst-pm__details[ open ] .sst-pm__details-summary::after {
	transform: rotate( -135deg ) translate( -2px, -2px );
}

body.sst-co-ab .sst-pm__details-summary:focus-visible {
	outline: 2px solid var( --co-primary );
	outline-offset: 2px;
}

/* The fee companion replaces the pre-selection fee line rather than stacking
   on it, so the selected card gains no height (checkout_paypal.md PP-06 says
   this block is already the most compressible on the page). */
body.sst-co-ab .sst-pm__total {
	display: none;
	margin: 12px 0 0;
}

body.sst-co-ab .sst-pm.is-selected .sst-pm__total,
body.sst-co-ab li.wc_payment_method--selected .sst-pm__total,
body.sst-co-ab li.wc_payment_method:has( input[ name="payment_method" ]:checked ) .sst-pm__total {
	display: block;
}

body.sst-co-ab .sst-pm.is-selected .sst-pm__fee,
body.sst-co-ab li.wc_payment_method--selected .sst-pm__fee,
body.sst-co-ab li.wc_payment_method:has( input[ name="payment_method" ]:checked ) .sst-pm__fee {
	display: none;
}

body.sst-co-ab .sst-pm__total-amount,
body.sst-co-ab .sst-pm__total-fee {
	font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------ *
 * 14. FedEx rate rows — comparison badges and the price delta (P2-1).
 *
 * The two options differed only by service name, with no transit estimate
 * anywhere (checkout_rates.md F1) — a ¥2,654 decision with nothing to decide
 * on. `samurai-fedex-shipping` 0.3.93 stores no transit time, so the row
 * carries what IS knowable: which is cheapest, which is faster, and what the
 * difference costs. Structure only; the skins own the colours.
 * ------------------------------------------------------------------ */

body.sst-co-ab .sst-ship__badges {
	display: inline-flex;
	flex-wrap: wrap;
	gap: 6px;
	vertical-align: baseline;
}

body.sst-co-ab .sst-ship__badge {
	display: inline-flex;
	align-items: center;
	border-radius: 999px;
	padding: 2px 8px;
	border: 1px solid var( --co-rule );
	white-space: nowrap;
	line-height: 1.4;
}

body.sst-co-ab .sst-ship__diff {
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
	color: var( --co-mute );
}

/* ------------------------------------------------------------------ *
 * 15. Totals regrouping (P2-4): money tight, rewards after the Total.
 * ------------------------------------------------------------------ */

/* One reassurance line under the import-charge rows. It answers the question
   +30% of unexpected cost actually raises — "is there more to pay later?" —
   at the moment it is raised. */
body.sst-co-ab tr.sst-co-prepaid > td {
	text-align: left;
	color: var( --co-mute );
}

body.sst-co-ab tr.sst-co-rewards__head > th {
	text-align: left;
}

/* The reward rows are no longer part of the subtotal-to-total chain, so they
   must not read as money rows. Skins group them further. */
body.sst-co-ab tr.sst-co-reward-row > th,
body.sst-co-ab tr.sst-co-reward-row > td {
	color: var( --co-mute );
}

/* ------------------------------------------------------------------ *
 * 16. Member confirm strip (P4).
 *
 * MC-05: nothing acknowledged the returning customer, and MC-06 measured the
 * in-flow CTA at 4.8–4.9 viewports on a phone because the prefilled form gets
 * the whole first column. One line of confirming replaces eleven fields of
 * reading. Rendered above `form.checkout`, so the >=1024 shell is untouched.
 * ------------------------------------------------------------------ */

body.sst-co-ab .sst-co-member {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 8px 16px;
	margin: 0 0 16px;
	padding: var( --co-card-pad );
	border: 1px solid var( --co-rule );
	border-radius: var( --co-radius );
	background: var( --co-card );
}

body.sst-co-ab .sst-co-member__line {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 4px 10px;
	margin: 0;
	min-width: 0;
}

body.sst-co-ab .sst-co-member__ship {
	color: var( --co-mute );
	min-width: 0;
}

body.sst-co-ab .sst-co-member__edit {
	flex: 0 0 auto;
	min-height: 44px;
	padding: 0 12px;
	border: 1px solid var( --co-rule );
	border-radius: var( --co-radius );
	background: none;
	color: inherit;
	font: inherit;
	cursor: pointer;
}

/* The collapse. NEVER `display: none`: a required control inside a
   `display:none` block cannot be focused, and Chrome then blocks submission
   with "An invalid form control is not focusable" and no visible reason. Zero
   height with `overflow: hidden` keeps every field focusable and reachable by
   constraint validation, and `checkout-ab.js` re-opens the block on `invalid`,
   on `checkout_error` and on the place-order click. */
body.sst-co-ab #customer_details.sst-co-collapsed {
	max-height: 0;
	overflow: hidden;
	margin-bottom: 0;
}

/* ------------------------------------------------------------------ *
 * 17. Phone head compression (P2-5).
 *
 * cart.md F3 / checkout.md D1-5: before any content a phone spent ~135px on
 * a breadcrumb plus a 48px page title, so at 320px the cart showed a sliver
 * of one thumbnail — no price, no quantity, no coupon — and no arm showed a
 * single form field on the checkout. Below 431px the breadcrumb goes and the
 * cart's own title is replaced by one that carries information ("Cart · 1
 * item", rendered server-side by `render_cart_head()` so it is translated).
 * Exactly one visible `h1` at every width.
 * ------------------------------------------------------------------ */

body.sst-co-ab .sst-co-pagehead {
	display: none;
	margin: 0 0 12px;
}

@media ( max-width: 430px ) {
	body.sst-co-ab .woocommerce-breadcrumb,
	body.sst-co-ab .sst-page-breadcrumb,
	body.sst-co-ab .sst-page-header__breadcrumb {
		display: none;
	}

	body.sst-co-ab.woocommerce-cart .sst-co-pagehead {
		display: block;
	}

	/* REVIEW-CO-4 §6.1 — the suppression is conditional on the REPLACEMENT existing, so this
	   can never hide a title it has not replaced. NOTES-WS2 §14.8 previously claimed an upload
	   order removed the mixed-deploy window; it does not, it only chooses the artefact (assets
	   first → a titleless phone cart; includes first → two <h1>s). Gating on
	   `:has(.sst-co-pagehead)` removes the constraint outright, and also covers a PHP fatal or
	   any other partial render — not just this one deploy. Where `:has()` is unsupported
	   (below Chrome 105 / Safari 15.4 / Firefox 121) the rule simply does not match and the
	   benign two-title state is what degrades out, never the titleless one. */
	body.sst-co-ab.woocommerce-cart:has( .sst-co-pagehead ) .sst-page-header h1,
	body.sst-co-ab.woocommerce-cart:has( .sst-co-pagehead ) .entry-title,
	body.sst-co-ab.woocommerce-cart:has( .sst-co-pagehead ) .page-title,
	body.sst-co-ab.woocommerce-cart:has( .sst-co-pagehead ) .woocommerce-page-title {
		display: none;
	}
}


/* ------------------------------------------------------------------ *
 * 18. Shared row anatomy the skins only recolour (WS-3a hand-off).
 * ------------------------------------------------------------------ */

/* co-#12 / MCT-10 — touch targets. cart.md F4: the remove control is a ~16–20px
   glyph and the stepper buttons are 36px, both under the 44px floor the rubric
   asks for, on a destructive control and on the two controls a thumb reaches
   for most. Height is raised here rather than in the skins because the row
   anatomy is shared and the three arms must not differ by touch size.
   `min-height` is used, not `height`, so it wins over §10's
   `height: var(--co-qty-size)` without redefining the token — variant B
   deliberately narrows `--co-qty-size` to 30px below 560px to make the cart fit
   a 320px phone (0.2.3, D2), and that WIDTH decision is left intact. */
@media ( max-width: 1023px ) {
	body.sst-co-ab.woocommerce-cart .sst-cart-qty__btn,
	body.sst-co-ab.woocommerce-cart .sst-cart-qty input.qty {
		min-height: 44px;
	}

	body.sst-co-ab.woocommerce-cart .sst-cart-item__remove .remove {
		min-width: 44px;
		min-height: 44px;
	}
}

/* MCT-13 — the totals card stops stretching on tablets. Between 768 and 1023
   there is no rail yet (§10's two-column grid starts at 1024), so the card ran
   the full single-column width and its label/value pair sat ~700px apart. */
@media ( min-width: 768px ) and ( max-width: 1023px ) {
	body.sst-co-ab.woocommerce-cart .sst-cart-totals {
		max-width: 560px;
	}
}

/* ------------------------------------------------------------------ *
 * 19. ACF's `align-items: start` leaking into the phone/tablet column.
 *
 * `account-checkout.css:328-332` makes `form.checkout` a two-column GRID with
 * `align-items: start`, and its `@media (max-width: 980px)` block (line 3717)
 * switches `display` to `flex` WITHOUT resetting that. In a flex COLUMN the
 * cross axis is horizontal, so `start` stops shrinking nothing vertically and
 * starts shrink-wrapping every child to its own content width: WS-3b measured
 * the order strip at 331px inside a 720px column.
 *
 * That is shared anatomy — A and C inherit exactly the same leak — so the reset
 * belongs here rather than in one skin. (0,3,2) beats ACF's (0,2,2) in both of
 * its blocks. The base's own >=1024 shell sets `align-items: start` deliberately
 * in §1 and is not touched: that rule lives in a `min-width: 1024px` block.
 * ------------------------------------------------------------------ */

@media ( max-width: 1023px ) {
	body.sst-co-ab form.checkout.woocommerce-checkout {
		align-items: stretch;
	}
}
