/**
 * Shop: Simple Grid - shop listing review page.
 *
 * Factory Fresh tokens, lifted verbatim from cw-pdp/assets/cw-pdp.css - the
 * same system as the PDP and the Trade Board, not a third interpretation.
 *
 * Scoped under .cwsg throughout: this renders inside the real chrome, which
 * carries Bricks' @layer sheet and WooCommerce's stylesheet, so bare class
 * names would collide in both directions.
 *
 * The card is deliberately the LIVE SHOP's card, restated: photo, name, price
 * range, size pills, one button. The whole design argument of this direction
 * is that the card stays quiet and the aisle choosing moves up into the mega
 * menu - so nothing here may shout.
 */

.cwsg {
	--sg-lime: var(--cw-lime, #80bc00);
	--sg-lime-deep: var(--cw-lime-deep, #5f8c00);
	--sg-lime-dark: var(--cw-lime-dark, #4c7000);
	--sg-lime-wash: var(--cw-lime-wash, #f3f9e4);
	--sg-lime-row: var(--cw-lime-row, #f9fcf0);
	--sg-olive: var(--cw-olive, #16210a);
	--sg-ink: var(--cw-ink, #263238);
	--sg-ink-2: var(--cw-ink-2, #52575a);
	--sg-grey: var(--cw-grey, #6b6b6b);
	--sg-faint: var(--cw-faint, #9a9a94);
	--sg-ground: var(--cw-ground, #f7f7f5);
	--sg-card: #fff;
	--sg-line: var(--cw-line, #e7e5df);
	--sg-line-2: var(--cw-line-2, #d6d3ca);
	--sg-amber: var(--cw-amber, #9a6414);
	--sg-brick: var(--cw-brick, #a3372c);
	--sg-blue: var(--cw-rewards, #185aa6);
	--sg-blue-deep: var(--cw-rewards-deep, #12467f);
	--sg-blue-wash: var(--cw-rewards-tint, #e9f1fa);
	--sg-blue-line: var(--cw-rewards-line, #cdddf0);

	/*
	 * PROMO. --cw-campaign-amber is the token whose documented job is exactly
	 * this ("promo banners, competitions"), so the strip fill and its ink are
	 * straight aliases and no new colour enters the system.
	 *
	 * --cw-promo-deep is the one value the palette genuinely does not answer:
	 * the campaign amber is a FILL, and as TYPE on white it measures 2.42:1.
	 * #a8530a measures 5.38:1 on white and 4.93:1 on the pill wash below, and
	 * still reads orange rather than the desaturated state --cw-amber (4.99:1,
	 * but brown). Figures measured, not estimated. It is aliased so that
	 * promoting it to cw-tokens.css later needs no edit here - and cw-pdp.css
	 * aliases the same name, which is the threshold that file sets for a real
	 * token ("invented independently in two or more plugins").
	 *
	 * The pill wash and border reuse the existing amber tint/line. Their
	 * documented zone is state (pending, low stock), but nothing on a product
	 * card uses those, so there is no collision - and two near-identical
	 * off-whites would be exactly the fragmentation the sweep removed.
	 */
	--sg-promo: var(--cw-campaign-amber, #fc881d);
	--sg-promo-ink: var(--cw-amber-ink, #3d2000);
	--sg-promo-deep: var(--cw-promo-deep, #a8530a);
	--sg-promo-wash: var(--cw-amber-tint, #fdf4e6);
	--sg-promo-line: var(--cw-amber-line, #ecdcc0);

	background: var(--sg-ground);
	color: var(--sg-ink);
	font-family: system-ui, -apple-system, "Segoe UI", roboto, sans-serif;
	font-size: 14.5px;
	line-height: 1.5;
	-webkit-font-smoothing: antialiased;
}

.cwsg *,
.cwsg *::before,
.cwsg *::after {
	box-sizing: border-box;
}

/*
 * The hidden attribute must ALWAYS win. Its browser default (display: none)
 * sits in the UA stylesheet, so any component rule that sets a display -
 * .cwsg-btn { display: block }, .cwsg-stepper { display: flex } - silently
 * overrides it, which is exactly the bug this fixes: the Add button and the
 * quantity stepper both showing at once. State on this page is driven by
 * [hidden]; no layout rule may outrank it.
 */
.cwsg [hidden] {
	display: none !important;
}

.cwsg a {
	color: inherit;
	text-decoration: none;
}

.cwsg button {
	font-family: inherit;
	cursor: pointer;
}

.cwsg :focus-visible {
	outline: 3px solid rgba(128, 188, 0, 0.55);
	outline-offset: 2px;
	border-radius: 4px;
}

.cwsg-num,
.cwsg .woocommerce-Price-amount {
	font-variant-numeric: tabular-nums;
}

.cwsg-wrap {
	max-width: 1300px;
	margin: 0 auto;
	padding: 0 20px;
}

/* --- review banner --- */
.cwsg-review {
	background: var(--sg-olive);
	color: var(--cw-lime-line, #dcecb8);
	font-size: 12.5px;
	padding: 9px 0;
}

.cwsg-reviewin {
	display: flex;
	align-items: center;
	gap: 14px;
	flex-wrap: wrap;
}

.cwsg-review b {
	color: #fff;
}

.cwsg-badge {
	background: var(--sg-lime);
	color: var(--sg-olive);
	border-radius: 5px;
	padding: 3px 10px;
	font-weight: 800;
	font-size: 11px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	white-space: nowrap;
}

.cwsg-reviewlink {
	margin-left: auto;
	color: var(--cw-lime-bright, #b5e048);
	font-weight: 700;
	border-bottom: 1px solid rgba(181, 224, 72, 0.4);
	white-space: nowrap;
}

/* --- page head --- */
.cwsg-main {
	padding-top: 22px;
	padding-bottom: 46px;
}

.cwsg-crumb {
	font-size: 11.5px;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--sg-grey);
	margin-bottom: 8px;
}

.cwsg-crumb a:hover {
	color: var(--sg-ink);
}

.cwsg-headrow {
	display: flex;
	align-items: baseline;
	gap: 13px;
	flex-wrap: wrap;
}

.cwsg-headrow h1 {
	font-size: 24px;
	font-weight: 800;
	letter-spacing: -0.025em;
	margin: 0;
	line-height: 1.2;
	color: var(--sg-ink);
}

.cwsg-cnt {
	font-size: 13px;
	color: var(--sg-grey);
}

.cwsg-clear {
	font-size: 12.5px;
	font-weight: 700;
	color: var(--sg-lime-dark);
	border: 1.5px solid var(--sg-line-2);
	border-radius: 999px;
	padding: 4px 12px;
	transition: border-color 0.14s, background 0.14s;
}

.cwsg-clear:hover {
	border-color: var(--sg-lime);
	background: var(--sg-lime-row);
}

.cwsg-sort {
	margin-left: auto;
	display: flex;
	align-items: center;
	gap: 8px;
	font-size: 12.5px;
	color: var(--sg-grey);
	font-weight: 600;
}

.cwsg-sort select {
	border: 1.5px solid var(--sg-line-2);
	border-radius: 7px;
	padding: 7px 10px;
	font-size: 13px;
	font-weight: 700;
	color: var(--sg-ink-2);
	background: var(--sg-card);
	font-family: inherit;
}

.cwsg-hint {
	font-size: 13px;
	color: var(--sg-ink-2);
	margin: 8px 0 0;
	max-width: 78ch;
}

.cwsg-hint b {
	color: var(--sg-ink);
}

/*
 * THE PROMO TYPE ROW. Same tag-chip language as the size pills further down
 * the card (.cwsg-pill) rather than a new pattern, because it is the same
 * idea - a row of togglable labels - just filtering the whole aisle instead
 * of one product. Selected fills brand orange (the promo system's own
 * colour, not the lime used for aisle choosing) so "which tags are active"
 * reads at a glance against the count badges, which stay neutral either way.
 */
.cwsg-ptypes {
	display: flex;
	flex-wrap: wrap;
	gap: 7px;
	margin-top: 12px;
}

.cwsg-ptype {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	border: 1.5px solid var(--sg-line-2);
	background: var(--sg-card);
	border-radius: 999px;
	padding: 5px 12px;
	font-size: 12px;
	font-weight: 700;
	color: var(--sg-ink-2);
	transition: border-color 0.13s, background 0.13s, color 0.13s;
}

.cwsg-ptype:hover {
	border-color: var(--sg-promo-deep);
	background: var(--sg-promo-wash);
	color: var(--sg-promo-deep);
}

.cwsg-ptype .cwsg-num {
	font-size: 10.5px;
	font-weight: 800;
	color: inherit;
	opacity: 0.6;
}

.cwsg-ptype.is-on {
	border-color: var(--sg-promo-deep);
	background: var(--sg-promo);
	color: var(--sg-promo-ink);
}

.cwsg-ptype.is-on:hover {
	border-color: var(--sg-promo-ink);
	background: var(--sg-promo);
	color: var(--sg-promo-ink);
}

.cwsg-ptype.is-clear {
	border-style: dashed;
	color: var(--sg-faint);
}

.cwsg-ptype.is-clear:hover {
	border-color: var(--sg-line-2);
	background: var(--sg-card);
	color: var(--sg-grey);
}

/* --- the grid --- */
.cwsg-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
	gap: 16px;
	margin-top: 20px;
}

/*
 * [hidden] is how the promo-type row (both the server-rendered starting
 * state and shop-simple-grid.js's instant toggle) hides a card - but the
 * attribute selector and .cwsg-card/.cwsg-ptype below are equal specificity,
 * and this author sheet loads after the UA one, so `display: flex/inline-flex`
 * would silently win and the attribute would do nothing. These two rules
 * exist only to outrank that.
 */
.cwsg-card[hidden],
.cwsg-ptype[hidden] {
	display: none;
}

.cwsg-card {
	position: relative; /* anchors the wishlist heart */
	background: var(--sg-card);
	border: 1px solid var(--sg-line);
	border-radius: 12px;
	padding: 14px;
	display: flex;
	flex-direction: column;
	transition: border-color 0.15s, box-shadow 0.15s;
}

/* --- wishlist heart: proxies the real TI button, which stays hidden --- */
.cwsg-wish {
	position: absolute;
	top: 20px;
	right: 20px;
	z-index: 5;
}

.cwsg-wish .tinv-wraper {
	display: none;
}

.cwsg-heart {
	width: 36px;
	height: 36px;
	border: 1.5px solid var(--sg-line);
	background: var(--sg-card);
	border-radius: 999px;
	display: grid;
	place-items: center;
	color: var(--sg-ink-2);
	box-shadow: 0 1px 4px rgba(38, 50, 56, 0.1);
	transition: border-color 0.14s, color 0.14s, transform 0.1s;
}

.cwsg-heart svg {
	width: 18px;
	height: 18px;
}

.cwsg-heart:hover {
	border-color: var(--sg-brick);
	color: var(--sg-brick);
}

.cwsg-heart:active {
	transform: scale(0.92);
}

.cwsg-heart.is-on {
	color: var(--sg-brick);
	border-color: var(--sg-brick);
}

.cwsg-heart.is-on svg {
	fill: var(--sg-brick);
	stroke: var(--sg-brick);
}

.cwsg-card:hover {
	border-color: var(--sg-line-2);
	box-shadow: 0 5px 16px rgba(38, 50, 56, 0.08);
}

.cwsg-shot {
	position: relative;
	display: grid;
	place-items: center;
	aspect-ratio: 1 / 1;
	margin-bottom: 11px;
	overflow: hidden;
	border-radius: 8px;
	background: var(--cw-card, #fff);
}

.cwsg-shot img {
	max-width: 100%;
	max-height: 100%;
	width: auto;
	height: auto;
	object-fit: contain;
	display: block;
	margin: 0;
	transition: transform 0.3s ease;
}

.cwsg-card:hover .cwsg-shot img {
	transform: scale(1.04);
}

.cwsg-flag {
	position: absolute;
	top: 8px;
	left: 8px;
	background: var(--sg-lime);
	color: var(--sg-olive);
	font-size: 10.5px;
	font-weight: 800;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	padding: 4px 9px;
	border-radius: 5px;
}

.cwsg-flag.is-out {
	background: var(--sg-ground);
	color: var(--sg-brick);
	border: 1px solid var(--sg-line-2);
}

/*
 * THE PROMO STRIP. Bottom edge of the photo, full width.
 *
 * Bottom rather than a corner ribbon or a top-left pill for three reasons: it
 * never covers the product, it never collides with .cwsg-flag (top-left) or
 * .cwsg-wish (top-right, z-index 5), and a full-width bar has room for a line
 * of text - which is the point of this treatment, since it names WHICH size is
 * on special rather than just flashing "Sale".
 *
 * z-index 3 is deliberate, not decorative: .cwsg-shot img takes a
 * transform: scale() on card hover, and a transformed element paints alongside
 * positioned ones, so relying on DOM order alone would let the growing image
 * ride over the strip.
 */
.cwsg .cwsg-promo {
	position: absolute;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 3;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	padding: 5px 9px;
	background: var(--sg-promo);
	color: var(--sg-promo-ink);
	font-size: 10.5px;
	font-weight: 800;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	line-height: 1.35;
	/*
	 * Matches .cwsg-shot's own 8px radius. Without this, the strip's square
	 * bottom corners get clipped by .cwsg-shot's overflow: hidden into the
	 * curve of that radius - which chops the rewards variant's hairline
	 * border in half right at the corner instead of letting it turn cleanly.
	 */
	border-radius: 0 0 8px 8px;
}

/*
 * A rewards-only promo (cw_promo_strip() in inc/promo.php) switches the strip
 * itself from the public-promo orange to the quarantined rewards blue tint -
 * orange = a public special anyone can see the price of, light blue = a
 * members special, so the colour alone now tells a shopper which kind of
 * "Promo" label they are looking at without reading the strip text. The
 * inset line stands in for the strip's usual solid fill giving it an edge
 * against a light photo background.
 */
.cwsg .cwsg-promo.cw-promo--rewards {
	background: var(--sg-blue-wash);
	color: var(--sg-blue);
	box-shadow: inset 0 0 0 1px var(--sg-blue-line);
}

/*
 * The label truncates and the figure never does. A card is ~232px wide, so
 * "Promo · 5L & 25L on special" will not always fit - and if something has to
 * go it must be the descriptive tail, not the number, which is the part a
 * shopper is scanning for. The full promo name rides the title attribute.
 */
.cwsg .cwsg-promo .cw-promo-text {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.cwsg .cwsg-promo .cw-promo-figure {
	flex: none;
	background: var(--sg-promo-ink);
	color: #fff;
	border-radius: 3px;
	padding: 1px 6px;
	letter-spacing: 0.02em;
}

/*
 * The My Family Rewards mark, standing in for a Rand figure on a
 * rewards-only promo (cw_promo_is_rewards_only()) - a guest cannot have the
 * member price, so the chip names who can. Image, not text (2026-08-25): the
 * words badge fought the strip's own uppercase blue-on-orange treatment; the
 * pictogram carries the same meaning without adding a second colour block.
 * height, not width, is constrained - the source is trimmed to its own
 * bounding box (121x112 native) so aspect ratio is safe to leave free.
 */
.cwsg .cwsg-promo .cw-promo-mark {
	flex: none;
	display: block;
	height: 20px;
	width: auto;
}

.cwsg-name {
	font-size: 14.5px;
	font-weight: 800;
	letter-spacing: -0.01em;
	line-height: 1.3;
	/* 9px, not 5px: the price used to sit directly under the name and carried
	   its own 10px below it. With the price moved down into the action row the
	   size pills follow the name directly, and 5px read as cramped. */
	margin: 0 0 9px;
	color: var(--sg-ink);
}

.cwsg-name a:hover {
	color: var(--sg-lime-dark);
}

.cwsg-price {
	/* 13.5, not 14: see the gap note on .cwsg-cta - the price now shares a row
	   with the rewards chip and the 44px Add button, and half a pixel of type
	   is what keeps a full range ("R115.99 - R449.99") on one line at the
	   narrowest column. It still reads as the second-loudest thing on the card
	   after the name. */
	font-size: 13.5px;
	font-weight: 700;
	color: var(--sg-ink-2);
	margin-bottom: 10px;
}

.cwsg-price del {
	color: var(--sg-faint);
	font-weight: 600;
	font-size: 12.5px;
}

.cwsg-price ins {
	text-decoration: none;
	color: var(--sg-lime-dark);
}

.cwsg-pills {
	display: flex;
	flex-wrap: wrap;
	gap: 5px;
	margin-bottom: 12px;
}

.cwsg-pill {
	border: 1.5px solid var(--sg-line-2);
	background: var(--sg-card);
	border-radius: 6px;
	padding: 4px 9px;
	font-size: 11.5px;
	font-weight: 800;
	color: var(--sg-ink-2);
	transition: border-color 0.13s, background 0.13s, color 0.13s;
}

.cwsg-pill:hover {
	border-color: var(--sg-lime);
	background: var(--sg-lime-row);
	color: var(--sg-lime-dark);
}

.cwsg-pill.is-more {
	border-style: dashed;
	color: var(--sg-faint);
}

/*
 * A selected size: outlined, not filled (user preference 2026-08-20) - a
 * lime border reads as "chosen" without the pill competing with the lime
 * Add/stepper buttons below it for attention.
 */
.cwsg-pill.is-sel {
	background: var(--sg-card);
	border-color: var(--sg-lime-deep);
	border-width: 2px;
	color: var(--sg-ink);
}

.cwsg-pill.is-sel:hover {
	background: var(--sg-card);
	border-color: var(--sg-lime-deep);
	color: var(--sg-ink);
}

/*
 * THE ON-PROMO SIZE - filled brand orange, so "the 2L is the one on promo" is
 * legible from the pill row alone.
 *
 * Filled, not outlined. The first version was a tan border over a cream wash
 * with orange type: technically orange, and it read as beige sitting next to
 * three white pills. The promo has to carry as much weight as the lime
 * selection ring beside it, or the strip on the photo ends up being the only
 * thing saying anything.
 *
 * Never emitted for an out-of-stock size (see the template), so this rule and
 * .is-oos below can never both apply.
 */
.cwsg-pill.is-promo {
	border-color: var(--sg-promo);
	background: var(--sg-promo);
	color: var(--sg-promo-ink);
}

.cwsg-pill.is-promo:hover {
	border-color: var(--sg-promo-deep);
	background: var(--sg-promo);
	color: var(--sg-promo-ink);
}

/*
 * Promo AND chosen. Three classes so it outranks both two-class rules above -
 * without it the later .is-sel declarations would repaint a promo pill white the
 * moment it was picked, losing the promo exactly when the shopper engaged.
 *
 * The orange FILL stays and the RING darkens, so each colour keeps one job:
 * orange means on promo, a ring means this is what "+ Add" will add.
 *
 * The ring is --sg-promo-ink, not --sg-promo-deep: deep orange on the orange
 * fill measures 2.22:1, under the 3:1 a non-text state indicator needs to be
 * perceivable at all. The ink measures 6.18:1 and is already the pill's own
 * text colour, so the selected state costs the palette nothing.
 */
.cwsg-pill.is-promo.is-sel {
	border-color: var(--sg-promo-ink);
	border-width: 2px;
	background: var(--sg-promo);
	color: var(--sg-promo-ink);
}

/*
 * A rewards-only promo's on-promo size (is-rewards, set alongside is-promo in
 * the template - see cw_promo_strip()'s cw-promo--rewards note above) takes
 * the rewards TINT WASH rather than the public-promo orange fill: pill and
 * strip become the same material, so a members special reads as one quiet
 * system instead of the pill repeating the strip's orange in a second place
 * on the same card.
 *
 * Comes after .is-promo so it overrides the orange fill on equal (three vs
 * four class) specificity; .is-promo.is-rewards.is-sel comes after that
 * again for the same reason the plain promo+sel combo does.
 */
.cwsg-pill.is-promo.is-rewards {
	border-color: var(--sg-blue-line);
	background: var(--sg-blue-wash);
	color: var(--sg-blue-deep);
}

.cwsg-pill.is-promo.is-rewards:hover {
	border-color: var(--sg-blue-line);
	background: var(--sg-blue-wash);
	color: var(--sg-blue-deep);
}

.cwsg-pill.is-promo.is-rewards.is-sel {
	border-color: var(--sg-blue);
	border-width: 2px;
	background: var(--sg-blue-wash);
	color: var(--sg-blue-deep);
}

.cwsg-pill.is-oos {
	color: var(--sg-faint);
	border-style: dashed;
	cursor: not-allowed;
}

.cwsg-pill.is-oos:hover {
	border-color: var(--sg-line-2);
	background: var(--sg-card);
	color: var(--sg-faint);
}

/* "+ Add" pressed with no size chosen: point at the pills, don't guess. */
.cwsg-pills.is-nudge .cwsg-pill:not(.is-oos) {
	border-color: var(--sg-lime);
	box-shadow: 0 0 0 3px rgba(128, 188, 0, 0.25);
}

/*
 * THE ACTION ROW - price left, action right, one line (2026-08-24; the
 * "compact card", chosen from the Add-button review). The price used to sit
 * on its own line under the name with the CTA a full row below; pairing them
 * removes a row of card height and lets Add shrink to a 44px circle instead
 * of a full-width lime pill that repeated ~20x per screen and pulled the eye
 * off the packshots.
 *
 * flex-wrap is the safety valve, not decoration: the home carousel renders
 * this same card at ~186px wide (6 across its track) against the shop grid's
 * 232px-and-up columns, so on the narrowest card a long price range wraps to
 * two short lines beside the button instead of shoving it out of the card.
 */
.cwsg-cta {
	margin-top: auto;
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	/* 6, not 9: at the grid's 232px MINIMUM column a full price range needs
	   ~108px and the row only has ~109 to give it after the chip and button.
	   Three pixels of gap is the difference between a range sitting on one
	   line and stacking. */
	gap: 6px;
}

/*
 * order + margin-right:auto rather than a wrapper <div> around the controls:
 * cwsg_render_card() emits price / button / stepper / chip as flat siblings,
 * and this pins the price left and groups the rest right without adding an
 * element for shop-simple-grid.js to have to reach through.
 */
/*
 * flex: 1 1 0 (a ZERO basis), not margin-right:auto - and this is the whole
 * trick that keeps the row one row.
 *
 * A flex line is broken up using each item's hypothetical size, which for
 * `auto` is max-content. A full price range renders ~112px, and on the home
 * carousel's 190px card the row only has 160px: 112 + 37 (rewards chip) + 44
 * (button) + gaps = 207, so the browser wrapped the BUTTON onto a second line
 * and every carousel card grew ~35px taller - the opposite of compact.
 *
 * A zero basis takes the price out of that fitting decision entirely. The
 * chip and button always fit on one line, and the price then grows into
 * whatever is left and wraps its own TEXT instead: one line on a wide shop
 * column, two short lines on the narrow carousel card, and the row stays
 * 44px tall either way because the button is the tallest thing in it.
 */
.cwsg-cta .cwsg-price {
	order: 1;
	flex: 1 1 0;
	min-width: 0;
	margin: 0;
	line-height: 1.25;
}

.cwsg-cta .cwsg-rew {
	order: 2;
}

.cwsg-cta .cwsg-btn,
.cwsg-cta .cwsg-stepper {
	order: 3;
}

/* A text CTA ("Select options" / "View product") may shrink, and wraps to its
   own line on the narrowest cards rather than overflowing. */
.cwsg-cta .cwsg-btn:not(.cwsg-addbtn) {
	flex: 0 1 auto;
}

.cwsg-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 5px;
	text-align: center;
	background: var(--sg-lime);
	color: var(--sg-olive);
	border-radius: 999px;
	font-size: 13.5px;
	font-weight: 800;
	padding: 11px 14px;
	transition: background 0.15s;
}

.cwsg-btn:hover {
	background: var(--cw-lime-deep, #5f8c00);
}

.cwsg-btn.is-ghost {
	background: transparent;
	border: 1.5px solid var(--sg-line-2);
	color: var(--sg-ink-2);
}

.cwsg-btn.is-ghost:hover {
	border-color: var(--sg-lime);
	color: var(--sg-lime-dark);
	background: var(--sg-lime-row);
}

.cwsg-rew {
	background: var(--sg-blue-wash);
	border: 1px solid var(--sg-blue-line);
	color: var(--sg-blue);
	border-radius: 999px;
	padding: 4px 10px;
	font-size: 12px;
	font-weight: 800;
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
	cursor: help;
}

/*
 * ADD IS A 44px CIRCLE, OUTLINED - not a filled lime pill.
 *
 * Add is a REPEATED control: a shopper on a grid is choosing between
 * products, not between "add" and something else, so it does not need
 * primary-button weight until they have decided. Filled lime x20 stopped
 * reading as an action and started reading as a green pattern over the
 * merchandise. Lime is still here - it arrives on hover/focus, and on the
 * stepper's own + once the thing is actually in the basket.
 *
 * 44px is the touch-target floor, not a look: this control has no text label
 * to widen it, so the box has to be big enough on its own.
 *
 * Two classes deep (.cwsg-btn.cwsg-addbtn) on purpose - .cwsg-btn alone is
 * equal specificity, so this would otherwise be decided by source order.
 */
.cwsg-btn.cwsg-addbtn {
	width: 44px;
	height: 44px;
	padding: 0;
	flex: 0 0 auto;
	font-size: 22px;
	font-weight: 500;
	line-height: 1;
	background: var(--sg-card);
	border: 1.5px solid var(--sg-line-2);
	color: var(--sg-ink);
	transition: background 0.15s, border-color 0.15s, color 0.15s;
}

.cwsg-btn.cwsg-addbtn:hover,
.cwsg-btn.cwsg-addbtn:focus-visible {
	background: var(--sg-lime);
	border-color: var(--sg-lime);
	color: var(--sg-olive);
}

/*
 * SVG, not a "+" text glyph (2026-08-25, fixed a user-reported off-centre
 * plus). The button box WAS centred correctly (flexbox align/justify-center,
 * verified via getBoundingClientRect - the span's box matched the button's
 * centre exactly), but the "+" character's INK does not sit centred inside
 * its own line box for this font stack - font metrics reserve more space
 * above the baseline than a symbol glyph actually draws into, so the visible
 * stroke reads as off-centre even though the box around it is not. A path
 * drawn on a symmetric 24x24 viewBox (both strokes 5-19, centre 12,12 by
 * construction) has no such metrics to fight - it is exactly centred on
 * every font/OS/browser, which a nudge-by-pixels fix on the text glyph would
 * not have been (the offset is font-stack-dependent).
 */
.cwsg-addbtn__icon {
	width: 20px;
	height: 20px;
	stroke: currentColor;
}

.cwsg-addbtn[disabled] {
	opacity: 0.6;
	cursor: wait;
}

/*
 * Tap feedback: a full spin fired the INSTANT either "+" is pressed
 * (shop-simple-grid.js adds .is-tapped synchronously, before the async cart
 * write starts), so the button visibly reacts even on a slow connection or
 * while it's disabled mid-request - user request 2026-08-25 ("the plus
 * button to be responsive... make it rotate"). 0deg->360deg rather than a
 * half-turn: both a "+" and the stepper's "+" are symmetric under a partial
 * turn, so ending at exactly 360 is what guarantees the glyph looks
 * identical before and after regardless of font rendering, with no
 * asymmetric mid-turn artefact to worry about.
 *
 * Same class/keyframe on .cwsg-step.is-inc (the stepper's own "+", once a
 * size/qty is already chosen) as on .cwsg-addbtn - same glyph, same "one
 * more" action; spinning only the card's first "+" would read as an
 * inconsistency the moment someone taps the stepper's "+" right after.
 *
 * 1.14s, not 0.38s (2026-08-25, user request: "make it spin 3 times as
 * long") - shop-simple-grid.js removes .is-tapped on 'animationend' rather
 * than a fixed timeout, so lengthening the animation here is the whole
 * change; nothing in the JS assumes a duration.
 */
@media (prefers-reduced-motion: no-preference) {
	.cwsg-addbtn.is-tapped,
	.cwsg-step.is-inc.is-tapped {
		animation: cwsg-plus-spin 1.14s cubic-bezier(0.34, 1.56, 0.64, 1);
	}
}

@keyframes cwsg-plus-spin {
	from { transform: rotate(0deg); }
	to { transform: rotate(360deg); }
}

/* --- the stepper the Add button becomes (Walmart pattern) ---
 *
 * DELIBERATELY UNCHANGED by the 2026-08-24 compact-card work, and a lime
 * wash was explicitly rejected for it (user decision): white surface, grey
 * hairline, grey filled +. Leave it alone - it is the resting Add control
 * that changed, not this.
 */
.cwsg-stepper {
	display: inline-flex;
	align-items: center;
	gap: 2px;
	border: 1.5px solid var(--sg-line-2);
	border-radius: 999px;
	background: var(--sg-card);
	padding: 3px;
	height: 42px;
	width: auto;
	flex: 0 0 auto;
}

.cwsg-step {
	width: 34px;
	height: 34px;
	flex: 0 0 auto;
	border: 0;
	background: transparent;
	border-radius: 999px;
	font-size: 17px;
	font-weight: 800;
	color: var(--sg-ink);
	line-height: 1;
	display: grid;
	place-items: center;
	transition: background 0.13s;
}

.cwsg-step:hover {
	background: var(--sg-ground);
}

/* CW grey (the logo's second colour), not lime. The original reason was that
   lime was reserved for the filled "+ Add" pill; that pill is now an outlined
   circle, but the grey stays by explicit decision (2026-08-24) - the stepper
   was to keep its original look. */
.cwsg-step.is-inc {
	background: var(--sg-ink-2);
	color: #fff;
}

.cwsg-step.is-inc:hover {
	background: var(--cw-ink-2, #52575a);
}

.cwsg-step[disabled] {
	opacity: 0.5;
	cursor: wait;
}

.cwsg-qty {
	min-width: 30px;
	padding: 0 4px;
	text-align: center;
	font-size: 14.5px;
	font-weight: 800;
	color: var(--sg-ink);
}

.cwsg-empty {
	padding: 40px 0;
	font-size: 14px;
	color: var(--sg-grey);
}

/* --- pager --- */
/* Same [hidden]-vs-display trap as .cwsg-card - see that rule's comment. */
.cwsg-pager[hidden] {
	display: none;
}

.cwsg-pager {
	display: flex;
	align-items: center;
	gap: 7px;
	margin-top: 24px;
	flex-wrap: wrap;
}

/*
 * The endless-scroll trigger (shop-simple-grid.js) - invisible, zero
 * footprint in the layout. rootMargin on the observer means the fetch fires
 * well before this actually reaches the viewport, so it needs no height of
 * its own to be found in time.
 */
.cwsg-scroll-sentinel {
	height: 1px;
}

.cwsg-pg {
	min-width: 38px;
	height: 38px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border: 1.5px solid var(--sg-line-2);
	border-radius: 7px;
	font-size: 13.5px;
	font-weight: 800;
	color: var(--sg-ink-2);
	background: var(--sg-card);
	padding: 0 11px;
}

.cwsg-pg:hover {
	border-color: var(--sg-lime);
	color: var(--sg-lime-dark);
}

.cwsg-pg.is-on {
	background: var(--sg-lime);
	border-color: var(--sg-lime-deep);
	color: var(--sg-olive);
}

.cwsg-pgnote {
	margin-left: auto;
	font-size: 12.5px;
	color: var(--sg-grey);
}

/* --- the aisle currently showing, painted by this page's JS ---
   Two chrome generations: the original header's mega tiles get an outline,
   the v2 aisle rail's links get the inset lime underline the rest of the
   system uses for "you are here". Literal colours: these rules style header
   elements OUTSIDE .cwsg, so the --sg-* tokens are out of scope. */
.cwpr-mega__tile.cwsg-active {
	outline: 3px solid var(--cw-lime, #80bc00);
	outline-offset: 2px;
	border-radius: 8px;
}

#cwh-header a.cwsg-active {
	box-shadow: inset 0 -3px 0 var(--cw-lime, #80bc00);
}

/* --- Discover (phone only) --- */
.cwsg-discover {
	display: none;
	position: fixed;
	right: 16px;
	bottom: 18px;
	z-index: 950;
	align-items: center;
	gap: 8px;
	background: var(--sg-lime);
	color: var(--sg-olive);
	border: 0;
	border-radius: 999px;
	font-size: 14px;
	font-weight: 800;
	padding: 13px 20px;
	box-shadow: 0 6px 20px rgba(76, 112, 0, 0.35);
}

.cwsg-discover svg {
	width: 17px;
	height: 17px;
	color: var(--sg-olive);
}

.cwsg-sheetwrap {
	position: fixed;
	inset: 0;
	z-index: 960;
}

.cwsg-overlay {
	position: absolute;
	inset: 0;
	background: rgba(22, 33, 10, 0.55);
}

.cwsg-sheet {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	background: var(--sg-card);
	border-radius: 16px 16px 0 0;
	max-height: 78vh;
	overflow-y: auto;
	padding: 16px 16px 22px;
	box-shadow: 0 -6px 30px rgba(0, 0, 0, 0.25);
}

.cwsg-sheethead {
	display: flex;
	align-items: center;
	gap: 12px;
	margin-bottom: 13px;
}

.cwsg-sheethead h2 {
	font-size: 16px;
	font-weight: 800;
	letter-spacing: -0.02em;
	margin: 0;
	color: var(--sg-ink);
}

.cwsg-close {
	margin-left: auto;
	width: 34px;
	height: 34px;
	border: 1.5px solid var(--sg-line-2);
	background: var(--sg-card);
	border-radius: 999px;
	font-size: 18px;
	font-weight: 800;
	color: var(--sg-ink-2);
	line-height: 1;
}

.cwsg-sheetgrid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 9px;
}

.cwsg-stile {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 5px;
	background: var(--sg-ground);
	border: 1.5px solid var(--sg-line);
	border-radius: 10px;
	padding: 11px 8px 9px;
	text-align: center;
}

.cwsg-stile img {
	width: 56px;
	height: 56px;
	object-fit: contain;
	display: block;
}

.cwsg-stile-all {
	width: 56px;
	height: 56px;
	display: grid;
	place-items: center;
	background: var(--sg-lime);
	color: var(--sg-olive);
	border-radius: 999px;
	font-weight: 800;
	font-size: 14px;
}

.cwsg-stile b {
	font-size: 11.5px;
	font-weight: 800;
	color: var(--sg-ink);
	line-height: 1.25;
}

.cwsg-stile s {
	text-decoration: none;
	font-size: 10.5px;
	font-weight: 700;
	color: var(--sg-faint);
}

.cwsg-stile.is-on {
	border-color: var(--sg-lime);
	background: var(--sg-lime-wash);
}

/* WooCommerce's own price markup, brought into this type scale. */
.cwsg .woocommerce-Price-amount {
	font-weight: inherit;
	color: inherit;
}

@media (max-width: 900px) {
	.cwsg-discover {
		display: inline-flex;
	}
}

@media (max-width: 600px) {
	.cwsg-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 10px;
	}

	.cwsg-card {
		padding: 11px;
		border-radius: 10px;
	}

	.cwsg-headrow h1 {
		font-size: 20px;
	}

	.cwsg-sort {
		margin-left: 0;
		width: 100%;
	}
}

@media (prefers-reduced-motion: reduce) {
	.cwsg *,
	.cwsg *::before,
	.cwsg *::after {
		transition: none !important;
	}

	.cwsg-card:hover .cwsg-shot img {
		transform: none;
	}
}
