/*
 * pm-showcase-rows — the homepage gallery rows (WO-29, frame 55:506).
 *
 * Source frame: docs/design/frames/29-gallery-rows.json — two full-bleed
 * columns of gallery cards, 8px apart, with the section header and a
 * tertiary "View more" button composed into the first column between its
 * two cards. Column 1 is card / text / card (heights 405 + 397 + 658);
 * column 2 is three cards (485 + 485 + 489).
 *
 * Compiled to assets/css/components/showcase-rows.css by
 * src/build-tokens.mjs, which substitutes the breakpoint markers (a comment
 * holding `@bp <name>`) with the pixel value from tokens/tokens.json. Never
 * type a breakpoint width here.
 *
 * Every colour is a --pm-color-* token. No hex value and no literal
 * breakpoint width may appear in this file. Values the token file does not
 * hold (the 40px stack gap, the 320px header column) are typed with a
 * comment citing the extract key — the same technique as the section
 * header's 40px stack gap. The cards' own presentation is the
 * pm-gallery-card component's since WO-12 (gallery-card.css); the text
 * block's header is the pm-section-header pattern's since WO-28
 * (section-header.css); the button is the pm-button tertiary since WO-74
 * (button.css). This file keeps only the rows' grid and the text block's
 * metrics.
 */

.pm-showcase-rows {
	/* The scaffold stylesheet (style.css) constrains body to a centred 72rem
	   column; the section escapes that box with the same full-bleed technique
	   as the products section (products.css), because the frame is a
	   full-width band on Blush Linen with no side margins
	   (29-gallery-rows.json#measured — full bleed, gap 8). */
	box-sizing: border-box;
	width: 100vw;
	margin-inline: calc(50% - 50vw);
	display: grid;
	/* 29-gallery-rows.json#measured.gap — 8px, --pm-space-2. */
	gap: var(--pm-space-2);
	/* The frame's background is Blush Linen — the surface token, the page's
	   own; the 8px gutters show it between the cards. */
	background-color: var(--pm-color-surface);
}

/*
 * The two columns. Below the tablet breakpoint the wrappers dissolve
 * (display: contents) so every card and the text block stack in DOM order —
 * the reading order — inside the single-column section grid; the section's
 * own 8px gap separates them uniformly.
 */
.pm-showcase-rows__col {
	display: contents;
}

/*
 * A card slot: the wrapper its container places — the section's own grid
 * below the tablet breakpoint (where __col is display: contents), the
 * column flex container above it — and the gallery card fills. The card
 * carries its own ratio (--pm-card-ratio, written inline by
 * GalleryCard::render_card) and its own overflow; min-width: 0 is the wrap
 * guard that lets a long Dutch title wrap instead of stretching its
 * container (MISTAKES.md §E4). Keep it: it is the flex item's wrap guard
 * from the tablet breakpoint up and the section grid item's below, where a
 * long title really can widen the track — not dead code.
 */
.pm-showcase-rows__slot {
	min-width: 0;
}

/*
 * The text block (29-gallery-rows.json#measured.text — padding 64 block /
 * 96 sides, content-driven height 397 ±8 at 1440): the section header, then
 * the tertiary button, separated by the section-header pattern's own 40px
 * stack gap (28-intro.json#measured.stack_gap — no space token holds 40,
 * typed here like section-header.css does).
 */
.pm-showcase-rows__text {
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 40px;
	/* Below the tablet breakpoint: 48px block / 24px sides (WO-29's
	   below-tablet spec, the intro's mobile padding step). The desktop
	   padding is the frame's 64 / 96, applied from the tablet breakpoint
	   up in the media query below — mobile-first, so the two never
	   overlap at exactly 768px. */
	padding: var(--pm-space-12) var(--pm-space-6);
}

/*
 * 29-gallery-rows.json#measured.text.header_column — the header's column is
 * 320 wide (the body wraps inside it); the H2 and the eyebrow row hold the
 * same measure. No token holds 320, typed here citing the extract.
 */
.pm-showcase-rows__text .pm-section-header {
	max-width: 320px;
}

/*
 * The button is the pm-button tertiary — SemiBold 14px, 16px block padding,
 * a 1px ink bottom rule (29-gallery-card.json#measured.text.link; the
 * WO-74 component, not restyled here). align-items: flex-start above keeps
 * it at the column's left edge.
 */

/*
 * From the tablet breakpoint up: the frame's two equal columns, each a
 * column stack with the same 8px gap (29-gallery-rows.json#measured
 * .columns — two equal 1fr columns). Both columns stretch to the row's
 * height, and the frame's intent is that they END TOGETHER at every width,
 * not only at 1440 (29-gallery-rows.json#contradictions[-1], WO-87): the
 * cards scale with the column width, the text block's height is
 * content-driven, so one column always has slack the other does not.
 *
 * Each column is therefore a COLUMN FLEX container, not a row-template
 * grid, and exactly one child absorbs that slack — chosen by what the
 * column CONTAINS, never by position or by count. Both are conditional in
 * the markup: ShowcaseRows::render emits the text block only when one of
 * eyebrow / title / body / link is non-empty, and slot() emits nothing at
 * all for a null card, so a column can hold one, two or three children in
 * either order. A fixed grid-template-rows list would hand the flexible
 * track to whatever auto-placed into it — or, with all four text fields
 * empty, to nothing at all, opening a band of section background under the
 * last card. Flex has no tracks to mis-assign: every child defaults to
 * flex: 0 1 auto and only the two mutually exclusive rules below grant
 * growth. grid-template-columns: 1fr is replaced by flex's default
 * align-items: stretch, and align-content: start by the default
 * justify-content: flex-start.
 */
@media (min-width: 768px) {
	.pm-showcase-rows {
		grid-template-columns: 1fr 1fr;
	}

	.pm-showcase-rows__col {
		display: flex;
		flex-direction: column;
		gap: var(--pm-space-2);
	}

	/*
	 * The absorber, when the column has a text block: the text block. Its
	 * height is content plus whatever slack the row has — never a typed
	 * number (the frame's 397 at 1440 is content height; at 1728 the same
	 * block grows by the row's own difference). flex-basis stays auto, not
	 * 0: a 0 basis would change the column's intrinsic contribution and
	 * move the row height off the frame's numbers.
	 */
	.pm-showcase-rows__text {
		flex: 1 1 auto;
		/* 29-gallery-rows.json#measured.text — padding 64 block / 96 sides. */
		padding: var(--pm-space-16) var(--pm-space-24);
	}

	/*
	 * Otherwise — a column of cards only, the frame's column 2 — the last
	 * slot absorbs it. :has() is already this project's idiom
	 * (gallery-card.css). The two selectors are mutually exclusive by
	 * construction: ShowcaseRows::render emits .pm-showcase-rows__text as a
	 * direct child of the column, so :has(> …) matches exactly the columns
	 * the rule above already covers.
	 */
	.pm-showcase-rows__col:not(:has(> .pm-showcase-rows__text))
		> .pm-showcase-rows__slot:last-child {
		flex: 1 1 auto;
	}

	/*
	 * And the card inside that grown slot fills it. Every card here is a
	 * --ratio card (ShowcaseRows always passes a ratio, so gallery-card.css
	 * sets height: auto + aspect-ratio), which would otherwise size from its
	 * own width and leave a gap of section background under itself. This
	 * selector is (0,5,0) against --ratio's (0,1,0) and there is no @layer
	 * in this theme, so it wins; GalleryCard writes the ratio as an inline
	 * CUSTOM PROPERTY, never an inline height, so nothing inline beats it.
	 * During the intrinsic pass the slot's flex-basis is still auto, so the
	 * percentage is cyclic and resolves as auto — the card measures at its
	 * ratio height and the column's natural height is unchanged; only the
	 * post-flex surplus is absorbed, and object-fit: cover on the image
	 * takes it. The frame does exactly this: its last right card is 489,
	 * not 485, stretched 4px to meet the left column's 1476.
	 *
	 * width: 100% is not redundant and must not be deleted as such. Once
	 * height: 100% makes the height definite, the surviving aspect-ratio
	 * computes the card's AUTOMATIC inline size from it — a block-level
	 * box's width: auto does NOT stretch-fit past a preferred aspect ratio
	 * (CSS Sizing 4 §4.1). Measured on this page before the declaration was
	 * added: at 1024 the last card rendered 684px wide inside its 508px
	 * column and pushed the document to scrollWidth 1200; at 1440, 723.6 in
	 * a 716 column. A definite width on BOTH axes retires the ratio for
	 * this one card, which is exactly the intent — it fills the slot and
	 * object-fit: cover crops the image.
	 */
	.pm-showcase-rows__col:not(:has(> .pm-showcase-rows__text))
		> .pm-showcase-rows__slot:last-child > .pm-gallery-card {
		width: 100%;
		height: 100%;
	}
}

/*
 * Zero showcases: the text block alone, full width (WO-29 — the empty state
 * renders the text block only). Declared after the tablet-up block and at
 * (0,2,0) specificity on purpose: the equal-specificity media-query rule
 * above used to win by source order and left an empty 716px column beside
 * the text block (WO-29 test report, failure 2). Below the tablet
 * breakpoint the section is a single implicit column anyway, so 1fr holds
 * at every width.
 */
.pm-showcase-rows.pm-showcase-rows--text-only {
	grid-template-columns: 1fr;
}

/*
 * Responsive (MISTAKES.md §C7 — only the navigation is designed for mobile):
 * below the tablet breakpoint the section is the single column above — the
 * wrappers dissolve, the text block's padding steps down to 48px block /
 * 24px sides (the base rule), and the cards run full width at their slots'
 * ratios.
 */
