/* GENERATED by runbooks/deploy/css-split/split.py (backlog #3 Phase 1) from finalist.css — DO NOT EDIT.
   This is finalist.css with the other surfaces' blocks removed, order preserved. Edit finalist.css and re-run. */
:root { --sd-sticky-top: 87px; }
@media (min-width: 900px) { :root { --sd-sticky-top: 130px; } }
/* ---------- woo notices in the dark voice (site-wide) ---------- */
.woocommerce-message,
.woocommerce-info,
.woocommerce-error li,
.woocommerce-error {
	background: rgba(16, 26, 44, .92) !important;
	color: #eef2f8 !important;
	border-top-color: var(--ccr-blue) !important;
	border-radius: 0 0 12px 12px;
}
.woocommerce-message a,
.woocommerce-info a { color: var(--ccr-blue) !important; }
.woocommerce-error,
.woocommerce-error li { border-top-color: var(--ccr-accent) !important; }
.woocommerce-message::before { color: var(--ccr-blue) !important; }
.woocommerce-error::before,
.woocommerce-error li::before { color: var(--ccr-accent) !important; }

/* =============================================================================
   PRODUCT TILES (global) — the shared jet-woo listing card, redesigned in the
   finalist voice. Applies wherever product tiles render: cart loadout, shop
   archive, category pages, related products. (Kicks off the shop-card look.)
   ============================================================================= */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) {
	background: rgba(255, 255, 255, .03);
	border: 1px solid rgba(255, 255, 255, .08);
	border-radius: 16px;
	overflow: hidden;
	transition: transform .22s ease, border-color .22s ease;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart):hover {
	transform: translateY(-4px);
	border-color: rgba(56, 174, 232, .4);
	z-index: 2; /* lift paints above neighbors */
}
/* the jet grid ships grid-collapse-gap — row spacing so the hover lift
   never overlaps the row above (Jake 2026-08-11). The listing is FLEX
   (items sized flex-basis: 100%/var(--columns)), so adding column-gap
   alone makes rows wrap one short — re-derive the item basis from jet's
   own --columns minus the gap share. One rule, every breakpoint. */
.jet-listing-grid__items:has(.jet-woo-builder-archive-add-to-cart) {
	row-gap: 18px !important;
	column-gap: 12px !important;
}
.jet-listing-grid__items:has(.jet-woo-builder-archive-add-to-cart) > .jet-listing-grid__item {
	flex-basis: calc(100% / var(--columns) - 12px * (var(--columns) - 1) / var(--columns)) !important;
	max-width: calc(100% / var(--columns) - 12px * (var(--columns) - 1) / var(--columns)) !important;
}
/* desktop runs 4-up (Jake 2026-08-11: 5-up made the photos too small) —
   override the --columns var; the basis rule above follows automatically.
   !important: the Elementor template CSS (post-39372) sets --columns:5 at
   (0,4,0) widget-scope specificity. Media-scoped so tablet-2/mobile-1 keep
   their own counts. */
@media (min-width: 1025px) {
	.jet-listing-grid__items.grid-col-desk-5:has(.jet-woo-builder-archive-add-to-cart) { --columns: 4 !important; }
}
/* one paint layer: inner template sections go transparent */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-section,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-wrap,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-column {
	background: transparent !important;
	border: 0 !important;
	box-shadow: none !important;
}
/* product photo: white framed tile, inset from the card edge. 5:4 frame —
   the original square was ~half the card height and product shots are almost
   all wider than tall, so the cap trims pure white letterbox (Jake 2026-08-11:
   tiles too tall) */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-image img,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-thumbnail img {
	background: #fff;
	border-radius: 12px;
	border: 1px solid rgba(255, 255, 255, .06);
	object-fit: contain;
	width: 100% !important;
	/* !important: the listing template's Elementor CSS (post-39820,
	   .elementor-element-94a81a8 img) pins height:240px */
	height: auto !important;
	aspect-ratio: 5 / 4 !important;
}
/* the wrapper (link/figure) SHRINK-WRAPS to the image's width attribute —
   portrait products ship a 206px-wide medium, so their img rendered narrower
   than the column and the 5:4 frame came out ~6px shorter (Magpul MOE-K2
   family; Jake 2026-08-12). Full-width the whole chain. */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-image a,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-image figure,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-thumbnail a,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-thumbnail figure {
	display: block !important;
	width: 100% !important;
	max-width: 100% !important;
}
/* title */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .bcm-loop-title-text,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .bcm-loop-title-text a,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-title,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-title a {
	color: #eef2f8 !important;
	font-weight: 700 !important;
	font-size: .95rem !important;
	line-height: 1.32 !important;
	text-decoration: none !important;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .bcm-loop-title-text a:hover,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-title a:hover {
	color: var(--ccr-blue) !important;
}
/* "Online Inventory" / "In Store" chip: quiet mono badge, not a red alarm.
   (Plain declarations — the loop markup is ours now, class-only, via
   inc/catalog-labels.php; the labeler's inline styles no longer reach it.) */
.jet-listing-grid__item span.bcm-loop-prefix {
	display: inline-block;
	background: transparent;
	border: 1px solid rgba(56, 174, 232, .45);
	color: var(--ccr-blue);
	font-family: 'DM Mono', monospace;
	font-size: .6rem;
	font-weight: 500;
	letter-spacing: .14em;
	text-transform: uppercase;
	padding: 3px 8px;
	border-radius: 99px;
	margin-top: 4px;
	white-space: nowrap;
}
/* price in the mono voice */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-product-price,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-price,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-price .woocommerce-Price-amount {
	font-family: 'DM Mono', monospace !important;
	color: #fff !important;
	font-size: 1.02rem !important;
	font-weight: 700 !important;
}
/* stock status: mono caps, keep the state colors. One line ALWAYS — the
   longest state ("Only 4 left in stock") was wrapping, which gave Only-X and
   out-of-stock cards extra height that In-stock cards didn't have. Tighter
   tracking + full-width widget (the template pins it narrower) make it fit. */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-stock-status,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-stock-status *,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-stock-status,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-stock-status * {
	font-family: 'DM Mono', monospace !important;
	font-size: .76rem !important; /* .68 → .76 Jake 2026-08-17 ("a bit" bigger) */
	letter-spacing: .04em !important;
	text-transform: uppercase !important;
	white-space: nowrap !important;
	/* explicit line box: an inherited sub-1 line-height + any overflow clip
	   was slicing the glyphs horizontally mid-height */
	line-height: 1.5 !important;
	height: auto !important;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-jet-woo-builder-archive-stock-status {
	width: 100% !important;
	max-width: 100% !important;
	overflow: visible;
	height: auto !important;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-stock-status p.stock,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-stock-status p.stock { margin: 0 !important; }
/* add to cart: the family red */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .add_to_cart_button,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-jet-woo-builder-archive-add-to-cart .button {
	background: var(--ccr-accent) !important;
	color: #fff !important;
	border: 0 !important;
	border-radius: 10px !important;
	font-weight: 800 !important;
	font-size: .78rem !important;
	letter-spacing: .08em !important;
	text-transform: uppercase !important;
	padding: 11px 12px !important;
	box-shadow: none !important;
	transition: all .2s ease !important;
	white-space: nowrap !important;
}
/* Hover mirrors the paint rule's FULL selector pair above, not just the
   .add_to_cart_button half. Why it matters (Jake, 2026-08-16 — "the View
   Product button on Shop doesn't have the blue hover"): out-of-stock and
   external products render "View Product" / "Select options", which carry
   .button but NOT .add_to_cart_button. Those only matched the paint rule's
   second selector — (0,5,0) and !important — so the red base outranked the
   (0,3,1) hover fix down at ~L4590 and the button never changed colour. Adding
   :hover here makes these (0,6,0), which beats the base paint outright.
   General rule: a hover rule must out-specify EVERY selector that paints the
   element, not just the one it was written next to. */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .add_to_cart_button:hover,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .add_to_cart_button:focus-visible,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-jet-woo-builder-archive-add-to-cart .button:hover,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-jet-woo-builder-archive-add-to-cart .button:focus-visible {
	background: var(--ccr-blue) !important;
	color: #fff !important;
	transform: translateY(-2px);
}
/* sale badge reads oversized in the grids (Jake 2026-08-12 desktop 4-up;
   2026-08-14 mobile cart loadout) — compact at ALL widths. The wishlist/
   compare circles below stay desktop-only (mobile has its own 32px rule). */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-product-badge {
	font-size: .8rem !important;
	padding: 5px 10px !important;
	margin: 10px 0 0 10px !important;
	border-radius: 6px !important;
}
@media (min-width: 768px) {
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link,
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-compare-button__link {
		width: 38px !important;
		height: 38px !important;
		display: inline-flex !important;
		align-items: center !important;
		justify-content: center !important;
	}
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link svg,
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-compare-button__link svg {
		width: 17px !important;
		height: 17px !important;
	}
}

/* wishlist / compare affordances: quiet ghost circles */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-compare-button__link {
	background: rgba(10, 15, 28, .75) !important;
	border: 1px solid rgba(255, 255, 255, .15) !important;
	color: #dbe3f0 !important;
	border-radius: 99px !important;
	transition: all .2s ease !important;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link:hover,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-compare-button__link:hover {
	border-color: var(--ccr-blue) !important;
	color: var(--ccr-blue) !important;
}


/* desktop: the template pins the image WIDGET to ~80% width — let the photo
   fill the tile (Jake 2026-08-11: images too small on desktop; mobile is
   sized separately and stays as-is) */
@media (min-width: 768px) {
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-image,
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-jet-woo-builder-archive-product-thumbnail {
		width: 100% !important;
		max-width: 100% !important;
	}
}

/* every content widget spans the full card width, text flush left with the
   image edge — the template centered ~80%-wide widgets, which read as random
   mid-card alignment and wasted fitting room (Jake 2026-08-11). The absolute
   overlays (wishlist/compare circles, sale badge) keep their own geometry. */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-wrap > .elementor-widget:not(.elementor-widget-jet-wishlist-button):not(.elementor-widget-jet-compare-button):not(.elementor-widget-jet-woo-builder-archive-sale-badge) {
	width: 100% !important;
	max-width: 100% !important;
	margin-left: 0 !important;
	margin-right: 0 !important;
	text-align: left;
}
/* …and the CONTAINER inside each widget: the template ALSO puts horizontal
   margins/paddings there (20px at its breakpoints) — zeroing the widget alone
   left text sitting right of the image edge (Jake 2026-08-12, all listings).
   All widths; overlays excluded same as above. */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-wrap > .elementor-widget:not(.elementor-widget-jet-wishlist-button):not(.elementor-widget-jet-compare-button):not(.elementor-widget-jet-woo-builder-archive-sale-badge) > .elementor-widget-container {
	margin-left: 0 !important;
	margin-right: 0 !important;
	padding-left: 0 !important;
	padding-right: 0 !important;
}

/* ---------- tile internals normalized: fixed slots, ledger alignment ---------- */
.jet-listing-grid__items { align-items: stretch; }
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) { height: 100%; display: flex; flex-direction: column; }
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) > div { display: flex; flex-direction: column; flex: 1; }
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-wrap {
	display: flex !important;
	flex-direction: column;
	flex: 1;
}
/* title: three-line slot, clamped (slot height follows the 1.32 line-height;
   the 3-line clamp itself stays — DB-backed, 54% of titles need it).
   The loop markup is class-only now (inc/catalog-labels.php) — no inline
   styles to fight. */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .bcm-loop-title-text {
	display: -webkit-box;
	-webkit-line-clamp: 3;
	line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
	min-height: 3.96em;
}
/* chip line: constant height whether or not a chip renders */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .bcm-loop-title-wrap { min-height: 1.5em; }
/* price + stock: single fixed lines */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-jet-woo-builder-archive-product-price { min-height: 1.75em; margin-top: 2px !important; }
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-jet-woo-builder-archive-stock-status { min-height: 1.4em; }
/* button pinned to the card floor */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-jet-woo-builder-archive-add-to-cart {
	margin-top: auto !important;
	padding-top: 8px;
}


/* sale prices: Woo renders <del>old</del> <ins>new</ins>, which was wrapping
   to two lines and making sale tiles taller than the row. One fixed line:
   old price small/dim inline, sale price keeps the mono voice (the SALE
   badge widget already flags the deal). When a del is present BOTH prices
   size down so the pair fits the tile instead of clipping at its edge. */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-jet-woo-builder-archive-product-price {
	width: 100% !important;
	max-width: 100% !important;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-product-price,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-price {
	white-space: nowrap;
	overflow: hidden;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-price:has(del) .woocommerce-Price-amount {
	font-size: .85rem !important;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-price del,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-price del .woocommerce-Price-amount,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-price del .woocommerce-Price-currencySymbol {
	display: inline !important;
	font-size: .72rem !important;
	color: #9aa7bd !important;
	font-weight: 500 !important;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-price ins,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-price ins .woocommerce-Price-amount,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-price ins .woocommerce-Price-currencySymbol {
	text-decoration: none !important;
	color: #fff !important;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-price ins { margin-left: 4px; }

/* mobile: single-column grid — no cross-card alignment to preserve, so the
   fixed slots collapse and the card hugs its content (Jake 2026-08-11: too
   much dead space). Flatter image, tighter widget gaps and inset. */
@media (max-width: 767px) {
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .bcm-loop-title-text { min-height: 0; }
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .bcm-loop-title-wrap { min-height: 0; }
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-jet-woo-builder-archive-product-price { min-height: 0; }
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-jet-woo-builder-archive-stock-status { min-height: 0; }
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-image img,
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-woo-builder-archive-product-thumbnail img {
		aspect-ratio: 16 / 10 !important;
	}
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget:not(:last-child) { margin-bottom: 8px !important; }
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-section { padding: 14px 16px !important; }
	/* breathing room around the title — the collapse round left it sitting
	   directly on the photo (Jake 2026-08-11 mobile screenshots) */
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-shortcode,
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-jet-woo-builder-archive-product-title {
		margin-top: 10px !important;
	}
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-jet-woo-builder-archive-add-to-cart {
		margin-top: 10px !important;
		padding-top: 0;
	}
}


/* the DM Mono dollar sign is too spindly — solid DM Sans symbol, mono digits
   (applies everywhere prices went mono: tiles, cart rows, totals).
   Weight was 800 and read CHUNKY on the tiles, where the price is smallest
   (Jake, 2026-08-14) → tried 700 (matching the product page + checkout ledger),
   now trying 600. NOTE: the product page and checkout ledger still declare 700
   in their own rules — if 600 sticks, those two want the same treatment so the
   symbol reads identically everywhere. */
.jet-listing-grid__item .woocommerce-Price-currencySymbol,
body.woocommerce-cart .woocommerce-Price-currencySymbol,
.cart_totals .woocommerce-Price-currencySymbol {
	font-family: 'DM Sans', sans-serif !important;
	font-weight: 600 !important;
	font-size: .9em;
	margin-right: 1px;
}


/* add-to-cart AJAX feedback: spinner rides inside the button, right edge */
.jet-listing-grid__item .add_to_cart_button { position: relative !important; }
.jet-listing-grid__item .add_to_cart_button.loading { opacity: .75; }
.jet-listing-grid__item .add_to_cart_button.loading::after {
	position: absolute !important;
	top: 50% !important;
	right: 10px !important;
	left: auto !important;
	bottom: auto !important;
	margin: -.5em 0 0 !important;
}
.jet-listing-grid__item .add_to_cart_button.added::after {
	position: absolute !important;
	top: 50% !important;
	right: 10px !important;
	left: auto !important;
	margin: -.5em 0 0 !important;
}
/* spinner centered in its button (Jake 2026-09-24). The ::after inherited the button line-height (18.7px box)
   against a -.5em (6.2px) pull-up, so the cog sat 3px low on tiles; the PDP button kept woo's top .618em and sat
   9px high. A square 1em box centered on the button fixes both and makes the spin turn about the cog's center. */
.jet-listing-grid__item .add_to_cart_button.loading::after,
.jet-listing-grid__item .add_to_cart_button.added::after,
body.single-product .sd-pp__atc.loading::after,
body.single-product .sd-pp__atc.added::after {
	position: absolute !important;
	top: 50% !important;
	bottom: auto !important;
	left: auto !important;
	width: 1em !important;
	height: 1em !important;
	line-height: 1 !important;
	text-align: center !important;
	margin: -.5em 0 0 !important;
	transform-origin: 50% 50% !important;
}
body.single-product .sd-pp__atc { position: relative; }
body.single-product .sd-pp__atc.loading::after,
body.single-product .sd-pp__atc.added::after { right: 16px !important; }
/* the "View cart" link that appears after adding: quiet blue, centered */
.jet-listing-grid__item .added_to_cart.wc-forward {
	display: block !important;
	text-align: center;
	color: var(--ccr-blue) !important;
	font-size: .78rem !important;
	font-weight: 700 !important;
	letter-spacing: .06em;
	text-transform: uppercase;
	text-decoration: none !important;
	margin-top: 8px;
}

/* ---------- back to top (mobile only): glass circle, chevron SVG ----------
   body button.sd-backtop = (0,1,2): the KIT's `button` rule at (0,1,1) forces
   border-radius:0 / padding:15px 35px / its red background onto any weaker
   selector (the runbook rule applies to OUR buttons too) */
body button.sd-backtop {
	display: none;
	position: fixed;
	right: 16px;
	bottom: 18px;
	z-index: 90;
	width: 48px;
	height: 48px;
	border-radius: 999px;
	background: rgba(13, 20, 36, .72);
	-webkit-backdrop-filter: blur(10px);
	backdrop-filter: blur(10px);
	border: 1px solid rgba(56, 174, 232, .5);
	color: #9fd8f5;
	padding: 0;
	background-color: rgba(13, 20, 36, .72);
	box-shadow: 0 8px 24px rgba(0, 0, 0, .45);
	cursor: pointer;
	opacity: 0;
	pointer-events: none;
	transform: translateY(10px) scale(.9);
	transition: opacity .25s ease, transform .25s ease, border-color .2s ease, color .2s ease;
}
@media (max-width: 1024px) {
	body button.sd-backtop { display: flex; align-items: center; justify-content: center; }
}
body button.sd-backtop.is-visible {
	opacity: 1;
	pointer-events: auto;
	transform: none;
}
/* tap leaves :focus stuck on mobile and the KIT's button:focus (0,2,1)
   re-squares it — restate the face on every interactive state */
body button.sd-backtop:hover,
body button.sd-backtop:focus,
body button.sd-backtop:active {
	border-radius: 999px;
	padding: 0;
	background: rgba(13, 20, 36, .8);
	background-color: rgba(13, 20, 36, .8);
	border-color: var(--ccr-blue);
	color: #fff;
	outline: none;
}
body button.sd-backtop:active {
	transform: scale(.9);
}

/* =============================================================================
   PRODUCT PASS (Phase 4b #3) — native single-product template (sd-pp).
   Replaces the JWB template 39324 render: gallery card left, sticky buy panel
   right, description/attributes/related full-width below. Calm register.
   Scope: body.single-product / .sd-pp — inert while SD_NATIVE_PRODUCT=false.
   KIT-AMBUSH NOTE: every <button> below declares its full face at (0,2,0)+
   and restates radius/color/padding on :hover/:focus/:active (kit-39208
   paints #a51f1c + radius 0 + padding 15px 35px on underspecified buttons).
   ============================================================================= */
body.single-product { background: radial-gradient(ellipse 130% 70% at 50% -5%, #101a2c 0%, #05070d 55%) !important; }

.sd-pp {
	max-width: 1240px;
	margin: 0 auto;
	padding: clamp(18px, 3vw, 34px) 20px 48px;
}

/* ---------- breadcrumbs: settle into mono ---------- */
.sd-pp__crumbs,
.sd-pp__crumbs a,
.sd-pp .woocommerce-breadcrumb,
.sd-pp .woocommerce-breadcrumb a {
	font-family: 'DM Mono', monospace;
	font-size: .74rem;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--ccr-text-dim);
	text-decoration: none;
}
.sd-pp__crumbs a:hover,
.sd-pp .woocommerce-breadcrumb a:hover { color: var(--ccr-blue); }
.sd-pp__crumb-sep { margin: 0 8px; opacity: .5; }
.sd-pp__crumbs { margin-bottom: 18px; }

/* ---------- layout: media left, sticky panel right ---------- */
.sd-pp__layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 420px;
	gap: 26px;
	align-items: start;
}
.sd-pp__panel {
	position: sticky;
	top: var(--sd-sticky-top);
	background: rgba(255, 255, 255, .03);
	border: 1px solid rgba(255, 255, 255, .08);
	border-radius: 16px;
	padding: 24px;
	display: flex;
	flex-direction: column;
	gap: 14px;
}

/* ---------- gallery ---------- */
.sd-pp-gallery {
	background: rgba(255, 255, 255, .03);
	border: 1px solid rgba(255, 255, 255, .08);
	border-radius: 16px;
	padding: 14px;
}
.sd-pp-gallery__main {
	margin: 0;
	background: #fff;
	border-radius: 12px;
	overflow: hidden;
}
.sd-pp-gallery__main--noimg { aspect-ratio: 5 / 4; background: rgba(255, 255, 255, .05); }
body .sd-pp-gallery button.sd-pp-gallery__zoom {
	display: block;
	width: 100%;
	padding: 0;
	margin: 0;
	background: #fff;
	background-color: #fff;
	border: 0;
	border-radius: 12px;
	cursor: zoom-in;
}
body .sd-pp-gallery button.sd-pp-gallery__zoom:hover,
body .sd-pp-gallery button.sd-pp-gallery__zoom:focus,
body .sd-pp-gallery button.sd-pp-gallery__zoom:active {
	background: #fff;
	background-color: #fff;
	border-radius: 12px;
	padding: 0;
	color: inherit;
	outline: none;
}
body .sd-pp-gallery button.sd-pp-gallery__zoom:focus-visible { outline: 2px solid var(--ccr-blue); outline-offset: 2px; }
.sd-pp-gallery__img,
.sd-pp-gallery__zoom img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 5 / 4;
	object-fit: contain;
}
.sd-pp-gallery__thumbs {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin-top: 10px;
}
body .sd-pp-gallery button.sd-pp-gallery__thumb {
	width: 64px;
	height: 64px;
	padding: 0;
	background: #fff;
	background-color: #fff;
	border: 1px solid rgba(255, 255, 255, .14);
	border-radius: 8px;
	overflow: hidden;
	cursor: pointer;
	transition: border-color .15s ease;
}
body .sd-pp-gallery button.sd-pp-gallery__thumb:hover,
body .sd-pp-gallery button.sd-pp-gallery__thumb:focus,
body .sd-pp-gallery button.sd-pp-gallery__thumb:active {
	background: #fff;
	background-color: #fff;
	border-radius: 8px;
	padding: 0;
	color: inherit;
	border-color: rgba(56, 174, 232, .55);
	outline: none;
}
body .sd-pp-gallery button.sd-pp-gallery__thumb.is-active { border-color: var(--ccr-blue); }
.sd-pp-gallery__thumb img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}

/* ---------- lightbox (native <dialog>) ---------- */
.sd-pp-gallery__lightbox {
	background: transparent;
	border: 0;
	padding: 0;
	max-width: 100vw;
	max-height: 100vh;
	outline: none;
}
.sd-pp-gallery__lightbox::backdrop { background: rgba(3, 5, 10, .88); }
.sd-pp-gallery__lb-img {
	display: block;
	max-width: min(92vw, 1200px);
	max-height: 86vh;
	border-radius: 12px;
	background: #fff;
}
body .sd-pp-gallery .sd-pp-gallery__lightbox button {
	position: fixed;
	width: 44px;
	height: 44px;
	padding: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(255, 255, 255, .08);
	background-color: rgba(255, 255, 255, .08);
	border: 1px solid rgba(255, 255, 255, .2);
	border-radius: 999px;
	color: #eef2f8;
	font-size: 1.3rem;
	line-height: 1;
	cursor: pointer;
	transition: all .15s ease;
}
body .sd-pp-gallery .sd-pp-gallery__lightbox button:hover,
body .sd-pp-gallery .sd-pp-gallery__lightbox button:focus,
body .sd-pp-gallery .sd-pp-gallery__lightbox button:active {
	background: rgba(56, 174, 232, .25);
	background-color: rgba(56, 174, 232, .25);
	border-radius: 999px;
	padding: 0;
	color: #fff;
	border-color: rgba(56, 174, 232, .6);
	outline: none;
}
.sd-pp-gallery__lb-close { top: 18px; right: 18px; }
.sd-pp-gallery__lb-prev { left: 18px; top: 50%; transform: translateY(-50%); }
.sd-pp-gallery__lb-next { right: 18px; top: 50%; transform: translateY(-50%); }

/* ---------- panel: chip · title · price · stock ---------- */
.sd-pp__chip {
	align-self: flex-start;
	border: 1px solid rgba(56, 174, 232, .45);
	color: var(--ccr-blue);
	font-family: 'DM Mono', monospace;
	font-size: .66rem;
	letter-spacing: .14em;
	text-transform: uppercase;
	padding: 3px 9px;
	border-radius: 99px;
	white-space: nowrap;
}
.sd-pp h1.sd-pp__title {
	font-size: clamp(1.3rem, 2.1vw, 1.7rem);
	font-weight: 800;
	line-height: 1.28;
	color: #fff;
	margin: 0;
}
/* CENTRE, not baseline (Jake, 2026-08-15: "I don't want it to step up like a
   ladder"). The row mixes three different sizes — an 11.5px padded SALE pill,
   the 15px struck price and the 23px sale price — and baseline alignment pushed
   the pill's BOX ~7px below the sale price, because a padded pill's own text
   baseline sits inside its padding. Centred, all three share one centre line.
   (Supersedes the 2.14.x "sale row baseline fix", which was about the two price
   texts; the pill is what actually needed different treatment.) */
.sd-pp__price {
	display: flex;
	align-items: center;
	gap: 10px;
	font-family: 'DM Mono', monospace;
	font-size: 1.45rem;
	color: #fff;
}
.sd-pp__price .woocommerce-Price-amount,
.sd-pp__price .woocommerce-Price-currencySymbol { color: #fff; }
.sd-pp__price .woocommerce-Price-currencySymbol { font-family: 'DM Sans', sans-serif; font-weight: 600; }
.sd-pp__price del,
.sd-pp__price del .woocommerce-Price-amount,
.sd-pp__price del .woocommerce-Price-currencySymbol {
	color: var(--ccr-text-dim);
	font-size: .95rem;
	text-decoration: line-through;
}
.sd-pp__price ins,
.sd-pp__price ins .woocommerce-Price-amount { text-decoration: none; color: #fff; }
.sd-pp__sale-chip {
	/* CENTRE. This was `align-self: baseline` from the product pass, which
	   silently opted the chip OUT of the row's `align-items: center` added
	   2026-08-15 — so the ladder Jake had removed came back the moment the sale
	   price grew taller than the chip (measured 2026-08-16: chip centre 347 vs
	   both prices at 352). The row and the chip now agree. */
	align-self: center;
	background: rgba(210, 64, 52, .16);
	border: 1px solid var(--ccr-accent);
	color: #ff8a7d;
	font-family: 'DM Mono', monospace;
	font-size: .72rem;
	font-weight: 700;
	letter-spacing: .16em;
	text-transform: uppercase;
	padding: 3px 11px;
	border-radius: 99px;
}
/* stock line: mono caps, state colors owned HERE. The legacy main.css
   single-product stock family (L1132+/L1287+) forces size/weight/transform
   with !important — counters reverted to plain 2026-08-13 (batch 3 pruned). */
body.single-product .sd-pp__stock p.stock {
	font-family: 'DM Mono', monospace;
	font-size: .82rem;
	font-weight: 500;
	letter-spacing: .1em;
	text-transform: uppercase;
	line-height: 1.5;
	margin: 0;
}
.sd-pp__stock p.stock.in-stock { color: #2ecc71; -webkit-text-fill-color: #2ecc71; }
.sd-pp__stock p.stock.in-stock.low-stock { color: #e6a23c; -webkit-text-fill-color: #e6a23c; }
.sd-pp__stock p.stock.out-of-stock { color: rgba(226, 85, 85, .85); -webkit-text-fill-color: rgba(226, 85, 85, .85); }
/* OUT OF STOCK a step up from the .82rem stock line (backlog #68, Jake 2026-09-23). The body prefix matters:
   the base rule above is (0,3,2) and beats a bare .out-of-stock (0,3,1); in-stock / low-stock keep .82rem. */
body.single-product .sd-pp__stock p.stock.out-of-stock { font-size: .92rem; }
/* state dot: was the legacy family's ::before (quarantined in batch 3) — owned
   here now; color inherits from the state color above */
.sd-pp__stock p.stock::before {
	content: "●";
	font-size: .7em;
	vertical-align: .12em;
	line-height: 1;
	margin-right: .35em;
}

/* ---------- buy box ---------- */
.sd-pp form.cart {
	display: flex;
	align-items: stretch;
	gap: 10px;
	margin: 4px 0 2px;
}
/* qty: same sd-qty voice as the cart (scoped fresh — the cart rules stay cart-only) */
body.single-product .sd-pp .quantity input[type="number"]::-webkit-outer-spin-button,
body.single-product .sd-pp .quantity input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none !important; margin: 0 !important; }
body.single-product .sd-pp .quantity input[type="number"] { -moz-appearance: textfield !important; appearance: textfield !important; }
body.single-product .sd-pp .sd-qty {
	display: inline-flex;
	align-items: stretch;
	height: 100%;
	min-height: 50px;
	border: 1px solid rgba(255, 255, 255, .16);
	border-radius: 10px;
	overflow: hidden;
	background: rgba(255, 255, 255, .04);
}
body.single-product .sd-pp .sd-qty:focus-within { border-color: rgba(56, 174, 232, .65); }
body.single-product .sd-pp .sd-qty .sd-qty__btn {
	background: transparent !important;
	background-color: transparent !important;
	color: #dbe3f0 !important;
	border: 0 !important;
	border-radius: 0 !important;
	width: 34px !important;
	min-height: 100% !important;
	padding: 0 !important;
	margin: 0 !important;
	font-size: 1.05rem !important;
	font-weight: 600 !important;
	line-height: 1 !important;
	cursor: pointer;
	transition: all .15s ease !important;
}
body.single-product .sd-pp .sd-qty .sd-qty__btn:hover,
body.single-product .sd-pp .sd-qty .sd-qty__btn:focus,
body.single-product .sd-pp .sd-qty .sd-qty__btn:active {
	color: var(--ccr-blue) !important;
	background: rgba(56, 174, 232, .08) !important;
	background-color: rgba(56, 174, 232, .08) !important;
	border-radius: 0 !important;
	padding: 0 !important;
}
html body.single-product .sd-pp .sd-qty .qty,
html body.single-product .sd-pp .sd-qty .qty:focus {
	border: 0 !important;
	background: transparent !important;
	width: 48px !important;
	min-height: 48px !important;
	height: 100%;
	margin: 0 !important;
	padding: 0 !important;
	border-radius: 0 !important;
	color: #eef2f8 !important;
	font-family: 'DM Mono', monospace !important;
	text-align: center;
	outline: none !important;
}
/* fallback face for the pre-JS instant (bare input before .sd-qty wraps it) */
body.single-product .sd-pp form.cart .quantity .qty {
	background: rgba(255, 255, 255, .05);
	border: 1px solid rgba(255, 255, 255, .16);
	border-radius: 10px;
	color: #eef2f8;
	font-family: 'DM Mono', monospace;
	text-align: center;
	min-height: 50px;
	width: 72px;
}
/* ATC: the main.css preamble supplies red/blue bg+color (!important, intended);
   we own everything else and restate the face on every interactive state */
body.single-product .sd-pp button.sd-pp__atc {
	flex: 1;
	min-height: 50px;
	padding: 12px 24px;
	border: 0;
	border-radius: 10px;
	font-family: 'DM Sans', sans-serif;
	font-size: .9rem;
	font-weight: 800;
	letter-spacing: .1em;
	text-transform: uppercase;
	cursor: pointer;
	transition: all .2s ease;
}
body.single-product .sd-pp button.sd-pp__atc:hover,
body.single-product .sd-pp button.sd-pp__atc:focus,
body.single-product .sd-pp button.sd-pp__atc:active {
	border-radius: 10px;
	padding: 12px 24px;
	border: 0;
	color: #fff;
	transform: translateY(-2px);
	outline: none;
}
body.single-product .sd-pp button.sd-pp__atc:focus-visible { outline: 2px solid var(--ccr-blue); outline-offset: 2px; }

/* ---------- OOS / Omnisend ---------- */
.sd-pp .oos-notify-wrap { margin: 4px 0 0; }
.sd-pp .oos-notify-wrap,
.sd-pp .oos-notify-wrap > div,
.sd-pp .oos-notify-wrap iframe,
.sd-pp .oos-notify-wrap form { margin-left: 0; padding-left: 0; max-width: 100%; }

/* ---------- Omnisend back-in-stock form (remote-injected markup) ----------
   Omnisend renders the embedded form with its own <style> block: Arial, the
   RETIRED legacy red #c0392b (2px input border + button), radius 8. Contained
   here in the finalist voice — element selectors (its classes carry the form
   ID) + !important (its stylesheet is remote and may change). Scoped to the
   product page wrap only. */

/* HEADING — backlog #24 (Jake, 2026-09-17): this used to be DM Mono .85rem
   uppercase in --ccr-blue, which is the SAME register as .sd-pp__taxfree
   directly above it (DM Mono .78rem uppercase --ccr-blue). Two near-identical
   blue mono lines stacked as flex siblings read as a pair, and this one won
   the eye because it is larger and wider-tracked — that similarity WAS the
   "competes with the sales tax line" complaint. Now in the product title's
   voice instead, so blue mono means "tax messaging" again.
   ⚠ Do NOT "simplify" font-family to `inherit` the way .sd-pp__sechead does
   (:5542). This h3 inherits from OMNISEND's injected container, not from our
   panel, so `inherit` computes to Arial — verified in the live DOM. The family
   must be named. 'DM Sans' also matches this block's own input/button/p rules.
   ⚠ text-transform: none does NOT give sentence case — the caps are in
   Omnisend's form config, not added here. A lowercase + ::first-letter trick
   was tested and rejected: the wrap holds a SECOND, hidden h3 for the success
   state ("Thanks. Keep an eye out for updates!") which it mangles to
   "Thanks. keep ...". Sentence case has to be set in the Omnisend form editor;
   this rule renders whatever text is typed there. */
.sd-pp .oos-notify-wrap h3,
.sd-pp .oos-notify-wrap h3 strong {
	font-family: 'DM Sans', sans-serif !important;
	font-size: 1rem !important;
	font-weight: 800 !important;
	letter-spacing: normal !important;
	text-transform: none !important;
	color: #fff !important;
	line-height: 1.3 !important;
}
.sd-pp .oos-notify-wrap input {
	background: rgba(255, 255, 255, .05) !important;
	background-color: rgba(255, 255, 255, .05) !important;
	border: 1px solid rgba(255, 255, 255, .16) !important;
	border-radius: 10px !important;
	color: #eef2f8 !important;
	font-family: 'DM Sans', sans-serif !important;
	font-size: .95rem !important;
	padding: 13px 14px !important;
}
.sd-pp .oos-notify-wrap input::placeholder { color: var(--ccr-text-dim) !important; }
.sd-pp .oos-notify-wrap input:focus {
	border-color: rgba(56, 174, 232, .65) !important;
	outline: none !important;
}
.sd-pp .oos-notify-wrap button {
	background: var(--ccr-accent) !important;
	background-color: var(--ccr-accent) !important;
	border: 0 !important;
	border-radius: 10px !important;
	color: #fff !important;
	font-family: 'DM Sans', sans-serif !important;
	font-size: .85rem !important;
	font-weight: 800 !important;
	letter-spacing: .1em !important;
	text-transform: uppercase !important;
	padding: 13px 24px !important;
	cursor: pointer;
	transition: all .2s ease !important;
}
.sd-pp .oos-notify-wrap button:hover,
.sd-pp .oos-notify-wrap button:focus,
.sd-pp .oos-notify-wrap button:active {
	background: var(--ccr-blue) !important;
	background-color: var(--ccr-blue) !important;
	border-radius: 10px !important;
	padding: 13px 24px !important;
	color: #fff !important;
	outline: none !important;
}
/* success/error copy the form swaps in after submit */
.sd-pp .oos-notify-wrap p,
.sd-pp .oos-notify-wrap span,
.sd-pp .oos-notify-wrap label {
	font-family: 'DM Sans', sans-serif !important;
	color: #dbe3f0 !important;
}

/* ---------- back-in-stock frame (backlog #66, 2026-09-23) ----------
   Omnisend mounts the embedded form ~2 s after load (their platform script polls once a second before the Store API
   stock check, then renders). The template prints a non-interactive frame right after the mount div: real h3 / input /
   button elements, so the rules above size them exactly like the live form (measured on prod: heading 21 px, field
   46 + 5, button 42 in 5/12 padding = 131 px; 32 px right inset from Omnisend's section + block padding; stacked at
   every width). Shown only while the mount div is :empty - the moment Omnisend inserts the form the frame is gone,
   same box, no shift. If Omnisend never mounts (blocked, no consent) the frame removes itself after 12 s rather than
   posing as a form. :empty needs the mount div printed with no whitespace inside (the template does). */
.sd-pp .oos-notify-wrap .sd-oos-frame {
	display: none;
	padding: 0 32px 12px 0; /* the live form's 12 px sits on its action block; padding keeps it inside this box */
	pointer-events: none;
	animation: sd-oos-frame-timeout 0s linear 12s forwards;
}
.sd-pp .oos-notify-wrap #omnisend-embedded-v2-6a03bf159a6498d620157d40:empty + .sd-oos-frame { display: block; }
.sd-pp .oos-notify-wrap .sd-oos-frame h3 { margin: 0; }
.sd-pp .oos-notify-wrap .sd-oos-frame input { display: block; width: 100%; box-sizing: border-box; margin: 0 0 10px; line-height: 1.2; } /* Omnisend: line-height 120%; 10 = its 5 + 5 container paddings (sibling margins would collapse) */
.sd-pp .oos-notify-wrap .sd-oos-frame button { display: block; width: 100%; margin: 0; line-height: 1.2; }
@keyframes sd-oos-frame-timeout { to { visibility: hidden; height: 0; margin: 0; padding: 0; overflow: hidden; } }

/* ---------- credova (ported from cc-credova-single-dark, main.css) ---------- */
.sd-pp #credova-button { margin: 2px 0 0 !important; display: block !important; }
.sd-pp #credova-button .crdv-button { background: transparent !important; border: none !important; box-shadow: none !important; padding: 0 !important; text-decoration: none !important; }
.sd-pp #credova-button, .sd-pp #credova-button * { color: #fff !important; }
.sd-pp #credova-button svg path { fill: #fff !important; }

/* ---------- blurb + notice ---------- */
.sd-pp__blurb {
	font-size: .82rem;
	line-height: 1.55;
	color: var(--ccr-text-dim);
	margin: 0;
}
/* link to the matching "cheapest <caliber> ammo" guide (2.43.0) */
.sd-pp__guide { margin: 10px 0 0; font-size: .82rem; line-height: 1.5; }
.sd-pp__guide a { color: var(--ccr-blue); text-decoration: none; }
.sd-pp__guide a::after { content: ' \2192'; }
.sd-pp__guide a:hover,
.sd-pp__guide a:focus-visible { text-decoration: underline; }
.sd-pp .bcm-product-tag-notice {
	font-size: .84rem;
	line-height: 1.55;
	color: rgba(255, 255, 255, .72);
	background: rgba(255, 255, 255, .03);
	border: 1px solid rgba(255, 255, 255, .08);
	border-left-width: 3px;
	border-radius: 0 10px 10px 0;
	padding: 10px 14px;
	margin: 0;
}
.sd-pp .bcm-in-store-notice { border-left-color: var(--ccr-blue); }
.sd-pp .bcm-online-only-notice { border-left-color: var(--ccr-accent); }

/* ---------- meta ledger ---------- */
.sd-pp__meta {
	margin: 2px 0 0;
	border-top: 1px solid rgba(255, 255, 255, .08);
	padding-top: 12px;
	display: flex;
	flex-direction: column;
	gap: 6px;
}
.sd-pp__meta-row {
	display: flex;
	gap: 12px;
	align-items: baseline;
}
.sd-pp__meta-row dt {
	font-family: 'DM Mono', monospace;
	font-size: .68rem;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--ccr-text-dim);
	min-width: 96px;
}
.sd-pp__meta-row dd {
	margin: 0;
	font-size: .84rem;
	color: #dbe3f0;
}
.sd-pp__meta-row dd a { color: #dbe3f0; text-decoration: none; transition: color .15s ease; }
.sd-pp__meta-row dd a:hover { color: var(--ccr-blue); }

/* ---------- shared kicker + full-width sections ---------- */
.sd-pp__kicker {
	display: block;
	font-family: 'DM Mono', monospace;
	font-size: 1rem;
	font-weight: 500;
	letter-spacing: .2em;
	text-transform: uppercase;
	color: var(--ccr-blue);
	margin-bottom: 16px;
}
.sd-pp__desc,
.sd-pp__attrs {
	background: rgba(255, 255, 255, .03);
	border: 1px solid rgba(255, 255, 255, .08);
	border-radius: 16px;
	padding: clamp(18px, 3vw, 28px);
	margin-top: 26px;
}

/* description: light touch only — distributor-fed HTML varies */
.sd-pp__desc-body {
	color: #dbe3f0;
	line-height: 1.7;
	font-size: .95rem;
	overflow-x: auto;
}
.sd-pp__desc-body p { line-height: 1.7; }
.sd-pp__desc-body h1, .sd-pp__desc-body h2, .sd-pp__desc-body h3,
.sd-pp__desc-body h4, .sd-pp__desc-body h5 { color: #fff; }
.sd-pp__desc-body a { color: var(--ccr-blue); }
.sd-pp__desc-body img { max-width: 100%; height: auto; }
.sd-pp__desc-body table { max-width: 100%; }
.sd-pp__desc-body ul, .sd-pp__desc-body ol { padding-left: 1.3em; }

/* attributes: the ledger table. The legacy main.css PRODUCT ATTRIBUTES TABLE
   block (L1343-1349, blue th / black-grey striped) paints bg+color+weight
   with !important — countered here with !important on ONLY those properties;
   the counters revert to plain declarations when that block moves to
   quarantine (batch 3, post prod replay). */
.sd-pp__attrs-body table.woocommerce-product-attributes,
.sd-pp__attrs-body table.shop_attributes {
	width: 100%;
	border-collapse: collapse;
	background: transparent;
	border: 0;
}
.sd-pp__attrs-body table.woocommerce-product-attributes tr:nth-child(odd) td,
.sd-pp__attrs-body table.shop_attributes tr:nth-child(odd) td { background-color: transparent; }
.sd-pp__attrs-body table.woocommerce-product-attributes tr:nth-child(even) td,
.sd-pp__attrs-body table.shop_attributes tr:nth-child(even) td { background-color: rgba(255, 255, 255, .02); }
.sd-pp__attrs-body table.woocommerce-product-attributes th,
.sd-pp__attrs-body table.woocommerce-product-attributes td,
.sd-pp__attrs-body table.shop_attributes th,
.sd-pp__attrs-body table.shop_attributes td {
	border: 0;
	border-bottom: 1px solid rgba(255, 255, 255, .06);
	padding: 9px 12px;
	background-image: none;
	text-align: left;
	vertical-align: middle;
}
.sd-pp__attrs-body table.woocommerce-product-attributes th,
.sd-pp__attrs-body table.shop_attributes th {
	font-family: 'DM Mono', monospace;
	font-size: .72rem;
	font-weight: 500;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--ccr-text-dim);
	background-color: transparent;
	width: 220px;
}
.sd-pp__attrs-body table.woocommerce-product-attributes td,
.sd-pp__attrs-body table.shop_attributes td {
	font-size: .88rem;
	color: #eef2f8;
	background-color: transparent;
}
.sd-pp__attrs-body table.woocommerce-product-attributes td p { margin: 0; color: inherit; }

/* ---------- related ---------- */
/* The legacy main.css body.single-product stock overrides (sentence case,
   .95rem, no bullet gap — L1287+) leak into the related TILES' stock lines
   on product pages; restore the tile voice. Counters die with batch 3. */
body.single-product .sd-pp__related .jet-listing-grid__item p.stock,
body.single-product .sd-pp__related .jet-listing-grid__item p.stock.in-stock,
body.single-product .sd-pp__related .jet-listing-grid__item p.stock.out-of-stock {
	font-family: 'DM Mono', monospace !important;
	font-size: .72rem !important;
	font-weight: 500 !important;
	letter-spacing: .08em !important;
	text-transform: uppercase !important;
	line-height: 1.5 !important;
}
body.single-product .sd-pp__related .jet-listing-grid__item p.stock.out-of-stock::before,
body.single-product .sd-pp__related .jet-listing-grid__item p.stock.in-stock::before {
	margin-right: .3em !important;
}
/* 2-col mobile grid: tile CTAs sized to fit the narrow tiles (VIEW PRODUCT
   was overflowing its button at the tile system's default padding) */
@media (max-width: 767px) {
	/* (0,5,0)+ — must out-rank the tile system's (0,4,0)!important ATC rule */
	.sd-pp__related .jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-jet-woo-builder-archive-add-to-cart .button,
	.sd-pp__related .jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .button {
		font-size: .68rem !important;
		padding: 9px 8px !important;
		letter-spacing: .04em !important;
		white-space: nowrap !important;
		max-width: 100%;
		overflow: hidden;
		text-overflow: ellipsis;
	}
	/* mobile density: one small uniform section inset for ALL tile cards */
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-section {
		padding-left: 12px !important;
		padding-right: 12px !important;
	}
	/* longest stock state ("ONLY 1 LEFT IN STOCK") must fit the narrow tiles */
	body.single-product .sd-pp__related .jet-listing-grid__item p.stock,
	body.single-product .sd-pp__related .jet-listing-grid__item p.stock.in-stock,
	body.single-product .sd-pp__related .jet-listing-grid__item p.stock.out-of-stock {
		font-size: .62rem !important;
		letter-spacing: .04em !important;
		white-space: nowrap !important;
	}
	/* 2-col grid: cross-card alignment matters again — restore the ledger
	   slots the 1-col mobile collapse zeroes (2- vs 3-line titles staggered
	   the chip/price/stock/CTA rows; Jake) and re-pin the CTA to the floor */
	.sd-pp__related .jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .bcm-loop-title-text { min-height: 3.96em; }
	.sd-pp__related .jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .bcm-loop-title-wrap { min-height: 1.5em; }
	.sd-pp__related .jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-jet-woo-builder-archive-product-price { min-height: 1.75em; }
	.sd-pp__related .jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-jet-woo-builder-archive-stock-status { min-height: 1.4em; }
	.sd-pp__related .jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-jet-woo-builder-archive-add-to-cart { margin-top: auto !important; padding-top: 10px; }
	/* wishlist circle at tile scale (the 38px compact sizing is desktop-only;
	   the template default is oversized for ~170px tiles) */
	.sd-pp__related .jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link,
	.sd-pp__related .jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-compare-button__link {
		width: 32px !important;
		height: 32px !important;
		display: inline-flex !important;
		align-items: center !important;
		justify-content: center !important;
	}
	.sd-pp__related .jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link svg,
	.sd-pp__related .jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-compare-button__link svg {
		width: 14px !important;
		height: 14px !important;
	}
}
.sd-pp__related { margin-top: 34px; }
.sd-pp h2.sd-pp__related-title {
	font-size: clamp(1.3rem, 2.6vw, 1.8rem);
	font-weight: 900;
	text-transform: uppercase;
	letter-spacing: .02em;
	color: #fff;
	margin: 0 0 18px;
}

/* ---------- mobile ---------- */
@media (max-width: 1024px) {
	.sd-pp__layout { grid-template-columns: 1fr; gap: 18px; }
	.sd-pp__panel { position: static; }
}
@media (max-width: 767px) {
	.sd-pp { padding: 14px 14px 40px; }
	.sd-pp__panel { padding: 18px; gap: 12px; }
	.sd-pp-gallery { padding: 10px; }
	.sd-pp-gallery__img,
	.sd-pp-gallery__zoom img { aspect-ratio: 16 / 10; }
	.sd-pp form.cart { gap: 8px; }
	.sd-pp__crumbs { margin-bottom: 12px; }
	.sd-pp__meta-row dt { min-width: 84px; }
	.sd-pp-gallery__lb-img { max-width: 96vw; max-height: 80vh; }
	.sd-pp-gallery__lb-prev { left: 8px; }
	.sd-pp-gallery__lb-next { right: 8px; }
	.sd-pp-gallery__lb-close { top: 10px; right: 10px; }
}

/* =============================================================================
   NATIVE GRID SHELL (sd-grid / sd-shop) — JWB rebuild arc 2026-08-14.
   Replaces JetEngine frontend.css's grid base (flex + --columns from the
   grid-col-* classes) for natively rendered tiles; the whole tile design
   system above keys off the same jet class contract and applies unchanged.
   Values match jet's: flex track, breakpoint column vars.
   ============================================================================= */
.sd-grid .jet-listing-grid__items {
	display: flex;
	flex-wrap: wrap;
}
@media (min-width: 1025px) {
	.sd-grid .grid-col-desk-4 { --columns: 4; }
	.sd-grid .grid-col-desk-5 { --columns: 5; }
	.sd-grid .grid-col-desk-6 { --columns: 6; }
}
@media (min-width: 768px) and (max-width: 1024px) {
	.sd-grid .grid-col-tablet-2 { --columns: 2 !important; }
	.sd-grid .grid-col-tablet-3 { --columns: 3 !important; }
}
@media (max-width: 767px) {
	.sd-grid .grid-col-mobile-1 { --columns: 1 !important; }
	.sd-grid .grid-col-mobile-2 { --columns: 2 !important; }
}

/* ---------- shop archive layout (replaces template 39372's arrangement) ---------- */
.sd-shop__head {
	max-width: 1440px;
	margin: 0 auto;
	padding: clamp(26px, 4vw, 44px) 20px 6px;
}
.sd-shop__title {
	font-size: clamp(1.6rem, 3vw, 2.2rem);
	font-weight: 900;
	text-transform: uppercase;
	letter-spacing: .02em;
	color: #fff;
	margin: 0;
}
.sd-shop__desc { color: var(--ccr-text-dim); font-size: .9rem; max-width: 860px; margin: 8px 0 0; }
/* ammo archives link their buying guides (2.43.0) */
.sd-shop__guides { margin: 10px 0 0; font-size: .84rem; color: var(--ccr-text-dim); }
.sd-shop__guides-label {
	font-family: 'DM Mono', monospace;
	font-size: .68rem;
	letter-spacing: .14em;
	text-transform: uppercase;
}
.sd-shop__guides a { color: var(--ccr-blue); text-decoration: none; }
.sd-shop__guides a:hover,
.sd-shop__guides a:focus-visible { text-decoration: underline; }
.sd-shop__guides-sep { opacity: .5; }
.sd-shop__wrap {
	display: grid;
	grid-template-columns: 330px minmax(0, 1fr);
	gap: 10px 28px;
	align-items: start;
	max-width: 1440px;
	margin: 0 auto;
	padding: 10px 20px 50px;
}
.sd-shop__toolbar { grid-column: 2; grid-row: 1; min-width: 0; }
.sd-shop__side { grid-column: 1; grid-row: 1 / span 3; min-width: 0; }
.sd-shop__main { grid-column: 2; grid-row: 2; min-width: 0; }
.sd-shop__pagination { grid-column: 2; grid-row: 3; }
.sd-shop__sortm { display: none; }
@media (max-width: 1024px) {
	/* single column, round-4 order: toolbar → filters → grid → pagination */
	.sd-shop__wrap { grid-template-columns: 1fr; }
	.sd-shop__toolbar, .sd-shop__side, .sd-shop__main, .sd-shop__pagination { grid-column: 1; grid-row: auto; }
	/* Sort after the filters (Jake 2026-09-28): on one column the sort sat above the search box and filters, so the
	   first control offered was reordering 84K products. Narrow first, then order the results: the toolbar
	   wrappers step aside (display: contents) so the title, sort and chips join this grid, and order puts the sort
	   between the filters and the grid, full width. Desktop (sort top-right beside the count) is untouched. */
	.sd-shop__toolbar,
	.sd-shop__toolbar .sd-shopt,
	.sd-shop__toolbar .sd-shopt__row { display: contents; }
	.sd-shop__toolbar .sd-shopt__title { order: 1; }
	.sd-shop__toolbar .sd-shopt__chips { order: 2; margin-top: 0; }
	.sd-shop__side { order: 3; }
	.sd-shop__toolbar .sd-shopt__sort { order: 4; }
	.sd-shop__main { order: 5; }
	.sd-shop__pagination { order: 6; }
	.sd-shop__toolbar .sd-shopt__sort select { display: block; width: 100%; }
	/* even spacing in the one-column stack (grid gap 10px): title/chips -> search 14px; search -> filters -> sort ->
	   grid 12px each. The filters form keeps an 18px margin for the old stack (filters -> grid); here the sort follows. */
	.sd-shop__side { margin-top: 4px; }
	.sd-shop__side .sd-shopf { margin-bottom: 2px; }
	.sd-shop__toolbar .sd-shopt__sort { margin-bottom: 2px; }
	/* Tab order follows the layout (2.45.63): the sort is also rendered after the filters (.sd-shop__sortm) and the
	   toolbar copy is display: none, so keyboard and screen-reader order match what is seen. The rules above still
	   place the toolbar copy for pages cached before the change, which have no .sd-shop__wrap--sortm. */
	.sd-shop__wrap--sortm .sd-shop__toolbar .sd-shopt__sort { display: none; }
	.sd-shop__sortm { display: block; order: 4; margin-bottom: 2px; min-width: 0; }
	.sd-shop__sortm select { display: block; width: 100%; }
}
.sd-shop__none { color: var(--ccr-text-dim); padding: 30px 0; }

/* badge paint: was jet-woo-builder widget CSS (dies at kill #7) — finalist owns it */
.sd-grid .jet-woo-product-badge,
.elementor-39820 .jet-woo-product-badge {
	display: inline-block;
	background: var(--ccr-blue) !important;
	/* a11y (backlog #17): #fff here was 2.05:1 — near-black passes 7.4:1 */
	color: #05070d !important;
	font-weight: 700;
	line-height: 1.2;
}

/* loop-button hover: the old class-agnostic blue hover was jet-woo-builder
   widget CSS — View Product / Select options buttons lack .add_to_cart_button
   so the global rule misses them. Cover every loop button variant. */
.jet-woo-builder-archive-add-to-cart a.button:hover,
.jet-woo-builder-archive-add-to-cart a.button:focus {
	background: var(--ccr-blue) !important;
	border-color: var(--ccr-blue) !important;
	color: #fff !important;
}

/* wishlist circle recolor (Jake 2026-08-14: keep design, change coloring):
   glass circle + hairline (back-to-top family), blue hover, accent added */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link {
	background: rgba(16, 26, 44, .55) !important;
	border: 1px solid rgba(255, 255, 255, .18) !important;
	color: #dbe3f0 !important;
	backdrop-filter: blur(4px);
	transition: border-color .18s ease, color .18s ease;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link:hover {
	border-color: var(--ccr-blue) !important;
	color: var(--ccr-blue) !important;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link:has(.jet-wishlist-button__state-added:not([style*="none"])) { color: #dbe3f0; }
.jet-wishlist-button__state-added .jet-cw-icon { color: var(--ccr-accent); }


/* wishlist recolor take 2: jet-cw paints the circle on the PLANE layer divs
   inside the link (absolute bg layers) — the 2.22.7 link paint sat underneath.
   Planes carry the glass look; link keeps the heart color/hover. */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__plane {
	background: rgba(16, 26, 44, .55) !important;
	border: 1px solid rgba(255, 255, 255, .18) !important;
	border-radius: 50% !important;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link:hover .jet-wishlist-button__plane {
	border-color: var(--ccr-blue) !important;
}

/* wishlist take 3 (Jake: no visible difference — the glass navy matched the
   old disc): WHITE circle + navy heart, unmistakably new. Hover = blue heart,
   added = red filled heart (rules above). */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__plane {
	background: #fff !important;
	border: 1px solid rgba(15, 23, 42, .14) !important;
	box-shadow: 0 2px 10px rgba(0, 0, 0, .28);
	color: #16233d !important;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link { color: #16233d !important; }
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link:hover { color: var(--ccr-blue) !important; }
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link:hover .jet-wishlist-button__plane { border-color: var(--ccr-blue) !important; }

/* wishlist take 4 (Jake: white was worse): the dark disc he liked, coloring
   change carried by the ACCENT-RED heart. Hover = blue heart + border.
   Added = filled red (existing rule). */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link,
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__plane {
	background: rgba(16, 26, 44, .82) !important;
	border: 1px solid rgba(255, 255, 255, .16) !important;
	box-shadow: none;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link { color: var(--ccr-accent) !important; }
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link:hover { color: var(--ccr-blue) !important; }

/* wishlist FINAL (Jake round): cyan heart at rest (joins badge/chip blue —
   red stays reserved for ATC), RED on hover (previews the saved state) and
   red-filled once added. */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link { color: var(--ccr-blue) !important; }
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link:hover { color: var(--ccr-accent) !important; }
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link:hover .jet-wishlist-button__plane { border-color: var(--ccr-accent) !important; }

/* wishlist FINAL-2 (Jake: double ring artifact + wants transparent bg):
   planes killed (they were the doubled outlines), bare heart — transparent,
   no border, drop-shadow for legibility on white photos. Cyan rest / red
   hover+added unchanged. */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__plane { display: none !important; }
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link {
	background: transparent !important;
	border: 0 !important;
	box-shadow: none !important;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link svg {
	width: 19px !important;
	height: 19px !important;
	filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .45));
}

/* wishlist FINAL-3 (Jake: keep the circle outline, transparent fill):
   ONE ring on the link (planes stay dead — they were the double ring),
   cyan ring+heart at rest, red ring+heart on hover, red filled when added. */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link {
	border: 1px solid rgba(56, 174, 232, .6) !important;
	border-radius: 50% !important;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link:hover {
	border-color: var(--ccr-accent) !important;
}
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__link svg {
	width: 17px !important;
	height: 17px !important;
}

/* heart outline-only at rest (a stack rule force-fills SVGs; CSS fill beats
   the fill="none" attribute) — added state stays filled */
.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .jet-wishlist-button__state-normal svg {
	fill: none !important;
	stroke: currentColor !important;
}

/* OOS stock dot: its rule family (main.css ~735) matches via the inner
   stock-status wrapper but was left out of the .3em spacing rule (line 680
   covers in-stock/backorder only) — dot hugged the text (Jake) */
.jet-woo-builder-archive-product-stock-status .stock.out-of-stock::before { margin-right: .3em !important; }

/* stock dot gap: the legacy .3em margin computes on the dot's 0.7em font
   (~2px — invisible, Jake). Fixed 6px, every state, tiles only. */
.sd-grid .jet-woo-builder-archive-product-stock-status .stock::before,
.cc-xsell .jet-woo-builder-archive-product-stock-status .stock::before { margin-right: 6px !important; }

/* ---------- native wishlist page (sd-wl) — last JWB consumer retired ---------- */
.sd-wl__hero { position: relative; text-align: center; padding: clamp(34px, 5vw, 58px) 20px 8px; }
.sd-wl__title {
	font-size: clamp(2rem, 4.2vw, 3.1rem);
	font-weight: 900;
	text-transform: uppercase;
	letter-spacing: .02em;
	color: #fff;
	margin: 0;
}
.sd-wl .jet-breadcrumbs__wrap { display: flex; justify-content: center; align-items: center; gap: 10px; }
.sd-wl .jet-breadcrumbs, .sd-wl .jet-breadcrumbs * {
	font-family: 'DM Mono', monospace; font-size: .74rem; letter-spacing: .14em;
	text-transform: uppercase; color: var(--ccr-text-dim);
}
.sd-wl .jet-breadcrumbs__item-sep::after { content: "/"; font-family: 'DM Mono', monospace; color: var(--ccr-text-dim); opacity: .6; }
.sd-wl__body { max-width: 1240px; margin: 0 auto; padding: 14px 20px 60px; }
.sd-wl__empty { text-align: center; color: var(--ccr-text-dim); font-size: 1.05rem; padding: 40px 0 10px; }
.sd-wl__return-row { text-align: center; margin: 26px 0 0; }

/* ═══════════════════════════════════════════════════════════════════════
   SALES-TAX MESSAGING (Jake 2026-08-16) — PDP note + cart/checkout savings
   row. Markup/logic in inc/tax-messaging.php; nothing here names a state or
   a rate, both come from WooCommerce's tax table at render time.
   ═══════════════════════════════════════════════════════════════════════ */

/* PDP: borrows the stock line's mono voice one step quieter, and carries the
   same ● the stock states use so the two read as one column of conditions.
   Blue, not a stock state colour — this is information, not an alert. */
body.single-product .sd-pp__taxfree {
	font-family: 'DM Mono', monospace;
	font-size: .78rem;
	font-weight: 500;
	letter-spacing: .1em;
	text-transform: uppercase;
	line-height: 1.5;
	/* margin ZERO, not the 5px this shipped with (Jake 2026-08-16: "the spacing
	   is just slightly greater between those two"). .sd-pp__panel is a flex
	   column with `gap: 14px`, so ANY margin here is additive on top of the gap
	   — the 5px made stock->note 19px against the 14px the chip/title/price/
	   stock run keeps. The gap alone owns the rhythm; leave this at 0. */
	margin: 0;
	color: var(--ccr-blue);
	-webkit-text-fill-color: var(--ccr-blue);
}
body.single-product .sd-pp__taxfree::before {
	content: none; /* dot dropped (backlog #68, Jake 2026-09-23): the tax note is information, not a stock state */
	font-size: .7em;
	vertical-align: .12em;
	line-height: 1;
	margin-right: .35em;
}

/* Cart + checkout savings row.
   NOTE: this row IS the tax line for non-collected destinations — Woo hides
   zero-value tax rows (woocommerce_cart_hide_zero_taxes defaults true), so
   without it the order shows no tax line at all and the saving is invisible.
   The fill colours below are declared on the SPANS, not inherited: the
   checkout's tfoot th/td rules set -webkit-text-fill-color !important, which
   inherits and beats `color` on descendants. Declaring directly on the span
   sidesteps that entirely — no specificity contest needed. */
.sd-taxfree__zero {
	display: block;
	font-family: 'DM Mono', monospace;
}
.sd-taxfree__note {
	display: block;
	margin-top: 5px;
	font-size: .76rem;
	line-height: 1.45;
	letter-spacing: 0;
	text-transform: none;
	font-family: inherit;
	white-space: normal;
	color: var(--ccr-blue);
	-webkit-text-fill-color: var(--ccr-blue);
}
.sd-taxfree__note strong,
.sd-taxfree__note strong *,
.sd-taxfree__note .woocommerce-Price-amount,
.sd-taxfree__note .woocommerce-Price-currencySymbol {
	font-weight: 800;
	color: var(--ccr-blue);
	-webkit-text-fill-color: var(--ccr-blue);
}
/* the row's own figure stays in the ledger's dim voice; only the saving is lit */
body.woocommerce-cart .cart_totals tr.sd-taxfree th,
body.woocommerce-checkout .woocommerce-checkout-review-order-table tfoot tr.sd-taxfree th {
	vertical-align: top;
}

/* Tax note is a LINK to /guides/no-sales-tax/ (2026-08-17). It renders blue only
   because -webkit-text-fill-color inherits from .sd-pp__taxfree — the link's own
   `color` computes to the global link pink rgb(204,51,102). Third time this trap
   has appeared in this codebase, so pin both properties here: the day someone
   removes a fill declaration, this stays blue instead of turning pink. */
body.single-product .sd-pp__taxfree a {
	color: var(--ccr-blue);
	-webkit-text-fill-color: var(--ccr-blue);
	text-decoration: none;
}
body.single-product .sd-pp__taxfree a:hover,
body.single-product .sd-pp__taxfree a:focus-visible {
	text-decoration: underline;
	text-underline-offset: .25em;
}

/* ============================================================
   TILE STOCK→BUTTON GAP (Jake, 2026-08-17): was 44px visual —
   16px in-widget slack + 20px template widget margin + 8px ATC
   padding-top. Tightened to ~22px. Desktop-only: mobile keeps
   the round-12 approved rhythm (title/ATC 10px, 8px gaps).
   ============================================================ */
@media (min-width: 768px) {
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-jet-woo-builder-archive-stock-status {
		margin-bottom: 6px !important;
	}
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-jet-woo-builder-archive-add-to-cart {
		padding-top: 0 !important;
	}
	/* Tag→price gap (same request, round 2): was 24px visual — the same 20px
	   template widget margin on the title+chip shortcode widget + 4px price
	   offsets. 8px margin lands it ~12px. */
	.jet-listing-grid__item:has(.jet-woo-builder-archive-add-to-cart) .elementor-widget-shortcode {
		margin-bottom: 8px !important;
	}
}

/* ============================================================
   CATEGORY LINK SURFACES (SEO orphan fix, 2026-08-18): the crawl
   found 197/224 categories with zero inbound links (sidebar filter
   = checkboxes, footer = 8 silos). Two surfaces fix it: subcategory
   chips on shop/category heads + the /categories/ index page.
   ============================================================ */
.sd-shop__subcats { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 2px; }
.sd-shop__subcats a,
.sd-cats__chips a {
	display: inline-flex;
	align-items: baseline;
	gap: 7px;
	padding: 7px 13px;
	border: 1px solid rgba(255, 255, 255, .14);
	border-radius: 999px;
	background: rgba(255, 255, 255, .03);
	color: #dbe3f0;
	font-family: 'DM Mono', monospace;
	font-size: .72rem;
	letter-spacing: .06em;
	text-transform: uppercase;
	text-decoration: none;
	transition: border-color .2s ease, color .2s ease;
}
.sd-shop__subcats a:hover,
.sd-cats__chips a:hover { border-color: var(--ccr-blue); color: var(--ccr-blue); }
.sd-shop__subcats a span,
.sd-cats__chips a span { color: var(--ccr-text-dim); font-size: .64rem; }

/* /categories/ index page */
.sd-cats__body { max-width: 1080px; margin: 0 auto; padding: 8px 24px 70px; }
.sd-cats__group { margin: 0 0 34px; }
.sd-cats__group h2 { margin: 0 0 12px; }
.sd-cats__group h2 a {
	color: #fff;
	font-size: 1.15rem;
	letter-spacing: .04em;
	text-transform: uppercase;
	text-decoration: none;
}
.sd-cats__group h2 a:hover { color: var(--ccr-blue); }
.sd-cats__group h2 a span { color: var(--ccr-text-dim); font-size: .8rem; font-family: 'DM Mono', monospace; }
.sd-cats__chips { display: flex; flex-wrap: wrap; gap: 8px; }
.sd-cats__chips--sub { width: 100%; padding: 2px 0 6px 22px; }
.sd-cats__chips--sub a { font-size: .66rem; padding: 5px 11px; border-color: rgba(255, 255, 255, .09); }

/* ---- PDP KICKER PARITY (2026-08-21) ----
   Jake: the blue "Description" / "Additional Information" kickers must match
   the description content's own h2s ("Key Specifications", "FAQ" — distributor
   HTML rendering at a fixed 32px). One shared clamp on BOTH sides so they stay
   equal at every viewport width and both shrink sanely on phones. */
.sd-pp__kicker,
.sd-pp__desc-body h1,
.sd-pp__desc-body h2 {
	font-size: clamp(1.4rem, 4.8vw, 2rem);
}

/* ---- CHECKOUT: SHIP-TO-DIFFERENT TOGGLE FOR NON-FFL CARTS (2026-08-25) ----
   Backlog #13. g-ffl-checkout prints an inline script on carts that need no
   FFL selector which UNCHECKS woo's "Ship to a different address?" box and
   blanks the shipping fields (vendor default = ship to billing). The inert-
   heading treatment above hides the checkbox + label for every cart, so
   customers could never re-open it. sd-checkout.php now classes the page
   .sd-co--via-dealer / .sd-co--ships-direct via g-ffl's own order_requires_ffl_selector()
   (+ its C&R cookie override). Non-FFL carts get the native toggle back,
   styled, beneath the SHIPPING DETAILS heading — closed by default (ship to
   billing), the customer opens it and woo reveals the fields. FFL carts keep
   the inert heading (g-ffl locks the box checked + fills the dealer premise).
   Doubled class on purpose: the inert rules above are (1,1,x).
   CLASS NAMES: never put the substring "ffl" in a checkout class -- the FFL
   notice rule at ~L2580 uses [class*="ffl"] p / div and would box every
   element inside it (2026-08-25 incident: sd-co--noffl did exactly that). */
.sd-co.sd-co--ships-direct #ship-to-different-address {
	pointer-events: auto;
}
.sd-co.sd-co--ships-direct #ship-to-different-address::before {
	display: block;
	margin-bottom: 12px;
}
/* ---------- billing opt-in checkbox rows (Jake, 2026-09-21, backlog #55) ----------
   "these aren't aligned to their checkboxes" + "I don't think they need to be fully
   uppercase". Rows: Omnisend "Email me with news and offers", Omnisend "Text me with
   offers", and Woo's "Create an account?" (guests only) -- identical markup, so all three
   take the same treatment or the block looks inconsistent.
   Measured on prod: the label was `display:inline` with a 23px line box while the box
   carried `margin-top:2px` + `vertical-align:middle` (the global rule at ~L2671), which put
   the box centre 2.6px BELOW the text centre. "Ship to a different address?" (offset 0)
   already uses flex + align-items:center -- this is that recipe, scoped to these rows.
   Sentence case: the global checkout label rule (~L2627) uppercases every label at
   .72rem/.1em/500; a sentence-length opt-in reads as shouting in that register, so these
   take the insurance row's sentence-case voice (.82rem / 400 / no tracking). Colour is
   left to the global muted value on purpose -- they are optional opt-ins.
   Needs !important + an id on every line to beat the global rules above; `:has()` is
   already relied on by those rules, so no new support assumption. Does NOT reach
   #ship-to-different-address (an h3, not a p.form-row) or the rail's insurance row.
   Descendant combinators, NOT child: Woo's checkbox field template puts a
   span.woocommerce-input-wrapper between the p.form-row and the label (the Omnisend
   rows), while the createaccount row has the label as a direct child -- a `>` here
   fixed one row and silently skipped the other two (caught by the live prototype). */
html body.woocommerce-checkout #customer_details p.form-row:has(input[type="checkbox"]) label {
	display: flex !important;
	align-items: center !important;
	/* gap 0, not 10px: the label holds THREE flex items -- box, text, Woo's <span class="optional"> --
	   and a flex gap landed between text and "(optional)" too ("offers   (optional)", seen on prod).
	   The box-to-text space is the input's margin-right below; the span gets a normal word space. */
	gap: 0 !important;
	line-height: 1.5 !important;
	font-size: .82rem !important;
	font-weight: 400 !important;
	text-transform: none !important;
	letter-spacing: 0 !important;
	cursor: pointer;
}
html body.woocommerce-checkout #customer_details p.form-row:has(input[type="checkbox"]) label input[type="checkbox"] {
	margin: 0 10px 0 0 !important;
	flex-shrink: 0 !important;
}
html body.woocommerce-checkout #customer_details p.form-row:has(input[type="checkbox"]) label .optional {
	margin-left: .3em; /* flex drops the inter-item whitespace; restore a word space before "(optional)" */
}

.sd-co.sd-co--ships-direct #ship-to-different-address label {
	display: flex;
	align-items: center;
	gap: 10px;
	cursor: pointer;
	/* type + box size come from the checkout's global !important label/checkbox
	   rules (same voice as "Create an account?") -- deliberately not fought. */
}
.sd-co.sd-co--ships-direct #ship-to-different-address input {
	display: inline-block;
	-webkit-appearance: auto;
	appearance: auto;
	margin: 0;
	accent-color: #0177E3;
	cursor: pointer;
}

/* ---- CHECKOUT: DEALER-FORCED SHIPPING (2026-08-25) ----
   inc/ffl-shipping.php collapses a firearm cart's rates to the one the selected
   FFL dictates; woo then prints a HIDDEN input + label instead of radios
   (cart-shipping.php: radios only for 2+ rates). This block (a) renders that
   single rate as a read-only line with the PHP-appended .sd-co-shipnote and
   (b) before a dealer exists hides the still-choosable radio list behind the
   instruction row the PHP emits right before it (adjacent sibling, no :has()).
   Scoped to .sd-co--via-dealer only; non-firearm carts never match.
   CLASS NAMES: no "ffl" substring anywhere here (see ~L2580 + backlog #13). */
.sd-co.sd-co--via-dealer tr.sd-co-shipstate--pending + tr.woocommerce-shipping-totals {
	display: none !important; /* radios stay in the DOM (checkout.js still posts them); the customer can't pick */
}
html body.woocommerce-checkout .sd-co.sd-co--via-dealer tr.sd-co-shipstate {
	display: grid !important;
	grid-template-columns: 1fr;
	padding: 11px 0 !important;
	border-bottom: 1px solid rgba(255, 255, 255, .07);
}
html body.woocommerce-checkout .sd-co.sd-co--via-dealer tr.sd-co-shipstate th,
html body.woocommerce-checkout .sd-co.sd-co--via-dealer tr.sd-co-shipstate td {
	border: 0 !important;
	padding: 2px 0 !important;
	text-align: left !important;
	width: 100% !important;
}
html body.woocommerce-checkout .sd-co.sd-co--via-dealer .sd-co-shipstate__msg {
	display: block; /* inherits the ledger td colour on purpose -- same 85% white as woo's own
	                   "Enter your address to view shipping options." line (Jake 2026-08-25:
	                   it is an instruction to act on; --co-text-muted is only 36% white).
	                   Weight dropped to regular (Jake: bold competed with the totals). */
	font-weight: 400 !important;
}
html body.woocommerce-checkout .sd-co.sd-co--via-dealer ul#shipping_method li:only-child label {
	cursor: default !important;
	margin: 0 !important;
}
html body.woocommerce-checkout .sd-co.sd-co--via-dealer ul#shipping_method .sd-co-shipnote {
	display: block;
	margin-top: 3px;
	font-size: .72rem !important;
	letter-spacing: .02em !important;
	text-transform: none !important;
	color: var(--co-text-muted) !important;
	-webkit-text-fill-color: var(--co-text-muted) !important;
}

/* ===== CHECKOUT: keep selectWoo's hidden native <select> hidden (2026-08-27) =====
   With more than one allowed country (US + territories since 2026-08-27) WooCommerce
   renders #billing_country / #shipping_country as real <select>s that selectWoo
   parks off-screen via .select2-hidden-accessible (1x1px, absolute, clipped). Our
   `body.woocommerce-checkout .form-row select { width:100% !important }` above
   out-ranks that (0,2,2 vs 0,1,0), so the invisible select became viewport-wide
   from x=355 and the page scrolled ~350px to the right into dead space (Jake).
   Confirmed as the winning declaration via the cascade probe before this fix. */
html body.woocommerce-checkout .form-row select.select2-hidden-accessible,
html body.woocommerce-checkout select.select2-hidden-accessible {
	width: 1px !important;
	height: 1px !important;
	min-width: 0 !important;
	position: absolute !important;
	overflow: hidden !important;
	clip: rect(0 0 0 0) !important;
	padding: 0 !important;
	border: 0 !important;
}

/* ---- PDP SECTION HEADINGS (2026-08-29) ----
   Jake: "Description" should match the description's own white content h2s
   ("Key Specifications", "FAQ" -- 82,798 products carry them from the feed),
   not the blue DM Mono kicker. "Description" and "Additional Information" are
   real <h2>s now (document outline) styled exactly like those content h2s:
   same size clamp as the KICKER PARITY block, weight 500, white, no transform.
   The kicker register stays for labels elsewhere (// CATALOG, // FILTERS). */
.sd-pp h2.sd-pp__sechead {
	display: block;
	font-family: inherit;
	font-size: clamp(1.4rem, 4.8vw, 2rem);
	font-weight: 500;
	line-height: 1.2;
	letter-spacing: normal;
	text-transform: none;
	color: #fff;
	margin: 0 0 16px;
}

/* ---- A11Y REMEDIATION (backlog #17, 2026-09-01) ----
   axe-core sweep fixes with no existing rule to extend. Woo's
   .show-password-input span renders under 24px on the my-account login
   (target-size); give it a real box. The checkout quiet-down rule (~L3056)
   gained body.woocommerce-account scope in the same pass. */
body.woocommerce-account .show-password-input {
	display: inline-flex !important;
	align-items: center !important;
	justify-content: center !important;
	min-width: 24px !important;
	min-height: 24px !important;
}

/* ---- AUTOFILL (2026-09-06) ----
   Checkout/account fields are glass over a dark ground; give main.css
   cc-global-autofill-fix v2 the matching solids (sampled from the rendered
   page: form rows ~#10131b, payment-box inputs ~#07101a, login ~#0b111e). */
body.woocommerce-checkout { --sd-autofill-bg: #10131b; }
body.woocommerce-checkout #payment { --sd-autofill-bg: #07101a; }
body.woocommerce-account { --sd-autofill-bg: #0b111e; }
