/* =============================================================================
 * A5 — shop product cards: halve the card, fill the row.
 *
 * THE DEFECT. On dev the /shop/ product images painted at 411.7 x 411.7 px and
 * the four products sat 3-up with the fourth orphaned on a second row. Document
 * height 1932 px for four products.
 *
 * THE CAUSE IS NOT AN IMAGE RULE. Measured on the live page: the only rules
 * that reach the <img> are `width:100%` + `height:auto` (WooCommerce's
 * product-image.css) and `max-width:100%` (three sheets agree). There is no
 * height, no max-height and no aspect-ratio anywhere in its cascade. The 412 px
 * is simply THE COLUMN WIDTH arriving at a `width:100%` replaced element whose
 * source asset is square. Proven by shrinking only the container on the live
 * page — 1280 -> 800 px moved the image 411.7 -> 251.7 px with nothing else
 * touched, and the image box equals the grid track to within 0.1 px at every
 * width in the sweep (1600 -> 360).
 *
 * So the number has two inputs, and both belong to WooCommerce's own template:
 *   (1) `displayLayout.columns = 3`, which becomes the `columns-3` class and
 *       selects `grid-template-columns: repeat(auto-fill, minmax(max(150px,
 *       calc(33.33333% - .83333em)), 1fr))` from the block's emitted stylesheet;
 *   (2) `align: wide`, which makes the container 1280 px.
 * Track = (1280 - 2*22.5)/3 = 411.67. Measured: 411.656. The formula is exact.
 *
 * WHAT THIS FILE DOES, AND WHAT inc/woocommerce.php DOES
 * Input (1) is fixed AT SOURCE, in PHP: a `render_block_context` filter sets
 * `displayLayout.columns` to 4, so WooCommerce emits `columns-4` and picks its
 * OWN `calc(25% - .9375em)` rule. No CSS here overrides grid-template-columns.
 * This file supplies only input (2): it caps the grid to the width at which four
 * of WooCommerce's own columns land on the target card size, and centres it.
 *
 * ★ THE TWO HALVES MUST AGREE ON THE COLUMN COUNT. `--vnm-shop-cols` below and
 *   `VNM_SHOP_COLUMNS` in inc/woocommerce.php are the same number written twice.
 *   If they diverge the grid silently mis-sizes — 4 CSS columns against 3 real
 *   tracks gives 285 px cards and a second row, with no error anywhere. The
 *   merge script greps both and fails the build if they differ.
 *
 * NO `!important` — AND THAT WAS TESTED, NOT ASSUMED. The rule to beat is
 * `.wc-block-product-template__responsive.columns-3`, specificity (0,2,0),
 * printed in an inline <style> at head line ~68; this sheet is a <link> at head
 * line ~326, so it is later at equal specificity. Candidate G (no !important)
 * and candidate H (identical rule WITH !important) produced byte-identical
 * geometry — 208 px track, 1 row, docH 1145 — so `!important` buys nothing here
 * and is not used. Specificity was never the problem, exactly as A4 found on the
 * blog.
 *
 * SCOPE. Every selector starts at `.wp-block-woocommerce-product-collection`,
 * the block's own wrapper. It cannot match on a page with no Product Collection
 * on it, which today is every page except /shop/ and the two product-category
 * archives. Unlike A4 this lane does NOT introduce its own scope class: A4 owned
 * `templates/home.html` and could add one, whereas this markup is emitted by the
 * WooCommerce plugin and there is no filter that can add a class to it (tested:
 * `render_block_data` fires on the block but its className never reaches the
 * rendered wrapper). Two independent rollbacks still exist, and each degrades
 * safely on its own: delete this file -> 4 columns stretched to 303 px, one row;
 * delete inc/woocommerce.php -> 3 columns capped to 285 px, two rows.
 * ========================================================================== */

.wp-block-woocommerce-product-collection .wc-block-product-template {
	/* 13rem = 208px at this site's 16px root. Half of the measured 411.7px,
	   which is the whole ask. This is the ONE literal in the file. */
	--vnm-shop-card: 13rem;
	/* WooCommerce's own gap, repeated rather than redefined. It is `1.25em` on
	   this same element, so if the element's 18px font-size ever changes, the
	   real gap and this calc move together instead of drifting apart. Setting
	   `gap` here would be a bug, not a tidy-up: the block's column-count maths
	   uses a FIXED `.9375em` gap allowance, so changing the actual gap to 1.5rem
	   drops the grid from 4 columns to 3 while every number still looks right. */
	--vnm-shop-gap: 1.25em;
	--vnm-shop-cols: 4; /* MUST equal VNM_SHOP_COLUMNS in inc/woocommerce.php */

	max-width: min(
		100%,
		calc(
			var(--vnm-shop-cols) * var(--vnm-shop-card) +
			(var(--vnm-shop-cols) - 1) * var(--vnm-shop-gap)
		)
	);
	margin-inline: auto;
}

/* The results-count / sorting row is a sibling of the collection and is
 * `alignwide` (1280px) in WooCommerce's template. Left at full width it floats
 * ~190px wider than the grid on each side and the shop stops reading as one
 * column. `:has()` is used because that group carries no distinguishing class of
 * its own — only its children do. Support was verified in-browser
 * (CSS.supports('selector(:has(*))') === true, and the rule measurably resized
 * the group 1280 -> 400px in a probe) rather than assumed; a browser without
 * `:has()` simply keeps today's full-width row, which is the current behaviour
 * and not a regression. */
.wp-block-group.alignwide:has(> .wc-block-catalog-sorting),
.wp-block-group.alignwide:has(> .wc-block-product-results-count) {
	max-width: min(100%, calc(4 * 13rem + 3 * 1.25em));
	margin-inline: auto;
}

/* ---------------------------------------------------------------------------
 * The card.
 *
 * A column flexbox rather than the `list-item` flow WooCommerce ships, for one
 * measured reason: at half width a product title wraps to two lines and every
 * element below it slides down, so the "Add to cart" buttons in one row stop
 * lining up. That is not hypothetical — it is visible in this lane's own 6-up
 * candidate screenshot, where "100 Gumption Points" wrapped and its button sat
 * 28px below its neighbours' while the grid still reported all four cards at an
 * identical 371.4px height. Equal BOX height is not aligned CONTENT.
 *
 * `margin-top:auto` on the button is what fixes it: the button is the last
 * child, so the free space collects above it and the buttons sit on a common
 * baseline no matter how the titles wrap. It beats WooCommerce's
 * `:where(...)>:not(:last-child){margin-top:0}` on specificity (0,2,0 vs 0,1,0)
 * — and in any case that rule excludes the last child, which is the button.
 * ------------------------------------------------------------------------ */
.wp-block-woocommerce-product-collection .wc-block-product {
	display: flex;
	flex-direction: column;
}

.wp-block-woocommerce-product-collection .wc-block-components-product-button {
	margin-top: auto;
}

/* NO TYPOGRAPHY RULES — and that is a measured decision, not an omission.
 *
 * A draft of this file shrank the product title from 20px to 16px on the
 * reasoning that a 20px bold title is the heaviest thing in a 208px card. It was
 * previewed on the live page and the computed size came back 20px: the title
 * carries `has-medium-font-size`, and WordPress prints preset font-size classes
 * as `font-size:var(--wp--preset--font-size--medium)!important`. Winning would
 * have required the one thing this lane proved unnecessary for the actual defect
 * — so the rule was deleted rather than escalated. The owner asked for smaller
 * items, not smaller text, and the four current titles each measure one line
 * (28px) at 208px anyway. Wrap-induced misalignment is handled structurally by
 * the `margin-top:auto` above, which works at any title size.
 *
 * ---------------------------------------------------------------------------
 * The image.
 *
 * Nothing here sizes the image — the grid does, and that is the point of the
 * diagnosis above. `border-radius` + `overflow:hidden` are cosmetic only and
 * are the theme's own `--wp--custom--radius--md` (6px), not a new number. The
 * hover lift is decoration and is withdrawn under prefers-reduced-motion.
 * ------------------------------------------------------------------------ */
.wp-block-woocommerce-product-collection .wc-block-components-product-image {
	overflow: hidden;
	border-radius: var(--wp--custom--radius--md);
}

.wp-block-woocommerce-product-collection .wc-block-components-product-image img {
	transition: transform 300ms ease;
}

.wp-block-woocommerce-product-collection .wc-block-product:hover .wc-block-components-product-image img {
	transform: scale(1.03); /* contained by the overflow:hidden above */
}

@media (prefers-reduced-motion: reduce) {
	.wp-block-woocommerce-product-collection .wc-block-components-product-image img {
		transition: none;
	}
	.wp-block-woocommerce-product-collection .wc-block-product:hover .wc-block-components-product-image img {
		transform: none;
	}
}
