/* Building Block 1 — Master Shop Lander.
 * Product cards reuse the lander card styles (sale-products-styles-top.css,
 * packageSelectPopup.css). This file only adds the per-segment header theming
 * and minor filter-bar polish. */

.sbr-shop-wrap {
	--shop-header-bg: #3d3f40;
	--shop-accent: #5642bb;
	--shop-text: #ffffff;
	/* Lander typography: body/other text = Open Sans (headings opt into Montserrat
	   individually — card titles via each design's --*-disp var, page title below). */
	font-family: 'Open Sans', sans-serif;
}

.sbr-shop-header {
	background: var(--shop-header-bg);
	color: var(--shop-text);
	padding: 48px 0 32px;
	text-align: center;
}

.sbr-shop-header h1 {
	color: var(--shop-text);
	margin: 0 0 8px;
	font-family: 'Montserrat', sans-serif;
}

.sbr-shop-header .sbr-shop-sub {
	margin: 0 0 18px;
	opacity: 0.9;
}

.sbr-shop-header .sbr-shop-logo {
	max-height: 60px;
	width: auto;
	margin: 0 auto 16px;
	display: block;
}

/* Filter bar (Category / Product / Sort) sits in the branded header. */
.sbr-shop-filters {
	margin-top: 8px;
}

/* Active ?cat= filter notice. */
.sbr-shop-active-cat {
	padding: 16px 0 0;
	font-size: 15px;
}

.sbr-shop-active-cat a {
	color: var(--shop-accent);
	text-decoration: underline;
}

.sbr-shop-empty {
	text-align: center;
	padding: 60px 0;
}

/* Per-segment header banner (Shop Presentation). Also the swap target for the
 * category filter banner (Phase 4). */
.sbr-shop-banner {
	margin: 18px auto 0;
	max-width: 960px;
	text-align: center;
	background-color: var(--shop-banner-bg, transparent);
}

.sbr-shop-banner-img {
	max-width: 100%;
	height: auto;
	display: block;
	margin: 0 auto;
}

.sbr-shop-banner-text {
	margin-top: 10px;
	font-size: 16px;
	line-height: 1.5;
}

@media (max-width: 767px) {
	.sbr-shop-header {
		padding: 32px 0 24px;
	}
}
.wrapper.flex-wrapper .form-group-radio-custom {
    position: relative;
}

/* ---------------------------------------------------------------------------
 * Per-segment shop color override layer.
 *
 * These rules ONLY live in shop.css (loaded exclusively on /shop), so the
 * partner landers — which load the shared sale-products-styles-top.css /
 * packageSelectPopup.css but NOT this file — are completely unaffected.
 *
 * Each rule re-states the shared selector with one extra qualifier
 * (#newsalePage.sbr-shop-wrap) so it outranks the shared rule, and paints with
 * var(--token, <current default>). When the segment sets no override the token
 * is undefined and the fallback (the exact current color) is used, so the shop
 * looks identical to today. The wrapper's inline style sets the token per
 * segment (see sbr_shop_render_body()).
 * ------------------------------------------------------------------------- */

/* Action color — "X% OFF!" badge (.featureTag) + grid CTA buttons. */
#newsalePage.sbr-shop-wrap #product-list.productLandingPageContainer .medium-12 .featureTag,
#newsalePage.sbr-shop-wrap #product-list .landing-product:not(.medium-12) .featureTag {
	background: var(--shop-action, #9f1e82);
}

#newsalePage.sbr-shop-wrap .teethWhieteingSystemWrapper.productLandingPageContainer .product-selection-price-wrap button,
#newsalePage.sbr-shop-wrap .teethWhieteingSystemWrapper.productLandingPageContainer .product-selection-price-wrap a.product_type_composite,
#newsalePage.sbr-shop-wrap .teethWhieteingSystemWrapper.productLandingPageContainer .btn,
#newsalePage.sbr-shop-wrap #product-list .medium-12.thb-dark-column.small-12.landing-product .product-selection-description-parent-inner .btn-primary-blue {
	/* Default action color = design teal (was amber #f0c23a). Design-card CTAs
	   that carry .btn (quantity, night-guard) fall through to this rule, so an
	   amber default made them yellow while sibling cards showed teal. Segments
	   still override via --shop-action. */
	background-color: var(--shop-action, #1cb9bd);
}

/* Card background tint — full-width hero band + 2-/3-card info areas. */
#newsalePage.sbr-shop-wrap #product-list.productLandingPageContainer .medium-12.thb-dark-column.small-12.landing-product > .vc_column-inner {
	background: var(--shop-card-fill, #e8f8f8) !important;
}

#newsalePage.sbr-shop-wrap .teethWhieteingSystemWrapper.productLandingPageContainer .landing-product:not(.medium-12) .product-selection-description-parent,
#newsalePage.sbr-shop-wrap .packageQuantityBox,
#newsalePage.sbr-shop-wrap .selectPackageBox {
	background: var(--shop-card-fill, #e8f8f8);
}

#newsalePage.sbr-shop-wrap .teethWhieteingSystemWrapper.grid-changed .landing-product .product-selection-description-parent,
#newsalePage.sbr-shop-wrap #product-list.grid-changed .caripro-content-splitter,
#newsalePage.sbr-shop-wrap #product-list.grid-changed .sportGuardsProuductWrapper .caripro-content-splitter {
	background: var(--shop-card-fill, #e8f8f8);
}

/* Accent / border — package-popup featured card border.
 * (The popup stays inside .sbr-shop-wrap on open — confirmed it's a class
 * toggle, no move to <body> — so the inline var cascades into the popup.)
 * The divider lines (.sepratorLine) are inline-styled in the shared card
 * handler, so they reference the same var inline (each keeping its own
 * fallback) rather than being overridden here. */
#newsalePage.sbr-shop-wrap #product-list.productLandingPageContainer .package-product .stepQuantityOption .product-card.featured-product {
	border-color: var(--shop-action, #0eb4ba);
}

/* ── New JSON-driven design cards: exempt from the filter "uniform tiles" reflow ──
 * When any filter is active, lander-common.js adds .grid-changed to
 * #wrapper/#product-list, and custom-styles.css then forces EVERY .wpb_column
 * to 50% width to tile the stock cards (`.grid-changed .wpb_column { max-width:
 * 50% !important }`). The bespoke design cards (night-guard hero, quantity,
 * enamel — all marked .sbr-shop-design-col) must keep their own layout, so we
 * re-assert their Foundation column width here. Width is the only thing to
 * restore: every other .grid-changed rule targets .product-selection-* stock
 * internals these cards don't use. Default = full width; the medium-N overrides
 * keep any small/grid design card at its intended fraction. */
#newsalePage.sbr-shop-wrap #product-list.grid-changed .wpb_column.sbr-shop-design-col,
#newsalePage.sbr-shop-wrap #wrapper.grid-changed .wpb_column.sbr-shop-design-col {
	max-width: 100% !important;
	flex: 0 0 100% !important;
	width: 100% !important;
}
#newsalePage.sbr-shop-wrap #product-list.grid-changed .wpb_column.sbr-shop-design-col.medium-6,
#newsalePage.sbr-shop-wrap #wrapper.grid-changed .wpb_column.sbr-shop-design-col.medium-6 {
	max-width: 50% !important; flex: 0 0 50% !important; width: 50% !important;
}
#newsalePage.sbr-shop-wrap #product-list.grid-changed .wpb_column.sbr-shop-design-col.medium-4,
#newsalePage.sbr-shop-wrap #wrapper.grid-changed .wpb_column.sbr-shop-design-col.medium-4 {
	max-width: 33.333% !important; flex: 0 0 33.333% !important; width: 33.333% !important;
}
#newsalePage.sbr-shop-wrap #product-list.grid-changed .wpb_column.sbr-shop-design-col.medium-3,
#newsalePage.sbr-shop-wrap #wrapper.grid-changed .wpb_column.sbr-shop-design-col.medium-3 {
	max-width: 25% !important; flex: 0 0 25% !important; width: 25% !important;
}
/* ── Mobile: filtered design cards stack one-per-row (no 2-/3-/4-up tiles) ──────
 * The medium-6/4/3 width overrides above have no breakpoint, so under a filter
 * (.grid-changed) they force a grid/design card to a fraction of the row at EVERY
 * width — leaving cards 2-up on phones. Unfiltered, the same cards are single
 * column on mobile (their Foundation `small-12` beats `medium-6` below 40em), and
 * the storefront already collapses its own stock tiles to full width here
 * (media-query.css:4518 → `.grid-changed .wpb_column { max-width:100% }` inside
 * @media max-width:767px). Match that: at ≤767px re-collapse the design cards to
 * full width so the filtered flow shows one product after another, exactly like
 * the unfiltered flow. Same specificity as the medium-N rules above but later in
 * source, so it wins inside the query; desktop keeps its 2-/3-/4-up grid. */
@media (max-width: 767px) {
	#newsalePage.sbr-shop-wrap #product-list.grid-changed .wpb_column.sbr-shop-design-col.medium-6,
	#newsalePage.sbr-shop-wrap #wrapper.grid-changed .wpb_column.sbr-shop-design-col.medium-6,
	#newsalePage.sbr-shop-wrap #product-list.grid-changed .wpb_column.sbr-shop-design-col.medium-4,
	#newsalePage.sbr-shop-wrap #wrapper.grid-changed .wpb_column.sbr-shop-design-col.medium-4,
	#newsalePage.sbr-shop-wrap #product-list.grid-changed .wpb_column.sbr-shop-design-col.medium-3,
	#newsalePage.sbr-shop-wrap #wrapper.grid-changed .wpb_column.sbr-shop-design-col.medium-3 {
		max-width: 100% !important; flex: 0 0 100% !important; width: 100% !important;
	}
}

/* ── medium-12 design cards: card content = content-row width; band stays full-bleed
 * The storefront keeps a medium-12 card's .vc_column-inner full-bleed (100vw) AS A
 * BACKGROUND BAND and caps only the inner content (.product-selection-box) at
 * 1330px centered (sale-products-styles-top.css:3). So we must NOT touch the
 * .vc_column-inner width (that's the full-width colored band) — only cap the design
 * CARD content to the same 1330px, centered in the band. That matches the stock
 * medium-12 content width and lines the card up with the grid rows' card edges,
 * while the background band keeps spanning the full screen as before. (Supersedes
 * the per-design max-width:1180 caps, which stay in the files but are overridden.) */
#newsalePage.sbr-shop-wrap .sbr-shop-design-col.medium-12 > .vc_column-inner > .wpb_wrapper > .lander-shortcode,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col.medium-12 .sbr-ng-hero,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col.medium-12 .sbr-qty--wide,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col.medium-12 .sbr-spc--wide,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col.medium-12 .sbr-sp--wide {
	max-width: 1330px !important; margin-left: auto !important; margin-right: auto !important;
}

/* ── Night-guard: wrap the teal card surface, don't span full width ────────────
 * The other full-width designs strip their .vc_column-inner and cap the CARD to
 * 1330px centered (above). The night-guard's teal .vc_column-inner IS its card
 * surface and was given a VIEWPORT full-bleed (custom-styles.css:11706 →
 * width:100vw; left:calc(-50vw + 50%), only in the :not(.grid-changed) default
 * state), so it read as a full-width band behind the card. UNDO that full-bleed
 * (reset width + left) and cap it to 1330px centered so the teal wraps the card
 * like every other full-width card — and like the filtered (.grid-changed) state
 * already did. !important beats the (non-important) full-bleed & storefront rules.
 * Its 40px vertical padding + border-radius/shadow are kept, so it stays a card. */
#newsalePage.sbr-shop-wrap .sbr-ng-col.medium-12 > .vc_column-inner {
	width: 100% !important;
	left: 0 !important;
	max-width: 1330px !important;
	margin-left: auto !important;
	margin-right: auto !important;
}

/* ── Full-width (medium-12) product cards: uniform product-name size ──────────
 * On the medium breakpoint and up (matches .medium-12 = "12 md"), every full-width
 * design card's product name/title renders at a uniform 34px / weight 700 (they
 * previously varied: night-guard 50, enamel 44, subscription 40, the rest clamp→42).
 * Scoped to >= 640px so each design keeps its own smaller responsive sizes below
 * that (their overrides are all max-width: 940/900/880/480). Specificity (1,3,0)
 * outranks every design's base + wide title rule, so no !important is needed. Only
 * the medium-12 (wide) instances of quantity/simple-product/simple-package match;
 * their grid instances keep the compact 21px name. */
@media (min-width: 640px) {
	#newsalePage.sbr-shop-wrap .sbr-shop-design-col.medium-12 .sbr-ng-headline,
	#newsalePage.sbr-shop-wrap .sbr-shop-design-col.medium-12 .sbr-ea-title,
	#newsalePage.sbr-shop-wrap .sbr-shop-design-col.medium-12 .sbr-sub-title,
	#newsalePage.sbr-shop-wrap .sbr-shop-design-col.medium-12 .sbr-spg-title,
	#newsalePage.sbr-shop-wrap .sbr-shop-design-col.medium-12 .sbr-pc-title,
	#newsalePage.sbr-shop-wrap .sbr-shop-design-col.medium-12 .sbr-qty-name,
	#newsalePage.sbr-shop-wrap .sbr-shop-design-col.medium-12 .sbr-spc-name,
	#newsalePage.sbr-shop-wrap .sbr-shop-design-col.medium-12 .sbr-sp-name {
		font-size: 34px;
		font-weight: 700;
	}
}

/* ── Currency symbol on main prices: small but ON THE BASELINE ─────────────────
 * Every main (non-strikethrough) price wraps its "$" as <sup class="sbr-cur">$</sup>
 * (inc/shop-card-designs.php), so it inherits each design's cents-sup FONT-SIZE.
 * But the user wants the $ level with the price digits, not raised — so cancel
 * only the vertical lift (UA/normalize sup = vertical-align:super or
 * position:relative+top offset; some design rules add their own). Cents sups keep
 * their raise. Specificity (1,2,1) beats every `.sbr-X-price__now sup` (0,1,1).
 * Same leveling for the enamel/subscription plan-row $ (.dollerSymbal spans). */
#newsalePage.sbr-shop-wrap sup.sbr-cur {
	vertical-align: baseline;
	position: static;
	top: auto;
}
#newsalePage.sbr-shop-wrap .sbr-ea-plan__now .dollerSymbal,
#newsalePage.sbr-shop-wrap .sbr-sub-plan__now .dollerSymbal {
	vertical-align: baseline;
}

/* ── Cents sit at the BOTTOM of the whole number, not lifted on top ────────────
 * The "big integer + small cents" price format (format_price_with_sup() emits
 * `39<sup>45</sup>`; the sports-guard level tile builds the same markup by hand)
 * raises the cents <sup> with vertical-align:super (or, for the level tile, a UA
 * super + a stray top). Drop the cents to the baseline so the fractional part
 * aligns to the BOTTOM of the integer part instead of floating on top. Only the
 * vertical anchor moves — font-size stays per design (each sets its own cents
 * size). Scoped to these "now / from / bigprice" price contexts so every OTHER
 * price (strikethrough __was, plan rows, cart totals) is left untouched; the $
 * (sup.sbr-cur, above) is already on the baseline, so $ and cents now match.
 * Specificity (1,2,1) beats each design's `.sbr-X…sup` (0,1,1) and the UA
 * `sup{vertical-align:super}`; top:auto neutralises the level tile's lift. */
#newsalePage.sbr-shop-wrap .sbr-ng-price__now sup,
#newsalePage.sbr-shop-wrap .sbr-ng-reco__now sup,
#newsalePage.sbr-shop-wrap .sbr-qty-price__now sup,
#newsalePage.sbr-shop-wrap .sbr-ea-price__now sup,
#newsalePage.sbr-shop-wrap .sbr-sub-price__now sup,
#newsalePage.sbr-shop-wrap .sbr-sp-vprice__now sup,
#newsalePage.sbr-shop-wrap .sbr-sp-from__price sup,
#newsalePage.sbr-shop-wrap .sbr-spc-price__now sup,
#newsalePage.sbr-shop-wrap .sbr-pc-price__now sup,
#newsalePage.sbr-shop-wrap .sbr-pc-from__price sup,
#newsalePage.sbr-shop-wrap .sbr-spg-bigprice__now sup,
#newsalePage.sbr-shop-wrap .sbr-spg-pkg__now sup,
#newsalePage.sbr-shop-wrap .sbr-spg-level__now sup {
	vertical-align: baseline;
	top: auto;
	position: static;
}

/* ── Cents: bold (700) + a single (non-breaking) space before them ─────────────
 * Same "big integer + small cents" price format as above. Done in CSS, not markup,
 * on purpose: format_price_with_sup() is shared by 60+ single-product templates
 * that must NOT change, and the popups re-render their price in JS
 * (shop-night-guard/enamel/subscription rebuild `INT<sup>CENTS</sup>` on every
 * thickness/plan change) — anything injected into the markup would be wiped on
 * interaction. Keying off the bare cents <sup> survives that re-render.
 * `:not(.sbr-cur)` isolates the cents from the $. `content:"\00A0"` is the html
 * (non-breaking) space, rendered before the cents. */
#newsalePage.sbr-shop-wrap .sbr-ng-price__now sup:not(.sbr-cur),
#newsalePage.sbr-shop-wrap .sbr-ng-reco__now sup:not(.sbr-cur),
#newsalePage.sbr-shop-wrap .sbr-qty-price__now sup:not(.sbr-cur),
#newsalePage.sbr-shop-wrap .sbr-ea-price__now sup:not(.sbr-cur),
#newsalePage.sbr-shop-wrap .sbr-sub-price__now sup:not(.sbr-cur),
#newsalePage.sbr-shop-wrap .sbr-sp-vprice__now sup:not(.sbr-cur),
#newsalePage.sbr-shop-wrap .sbr-sp-from__price sup:not(.sbr-cur),
#newsalePage.sbr-shop-wrap .sbr-spc-price__now sup:not(.sbr-cur),
#newsalePage.sbr-shop-wrap .sbr-pc-price__now sup:not(.sbr-cur),
#newsalePage.sbr-shop-wrap .sbr-pc-from__price sup:not(.sbr-cur),
#newsalePage.sbr-shop-wrap .sbr-spg-bigprice__now sup:not(.sbr-cur),
#newsalePage.sbr-shop-wrap .sbr-spg-pkg__now sup:not(.sbr-cur),
#newsalePage.sbr-shop-wrap .sbr-spg-level__now sup:not(.sbr-cur) {
	font-weight: 700;
}
#newsalePage.sbr-shop-wrap .sbr-ng-price__now sup:not(.sbr-cur)::before,
#newsalePage.sbr-shop-wrap .sbr-ng-reco__now sup:not(.sbr-cur)::before,
#newsalePage.sbr-shop-wrap .sbr-qty-price__now sup:not(.sbr-cur)::before,
#newsalePage.sbr-shop-wrap .sbr-ea-price__now sup:not(.sbr-cur)::before,
#newsalePage.sbr-shop-wrap .sbr-sub-price__now sup:not(.sbr-cur)::before,
#newsalePage.sbr-shop-wrap .sbr-sp-vprice__now sup:not(.sbr-cur)::before,
#newsalePage.sbr-shop-wrap .sbr-sp-from__price sup:not(.sbr-cur)::before,
#newsalePage.sbr-shop-wrap .sbr-spc-price__now sup:not(.sbr-cur)::before,
#newsalePage.sbr-shop-wrap .sbr-pc-price__now sup:not(.sbr-cur)::before,
#newsalePage.sbr-shop-wrap .sbr-pc-from__price sup:not(.sbr-cur)::before,
#newsalePage.sbr-shop-wrap .sbr-spg-bigprice__now sup:not(.sbr-cur)::before,
#newsalePage.sbr-shop-wrap .sbr-spg-pkg__now sup:not(.sbr-cur)::before,
#newsalePage.sbr-shop-wrap .sbr-spg-level__now sup:not(.sbr-cur)::before {
	content: "\00A0";
}

/* ── Uniform Add to Cart / CTA buttons across every design ────────────────────
 * The primary CTAs (Add to Cart, Choose your package, Customize) were rendering
 * at different heights (38px where the storefront .btn padding leaked through, up
 * to 58px on the designed CTAs), different radii (8–14px), and the quantity Add
 * was capped at 325px by the storefront .btn max-width. Normalize them all to one
 * size: 54px tall, full-width of their card, 14px radius, 16px text — so every
 * Add to Cart button is the same height and width treatment. (Colors/gradients
 * stay per-design; only geometry is unified. Secondary Buy-Now buttons excluded —
 * EXCEPT the night-guard popup's .sbr-ng-buynow: client feedback wants that pair
 * dimension-identical, like the button pair on /product/night-guards.) */
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-qty-add,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-spc-add,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-sp-add,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-sp-choose,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-spg-add,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-spg-customize,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-pc-add,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-pc-choose,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-ng-add,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-ng-buynow,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-ng-choose,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-sub-cta,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-ea-cta {
	box-sizing: border-box !important;
	display: flex !important; align-items: center !important; justify-content: center !important; gap: 9px !important;
	width: 100% !important; max-width: 100% !important;
	min-height: 54px !important; height: auto !important;
	padding: 8px 22px !important; margin-left: 0 !important; margin-right: 0 !important;
	border-radius: 14px !important;
	font-size: 16px !important; line-height: 1.1 !important; white-space: nowrap !important;
}
/* keep the inner label/total text from re-introducing size differences */
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-qty-add span,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-spc-add span,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-sp-add span,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-spg-add span,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-pc-add span,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-ng-add span,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-sub-cta span,
#newsalePage.sbr-shop-wrap .sbr-shop-design-col .sbr-ea-cta span {
	font-size: 16px !important; line-height: 1.1 !important;
}

/* ── Equal-height cards within a row ──────────────────────────────────────────
 * The shop's row container (.rdhtabs) is display:flex; flex-wrap:wrap, so the
 * columns already stretch to the tallest in their row. But the design card inside
 * (.sbr-sp/-spc/-qty-card — flex-column with height:100% + a margin-top:auto CTA)
 * only reaches its NATURAL height because the wrapper chain
 * (.vc_column-inner → .wpb_wrapper → .lander-shortcode) doesn't pass the column's
 * stretched height down. Make that chain fill so a grid card fills its column and
 * row-mates end up equal height (image+content top, CTA pinned to the bottom).
 * Scoped to grid-cell columns (medium-6/4/3) only — the full-width medium-12
 * cards are always solo in their row, so they're left untouched. */
#newsalePage.sbr-shop-wrap .sbr-sp-col.medium-6, #newsalePage.sbr-shop-wrap .sbr-sp-col.medium-4, #newsalePage.sbr-shop-wrap .sbr-sp-col.medium-3,
#newsalePage.sbr-shop-wrap .sbr-spc-col.medium-6, #newsalePage.sbr-shop-wrap .sbr-spc-col.medium-4, #newsalePage.sbr-shop-wrap .sbr-spc-col.medium-3,
#newsalePage.sbr-shop-wrap .sbr-qty-col.medium-6, #newsalePage.sbr-shop-wrap .sbr-qty-col.medium-4, #newsalePage.sbr-shop-wrap .sbr-qty-col.medium-3 {
	display: flex; flex-direction: column;
}
#newsalePage.sbr-shop-wrap .sbr-sp-col.medium-6 > .vc_column-inner, #newsalePage.sbr-shop-wrap .sbr-sp-col.medium-4 > .vc_column-inner, #newsalePage.sbr-shop-wrap .sbr-sp-col.medium-3 > .vc_column-inner,
#newsalePage.sbr-shop-wrap .sbr-spc-col.medium-6 > .vc_column-inner, #newsalePage.sbr-shop-wrap .sbr-spc-col.medium-4 > .vc_column-inner, #newsalePage.sbr-shop-wrap .sbr-spc-col.medium-3 > .vc_column-inner,
#newsalePage.sbr-shop-wrap .sbr-qty-col.medium-6 > .vc_column-inner, #newsalePage.sbr-shop-wrap .sbr-qty-col.medium-4 > .vc_column-inner, #newsalePage.sbr-shop-wrap .sbr-qty-col.medium-3 > .vc_column-inner {
	display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; width: 100%;
}
#newsalePage.sbr-shop-wrap .sbr-sp-col.medium-6 .wpb_wrapper, #newsalePage.sbr-shop-wrap .sbr-sp-col.medium-4 .wpb_wrapper, #newsalePage.sbr-shop-wrap .sbr-sp-col.medium-3 .wpb_wrapper,
#newsalePage.sbr-shop-wrap .sbr-spc-col.medium-6 .wpb_wrapper, #newsalePage.sbr-shop-wrap .sbr-spc-col.medium-4 .wpb_wrapper, #newsalePage.sbr-shop-wrap .sbr-spc-col.medium-3 .wpb_wrapper,
#newsalePage.sbr-shop-wrap .sbr-qty-col.medium-6 .wpb_wrapper, #newsalePage.sbr-shop-wrap .sbr-qty-col.medium-4 .wpb_wrapper, #newsalePage.sbr-shop-wrap .sbr-qty-col.medium-3 .wpb_wrapper,
#newsalePage.sbr-shop-wrap .sbr-sp-col.medium-6 > .vc_column-inner > .wpb_wrapper > .lander-shortcode, #newsalePage.sbr-shop-wrap .sbr-sp-col.medium-4 > .vc_column-inner > .wpb_wrapper > .lander-shortcode, #newsalePage.sbr-shop-wrap .sbr-sp-col.medium-3 > .vc_column-inner > .wpb_wrapper > .lander-shortcode,
#newsalePage.sbr-shop-wrap .sbr-spc-col.medium-6 > .vc_column-inner > .wpb_wrapper > .lander-shortcode, #newsalePage.sbr-shop-wrap .sbr-spc-col.medium-4 > .vc_column-inner > .wpb_wrapper > .lander-shortcode, #newsalePage.sbr-shop-wrap .sbr-spc-col.medium-3 > .vc_column-inner > .wpb_wrapper > .lander-shortcode,
#newsalePage.sbr-shop-wrap .sbr-qty-col.medium-6 > .vc_column-inner > .wpb_wrapper > .lander-shortcode, #newsalePage.sbr-shop-wrap .sbr-qty-col.medium-4 > .vc_column-inner > .wpb_wrapper > .lander-shortcode, #newsalePage.sbr-shop-wrap .sbr-qty-col.medium-3 > .vc_column-inner > .wpb_wrapper > .lander-shortcode {
	display: flex; flex-direction: column; flex: 1 1 auto; width: 100%;
}
/* ── Uniform vertical spacing between card rows (all viewports) ────────────────
   The storefront gives full-width (medium-12) cards margin-bottom:1px so adjacent
   full-width cards nearly touch, while grid cards that follow a full-width card
   get margin:1.5rem 0 (~48px between rows) — so the vertical gaps between card
   rows come out unequal on desktop. Every product column (design cards AND any
   stock fallback card) carries .landing-product; force ONE uniform gap on all of
   them, at a specificity (2 ids + 2 classes) that outranks the storefront margin
   rules in sale-products-styles-top.css (incl. the `.medium-12 ~ .medium-6`
   sibling rule) in both the default and .grid-changed (filtered) states.
   Per-column margin-bottom + zeroed margin-top yields an even gap whether a row
   holds one full-width card or a 2-/3-up grid (the .rdhtabs row is flex-wrap, so
   row-mates are equal height and their bottoms align). 24px keeps the mobile
   rhythm this rule previously applied only below 639px. */
#newsalePage.sbr-shop-wrap #product-list .landing-product {
	margin-top: 0 !important;
	margin-bottom: 24px !important;
}

/* ── Strip the teal #e8f8f8 column surface from full-width design cards ─────────
   sale-products-styles-top.css:64 paints #e8f8f8 on full-width columns'
   .vc_column-inner at a HIGHER specificity than each card's own strip, so its SQUARE
   corners poke out behind the cards' rounded corners (reads as "corners not rounded",
   especially on enamel where the tints match). Re-strip at matching specificity for
   every custom full-width design card EXCEPT night-guard, whose teal surface IS its
   card (that one is rounded + clipped in shop-night-guard.css instead). */
#newsalePage #product-list.productLandingPageContainer .sbr-shop-design-col:not(.sbr-ng-col).medium-12.thb-dark-column.small-12.landing-product > .vc_column-inner {
	background: transparent !important;
	background-color: transparent !important;
}

/* ── Tablet-portrait only: zero the storefront's medium-12 column padding ────────
   sale-products-styles-top.css:424 adds padding:10px 0 to every medium-12
   .vc_column-inner, but ONLY inside @media (max-width:1024px)+(min-width:768px)+
   (orientation:portrait). Enamel/subscription strip it with #newsalePage … !important
   (wins); package-compare, sports-guard and the wide simple-* cards strip only at
   (0,2,0), so it survives there — 10px of transparent space above/below their
   (transparent) column makes them sit farther from neighbors than the rest on
   tablet-portrait. Zero it for every full-width design card so gaps stay uniform at
   that breakpoint too. NOTE: this has no effect on DESKTOP (that padding rule is not
   in scope there) — desktop inter-card spacing is handled entirely by the 24px
   margin rule above. Night-guard is excluded (its .vc_column-inner IS the visible
   band, so its padding is internal to the card, not a gap). */
#newsalePage.sbr-shop-wrap #product-list .sbr-shop-design-col:not(.sbr-ng-col).medium-12 > .vc_column-inner {
	padding-top: 0 !important;
	padding-bottom: 0 !important;
}

/* ============================================================================
 * Dynamic segment tagline — the "Ruled label" tagline style
 * (Design → Simple Product Card). Shared by every shop card design so the
 * Smart Sales per-segment tagline renders consistently: a thin accent bar +
 * the tagline text. Accent defaults to the per-segment --shop-card-accent and
 * is overridable per card via an inline --sbr-tl-accent. Hidden entirely when
 * there is no tagline (the renderer emits nothing).
 * ========================================================================== */
.sbr-shop-tagline {
	display: flex;
	align-items: stretch;
	gap: 10px;
	align-self: flex-start;
	max-width: 100%;
	margin: 12px 0;
	font-family: 'Open Sans', sans-serif;
	text-align: left;
}
.sbr-shop-tagline__bar {
	flex: 0 0 auto;
	width: 3px;
	border-radius: 3px;
	background: var(--sbr-tl-accent, var(--shop-card-accent, #0e9aa6));
}
.sbr-shop-tagline__body {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
}
/* Static caps eyebrow ("MEMBER PRICE") — carries the accent. */
.sbr-shop-tagline__eyebrow {
	font-weight: 800;
	font-size: 10px;
	line-height: 1.2;
	letter-spacing: .9px;
	text-transform: uppercase;
	color: var(--sbr-tl-accent, var(--shop-card-accent, #0e9aa6));
}
/* Dynamic tagline copy — dark, always-readable ink (some segment accents are
   light, e.g. Guardian green, and fail contrast as text). */
.sbr-shop-tagline__text {
	font-weight: 600;
	font-size: 12.5px;
	line-height: 1.35;
	letter-spacing: .1px;
	color: #3f4d4c;
}
@media (max-width: 860px) {
	.sbr-shop-tagline { gap: 8px; margin: 10px 0; }
	.sbr-shop-tagline__eyebrow { font-size: 9.5px; }
	.sbr-shop-tagline__text { font-size: 11.5px; }
}
/* Price + tagline on one row: the ruled label sits parallel to the price, and
   drops to its own line below the price only when there isn't room (narrow /
   grid cards). Wrap the price element + the ruled label in .sbr-shop-priceline.
   The price keeps its natural size; the tagline takes the remaining space and
   wraps under once less than its min-width is left beside the price. */
.sbr-shop-priceline {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 4px 18px;
	width: 100%;
}
.sbr-shop-priceline > :first-child { flex: 0 0 auto; margin-top: 0; margin-bottom: 0; }
.sbr-shop-priceline > .sbr-shop-tagline {
	margin: 0;
	/* Fixed basis (not auto) so the flex line-break test uses ~200px, not the
	   tagline's wide content size — otherwise it wraps below even when it fits. */
	flex: 1 1 200px;
	min-width: 200px;
	/* Center against the price row (override the base flex-start, which would pin
	   the label to the top of the taller price box and read as misaligned). When
	   the label wraps to its own line below, this has no visible effect. */
	align-self: center;
}
@media (max-width: 860px) {
	.sbr-shop-priceline { gap: 6px 14px; }
	.sbr-shop-priceline > .sbr-shop-tagline { flex-basis: 170px; min-width: 170px; }
}
/* Point the tagline accent at each card family's own accent var (which itself
   resolves to the per-segment --shop-card-accent), so the ruled label stays
   cohesive with the card it sits in without any per-call PHP wiring. */
.sbr-ng  .sbr-shop-tagline { --sbr-tl-accent: var(--shop-card-accent, var(--ng-accent)); }
.sbr-qty .sbr-shop-tagline { --sbr-tl-accent: var(--qt-accent); }
.sbr-ea  .sbr-shop-tagline { --sbr-tl-accent: var(--ea-teal); }
.sbr-sp  .sbr-shop-tagline { --sbr-tl-accent: var(--sp-accent); }
.sbr-spc .sbr-shop-tagline { --sbr-tl-accent: var(--spc-accent); }
.sbr-pc  .sbr-shop-tagline { --sbr-tl-accent: var(--pc-accent); }
.sbr-spg .sbr-shop-tagline { --sbr-tl-accent: var(--spg-accent); }
.sbr-sub .sbr-shop-tagline { --sbr-tl-accent: var(--sub-accent); }

/* ==========================================================================
 * "View product" pill — frosted glass, bottom-right of a card's image stage
 * Emitted by sbr_shop_d_view_pill() (PHP) and src/shop/cards/ViewPill.jsx
 * (React); the two are diffed by verify-shop-react-vmdiff.js, which is why the
 * arrow lives here as a ::after instead of in either renderer's markup.
 *
 * Frosted glass rather than a brand-teal fill: this is a secondary utility
 * control, and a teal surface would read as a second CTA competing with Add to
 * Cart. Bottom-right is the one corner no ribbon (top-left), discount badge, or
 * "N SIZES" pill (top-right) occupies. Every stage hosting it is position:relative.
 *
 * The tint is TOKENISED because the pill routinely sits on product photography,
 * not just on the pastel stage gradient: at mobile widths it overlaps artwork on
 * every design. The base rule is a near-opaque surface with NO blur; the
 * @supports block drops the tint and adds the blur. That order matters — a 50%
 * white pane with no backdrop-filter over a black toothbrush is unreadable, so
 * engines without backdrop-filter must never see the glass values.
 *
 * Ink is #0b1f24 (a near-black teal-slate) rather than a mid grey: that is what
 * buys the contrast margin over dark artwork. Do not lighten it.
 * ========================================================================== */
.sbr-shop-vp {
	/* Body tint (2 stops) + sheen, and their hover twins. These base values are
	   the no-blur fallback surface — effectively opaque. */
	--vp-body-1: rgba(251, 255, 255, .96);
	--vp-body-2: rgba(255, 255, 255, .97);
	--vp-body-1h: rgba(253, 255, 255, .98);
	--vp-body-2h: rgba(255, 255, 255, .99);
	--vp-sheen: rgba(255, 255, 255, .55);
	--vp-sheen-stop: 45%;
	--vp-ink: #0b1f24;

	position: absolute;
	right: 12px;
	bottom: 12px;
	/* Above .sbr-*-stage__img, which is inset:0 absolute and would otherwise
	   swallow the pointer, and level with the ribbon's z-index: 4. */
	z-index: 5;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	min-height: 36px;
	padding: 0 14px;
	box-sizing: border-box;
	/* Edges are drawn as inset shadows below, not as a border. */
	border: 0;
	border-radius: 999px;
	font-family: 'Open Sans', sans-serif;
	font-weight: 600;
	font-size: 12px;
	line-height: 1;
	letter-spacing: .02em;
	white-space: nowrap;
	color: var(--vp-ink);
	text-decoration: none;
	/* Specular sheen over the pane body. The sheen dies at ~42% height so the
	   pill reads as a curved pane catching light rather than a flat wash. */
	background-color: transparent;
	background-image:
		linear-gradient(180deg, var(--vp-sheen) 0%, rgba(255, 255, 255, 0) var(--vp-sheen-stop)),
		linear-gradient(160deg, var(--vp-body-1) 0%, var(--vp-body-2) 100%);
	background-repeat: no-repeat;
	/* Lit top edge, shaded bottom edge, hairline ring, inner floor shade, then
	   two outer shadows for lift. The 1px edges come first so they paint above
	   the ring. Together these are what give the pane apparent thickness. */
	box-shadow:
		inset 0 1px 0 rgba(255, 255, 255, .9),
		inset 0 -1px 0 rgba(11, 31, 36, .1),
		inset 0 0 0 1px rgba(255, 255, 255, .38),
		inset 0 -6px 12px -8px rgba(11, 31, 36, .1),
		0 1px 2px rgba(11, 40, 44, .1),
		0 6px 16px -6px rgba(11, 40, 44, .2);
	/* Never transition backdrop-filter — it re-rasterises the blur every frame. */
	transition: background-image .18s ease, box-shadow .18s ease;
}
/* The actual glass. Tint drops to .66 -> .50 so the 14px blur is plainly doing
   work: the pastel diagonal shifts hue across the pill and photo edges smear
   behind it. saturate() makes the transmitted tint read more chromatic than the
   stage, which is the cue that sells it as glass rather than as translucency. */
@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
	.sbr-shop-vp {
		--vp-body-1: rgba(244, 254, 255, .66);
		--vp-body-2: rgba(255, 255, 255, .5);
		--vp-body-1h: rgba(244, 254, 255, .76);
		--vp-body-2h: rgba(255, 255, 255, .6);
		--vp-sheen: rgba(255, 255, 255, .14);
		--vp-sheen-stop: 42%;
		-webkit-backdrop-filter: blur(14px) saturate(170%);
		backdrop-filter: blur(14px) saturate(170%);
	}
}
/* The chevron: presentation only, so it stays out of both renderers' markup and
   out of the accessible name (the anchor carries an aria-label). The teal is
   decorative here, and at glass density it cannot hold 3:1 against dark
   artwork on its own — the white halo is what keeps it separated.
   Sized up to 15px and bolded because U+203A draws lighter and smaller than the
   surrounding 12px label when set at a matched size. */
.sbr-shop-vp::after {
	content: '\203A';
	font-size: 15px;
	font-weight: 700;
	line-height: 1;
	color: #0e8a96;
	transform: translateY(-.5px);
	text-shadow: 0 0 2px rgba(255, 255, 255, .95), 0 0 4px rgba(255, 255, 255, .65);
}
/* States densify the pane. No fill and no teal surface, so it cannot be
   mistaken for the solid teal Add to Cart button. */
.sbr-shop-vp:hover,
.sbr-shop-vp:focus-visible {
	color: #081a1e;
	background-image:
		linear-gradient(180deg, var(--vp-sheen) 0%, rgba(255, 255, 255, 0) calc(var(--vp-sheen-stop) + 4%)),
		linear-gradient(160deg, var(--vp-body-1h) 0%, var(--vp-body-2h) 100%);
	text-decoration: none;
}
.sbr-shop-vp:focus-visible {
	outline: 2px solid #0e8a96;
	outline-offset: 2px;
}
@media (max-width: 860px) {
	/* Taller tap target on touch (the 36px desktop height is under the 44px
	   guideline); the label size is unchanged so the pill still reads as small. */
	.sbr-shop-vp {
		right: 10px;
		bottom: 10px;
		min-height: 40px;
		padding: 0 16px;
	}
}
@media (max-width: 640px) {
	/* Cheaper blur where the most pills scroll past at once. */
	.sbr-shop-vp {
		-webkit-backdrop-filter: blur(10px) saturate(155%);
		backdrop-filter: blur(10px) saturate(155%);
	}
	/* package-compare's photo fills its box edge to edge at this width, so the
	   pill provably lands on artwork — pin a denser pane there. */
	.sbr-pc .sbr-shop-vp {
		--vp-body-1: rgba(248, 255, 255, .88);
		--vp-body-2: rgba(255, 255, 255, .84);
		--vp-body-1h: rgba(250, 255, 255, .94);
		--vp-body-2h: rgba(255, 255, 255, .92);
		--vp-sheen: rgba(255, 255, 255, .3);
	}
}
/* Escape hatches: anyone who has asked for less transparency, more contrast, or
   a forced palette gets the opaque surface instead of the glass. */
@media (prefers-reduced-transparency: reduce) {
	.sbr-shop-vp {
		-webkit-backdrop-filter: none;
		backdrop-filter: none;
		--vp-body-1: rgba(251, 255, 255, .98);
		--vp-body-2: #fff;
		--vp-body-1h: #fff;
		--vp-body-2h: #fff;
		--vp-sheen: rgba(255, 255, 255, .55);
		--vp-sheen-stop: 45%;
	}
}
@media (forced-colors: active) {
	.sbr-shop-vp {
		-webkit-backdrop-filter: none;
		backdrop-filter: none;
		background-image: none;
		background-color: Canvas;
		color: CanvasText;
		border: 1px solid CanvasText;
		box-shadow: none;
		forced-color-adjust: none;
	}
	.sbr-shop-vp::after { color: CanvasText; text-shadow: none; }
}
@media (prefers-reduced-motion: reduce) {
	.sbr-shop-vp { transition: none; }
}


/* ==========================================================================
 * FULL-SCREEN POPUP CLEARANCE (mobile)
 * The four "Choose your package/system" popups are position:fixed at z-index
 * 100000, but the site's mobile bottom nav (#main-navigation-mobile, z 9999999)
 * and the chat launcher (#launcher, z 999998) sit far above them and paint over
 * the popup's bottom edge — so the full-screen popup reads as "not full screen"
 * at the bottom. Raising the popup's own z-index isn't viable: the mobile nav
 * outranks the slide-in cart drawer (#side-cart, z 999999) that opens on
 * Add-to-Cart, so going above the nav would also bury the cart. Instead, hide
 * those overlays while any shop popup is open (its body lock class is set), then
 * restore them on close. The popup is stacking-capped by an ancestor context, so
 * these root-level fixed elements paint over it no matter how high the popup's own
 * z-index goes — hiding them is the reliable fix. Covered:
 *   • #main-navigation-mobile — mobile bottom nav bar (z 9999999)
 *   • #launcher               — chat/help widget iframe (z 999998)
 *   • .saleParentWrapper      — fixed sitewide sale banner at the top (z 1030)
 * Mobile only (the nav/launcher and the full-screen treatment are mobile). The
 * slide-in cart drawer (#side-cart) is intentionally NOT hidden — it should still
 * open above the popup when Add-to-Cart is tapped. ============================= */
@media (max-width: 860px) {
	body.sbr-sp-lock  #main-navigation-mobile,
	body.sbr-pc-lock  #main-navigation-mobile,
	body.sbr-ng-lock  #main-navigation-mobile,
	body.sbr-spg-lock #main-navigation-mobile,
	body.sbr-sp-lock  #launcher,
	body.sbr-pc-lock  #launcher,
	body.sbr-ng-lock  #launcher,
	body.sbr-spg-lock #launcher,
	body.sbr-sp-lock  .saleParentWrapper,
	body.sbr-pc-lock  .saleParentWrapper,
	body.sbr-ng-lock  .saleParentWrapper,
	body.sbr-spg-lock .saleParentWrapper {
		display: none !important;
	}
}
