/*
 * The catalog grid.
 *
 * Every value here is a theme token or a ratio. No hex, no store name, no font
 * name — the pattern rule (shoptitan-core/docs/PATTERN-RULE.md) applies to the
 * stylesheet a pattern depends on exactly as it applies to the pattern.
 *
 * What it fixes, from the 2026-09-18 Safety walk (frames at 20:10 and 37:25):
 * two cards per row, each about a viewport tall, with the image free to be any
 * shape it liked — so one row of the catalog filled the screen and the page
 * under it was "super constrained" (37:21). Three per row at desktop, two at
 * tablet, a fixed image box and equal-height cards.
 */

/* THE GRID, DECLARED ONCE (🧮 one-token-file, 2026-09-29). This file used to
   declare the catalog's columns three times in 8.5 KB — a fixed 3 / 2 / 1
   here, the tokened 4 / 3 / 2 / 1 for the block template, and the same
   steps again for the classic loop — and the three disagreed. Now one
   declaration, no media query: `auto-fill` at the floor's minimum drops a
   column before a card goes under it, and the minimum itself steps with
   the viewport in assets/floor-tokens.css (150 / 200 / 220), generated from
   shoptitan-core floor.tokens.json. The column count at a width is an
   OUTCOME of that number, not a second rule. */
.woocommerce ul.products,
ul.products,
.st-catalog-grid[class*="is-style-catalog-"] .wc-block-product-template {
	/* FLOOR (c)'s `wide` count. The kit's `.st-grid-catalog` carries the same 5
	   and for the same reason: auto-fill at a 220px minimum runs EIGHT columns
	   in a 1920 container, and eight 220px cards is not a catalog the floor's
	   table ever names. The cap is cols * (min + gap) - gap, so it only ever
	   binds above the count — below it the minimum still decides, and a card
	   still drops out before it goes under the floor. */
	--st-catalog-cols: 5;
	display: grid;
	grid-template-columns: repeat(
		auto-fill,
		minmax(min(var(--wp--custom--st-card-min, 220px), 100%), 1fr)
	) !important;
	gap: var(--wp--custom--st-card-gap-row, 2rem) var(--wp--custom--st-card-gap, 0.75rem);
	align-items: stretch;
	max-inline-size: calc(
		var(--st-catalog-cols) *
			(var(--wp--custom--st-card-min) + var(--wp--custom--st-card-gap)) -
			var(--wp--custom--st-card-gap)
	);
}

.woocommerce ul.products,
ul.products {
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Core ships per-column width classes and floats. Both fight a grid. */
.woocommerce ul.products li.product,
ul.products li.product {
	width: 100% !important;
	float: none !important;
	margin: 0 !important;
	clear: none !important;
}

/* Equal height: the card is a column, the price is pushed to the bottom edge
   so every card in a row ends on the same line whatever its title wraps to. */
ul.products li.product {
	display: flex;
	flex-direction: column;
	height: 100%;
}

ul.products li.product .price {
	margin-top: auto;
}

/* One fixed box for the image, so a tall product and a wide one occupy the
   same space and the row does not set its height from the worst photograph. */
/* FLOOR (c): the box is 4/5, the garment is CONTAINED in it, and the ground it
   sits on is the store's own `stPanel` with the store's own corner — the kit's
   `.st-card-image`, ported. The theme's box was transparent and square: on a
   paper-white page a photograph with a white background had no edge at all, so
   the grid read as floating names rather than a row of cards. `stPanel` is a
   SKIN key, so what colour that ground is stays the store's (Site Settings ->
   Global Styles -> custom.stPanel), never this file's. */
ul.products li.product .product_thumbnail_wrapper,
ul.products li.product .product_thumbnail_wrapper__container,
.st-catalog-grid[class*="is-style-catalog-"] .wc-block-components-product-image {
	position: relative;
	width: 100%;
	aspect-ratio: var(--wp--custom--st-card-aspect, 4 / 5);
	overflow: hidden;
	background: var(--wp--custom--st-panel);
	border-radius: var(--wp--custom--st-radius);
}

ul.products li.product .product_thumbnail_wrapper__container img,
ul.products li.product img.kover2,
ul.products li.product .attachment-woocommerce_thumbnail {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	/* COVER, not contain (Diego, 2026-10-02: "the images on the product cards are
	   getting cut off unless they are hovered over, we probably don't need them
	   to be contained like that"). The rest photograph is square and the box is
	   4/5, so `contain` left a band of panel above and below it while the taller
	   hover photograph filled the box: the card changed size on hover. `cover`
	   fills the box at rest too and crops a square photograph by a tenth on each
	   side. FLOOR (c) says contain; this is the store owner choosing otherwise,
	   and docs/FLOOR.md in shoptitan-core still needs to say so.
	   CORRECTION, same day: the rest photograph was square only because the card
	   was handed WooCommerce's square CROP (the real cause of "cut off").
	   inc/catalog-archive.php now asks for the uncropped size. */
	object-fit: cover;
}

.st-catalog__blurb {
	max-width: var(--wp--style--global--content-size, 760px);
	margin: 0 0 2.5rem;
	color: var(--wp--preset--color--ti-accent-secondary, inherit);
}

/* WooCommerce prints the pagination BEFORE the button (woocommerce_after_shop_loop
   10 vs 15), so the sibling rules alone never matched it and both showed, the
   numbers sitting above Load more (seen live 2026-10-02). `:has()` catches it
   from the other side. */
/* Load more. The numbered pagination underneath is the no-JavaScript path and
   the crawlable next-page link, so it is hidden rather than removed — and it
   comes back the moment the button is not on the page. */
.st-catalog-more {
	display: flex;
	justify-content: center;
	margin: 3rem 0 1rem;
}

/* The kit's secondary button: an outline in the store's ink, 48px, and the
   ink fill on hover (TT-5911). It was the accent fill, which read as a second
   primary action under the grid. */
.st-catalog-more__button {
	min-block-size: 48px;
	min-inline-size: min(16rem, 100%);
	padding: 0 2.5rem;
	border: 1px solid var(--wp--preset--color--ti-fg, currentColor);
	border-radius: var(--wp--custom--st-radius, 2px);
	background: transparent;
	color: var(--wp--preset--color--ti-fg, inherit);
	font-family: var(--wp--preset--font-family--space-mono, inherit);
	font-size: var(--wp--preset--font-size--small, 0.8rem);
	letter-spacing: 0.12em;
	text-transform: uppercase;
	cursor: pointer;
}

.st-catalog-more__button:hover,
.st-catalog-more__button:focus-visible {
	background: var(--wp--preset--color--ti-fg, currentColor);
	color: var(--wp--preset--color--ti-bg, #fff);
}

.st-catalog-more__button[disabled] {
	opacity: 0.5;
	cursor: default;
}

.st-catalog-more + .woocommerce-pagination,
.st-catalog-more ~ .woocommerce-pagination,
.woocommerce-pagination:has(~ .st-catalog-more) {
	display: none;
}

/* ── The card grid, from tokens · WB-249 ────────────────────────────────────
 * Michael + Diego, 2026-09-25, mondaymerch.com beside threadghost.com at
 * half-screen width. Diego, V1 06:28: *"this is very obviously an issue of not
 * optimizing for this screen size."* Michael, V1 06:43: *"This is great to show
 * the minimum and the days."*
 *
 * WHAT WAS WRONG, and it is not this file's fault. WooCommerce Blocks' own
 * product-collection emits per-instance widths for its `displayLayout.columns`
 * and its own two breakpoints:
 *
 *     .st-catalog-grid.is-style-catalog-editorial .wc-block-product-template > li
 *         { width: calc(25.0000% - 1.5000rem) !important }
 *     @media (max-width: 1023px) { … 50% … }
 *     @media (max-width:  599px) { … 100% … }
 *
 * Four up above 1023 and two up below it, with nothing in between. At 1024-1100
 * that is four cards inside ~900px of content — about 200px each — and at
 * 700-1023 it is two enormous ones. Neither reads as intentional, and no width
 * a card could be is expressed anywhere as a floor.
 *
 * THE FIX. The template becomes a grid (the ONE declaration at the top of this
 * file) and the block's `width` declarations go inert (`width: auto`), so the
 * columns are ours: `auto-fill` at `--wp--custom--st-card-min`, which is what
 * makes 700-1100px impossible to squish — the grid drops a column before a
 * card goes under the floor, whatever the container turns out to be.
 *
 * Specificity: the block's rule is two classes and `!important`; the attribute
 * selector here adds a third, so these win without a second `!important` war.
 * Every value is a theme token (PATTERN-RULE.md).
 */
/* The block's own per-instance widths and floats, retired. Without this the
   grid item is still 25% wide and the columns do not add up. */
.st-catalog-grid[class*="is-style-catalog-"] .wc-block-product-template > li {
	width: auto !important;
	max-width: none !important;
	float: none !important;
	margin: 0 !important;
}

/* One image box, whatever the photograph is. The six style variations each set
   their own aspect-ratio with !important, so this is the token they all agree on
   — a variation that wants a different shape overrides the token on itself, not
   the rule. */
.st-catalog-grid[class*="is-style-catalog-"] .wc-block-components-product-image img,
ul.products li.product .product_thumbnail_wrapper__container img {
	aspect-ratio: var(--wp--custom--st-card-aspect, 4 / 5);
}

/* ── The hover pill, and the image's own 2% ─────────────────────────────────
 * FLOOR (c): "the pill fades and rises 4px in 280ms" over the name row, the
 * image scales 1.02 in 400ms on the floor's image curve, and where there is no
 * hover the pill is simply always there. The kit's `.st-card-pill` and
 * `.st-card-image img`, ported.
 *
 * The curve is the one this theme already uses for the same gesture
 * (assets/hover-motion.css, `.tg-hover img`), so the port reuses the number
 * rather than declaring a second easing nobody can find. The label is rendered
 * by inc/st-card-facts.php from the store's own design choice — no word from
 * this repo appears on a store's card.
 */
ul.products li.product .st-card-pill,
.st-catalog-grid[class*="is-style-catalog-"] .st-card-pill {
	position: absolute;
	inset-inline: 0.5rem;
	bottom: 0.5rem;
	display: flex;
	justify-content: flex-end;
	pointer-events: none;
	opacity: 0;
	transform: translateY(4px);
	transition:
		opacity 280ms cubic-bezier(0.22, 1, 0.36, 1),
		transform 280ms cubic-bezier(0.22, 1, 0.36, 1);
}

ul.products li.product .st-card-pill > span,
.st-catalog-grid[class*="is-style-catalog-"] .st-card-pill > span {
	padding: 0.35rem 0.75rem;
	background: var(--wp--preset--color--ti-accent);
	color: var(--wp--preset--color--ti-fg-alt);
	border-radius: var(--wp--custom--st-radius);
	font-family: var(--wp--preset--font-family--space-mono, inherit);
	font-size: 0.75rem;
	letter-spacing: var(--wp--custom--st-track);
	text-transform: var(--wp--custom--st-case);
}

ul.products li.product:hover .st-card-pill,
ul.products li.product:focus-within .st-card-pill,
.st-catalog-grid[class*="is-style-catalog-"] .wc-block-product:hover .st-card-pill,
.st-catalog-grid[class*="is-style-catalog-"] .wc-block-product:focus-within .st-card-pill {
	opacity: 1;
	transform: translateY(0);
}

ul.products li.product .product_thumbnail_wrapper__container img,
.st-catalog-grid[class*="is-style-catalog-"] .wc-block-components-product-image img {
	transition: transform 400ms cubic-bezier(0.2, 0.6, 0.2, 1);
}

ul.products li.product:hover .product_thumbnail_wrapper__container img,
.st-catalog-grid[class*="is-style-catalog-"] .wc-block-product:hover .wc-block-components-product-image img {
	transform: scale(1.02);
}

/* A touch device has no hover, so the pill is not a secret. */
@media (hover: none) {
	ul.products li.product .st-card-pill,
	.st-catalog-grid[class*="is-style-catalog-"] .st-card-pill {
		opacity: 1;
		transform: none;
	}
}

@media (prefers-reduced-motion: reduce) {
	ul.products li.product .st-card-pill,
	.st-catalog-grid[class*="is-style-catalog-"] .st-card-pill,
	ul.products li.product .product_thumbnail_wrapper__container img,
	.st-catalog-grid[class*="is-style-catalog-"] .wc-block-components-product-image img {
		transition: none;
	}
	ul.products li.product:hover .product_thumbnail_wrapper__container img,
	.st-catalog-grid[class*="is-style-catalog-"] .wc-block-product:hover .wc-block-components-product-image img {
		transform: none;
	}
}

/* ── The kit's catalog skin · TT-5911 ───────────────────────────────────────
 * Diego, 2026-10-01: the live /products/ should look like the titan-storefront
 * kit's. What was wrong, measured on threadghost.com at 1280:
 *   - a 384px photo banner and 130px of padding before the first row;
 *   - the grid capped at 798px by the legacy stylesheet, in 4 columns of 181;
 *   - every card a box inside a box (legacy `.dtla_product` ground + border,
 *     a white inner container), its facts line first in the markup;
 *   - the rail wrapped in a second bordered box.
 * Category archives keep their banner (term meta); only the SHOP page drops it.
 * Every value is a token. `body.woocommerce` + `li.dtla_product.product` is the
 * specificity needed to beat the scoped legacy sheet; the few `!important`s
 * are where that sheet already used one.
 *
 * The card minimum steps (150 / 200 / 220) come from assets/floor-tokens.css,
 * which until 2026-10-02 lost to theme.json's single value on WooCommerce pages
 * (inc/floor-tokens.php explains). This grid used to restate the steps itself;
 * it reads the token now.
 */
body.woocommerce-shop .tg-cat-banner{min-height:0 !important;background:transparent !important;color:var(--wp--preset--color--ti-fg) !important;padding-top:2.5rem !important;padding-bottom:1rem !important}
body.woocommerce-shop .tg-cat-banner::before,body.woocommerce-shop .tg-cat-banner::after{display:none !important;content:none !important}
body.woocommerce-shop .tg-cat-banner .wp-block-query-title{color:var(--wp--preset--color--ti-fg) !important;text-transform:uppercase}
body.woocommerce-shop .tg-cat-banner__crumbs,body.woocommerce-shop .tg-cat-banner__crumbs a{color:var(--wp--preset--color--ti-accent-secondary) !important}
body.woocommerce-shop .tg-cat-banner__col{max-width:none}

body.woocommerce .dtla-shop-archive ul.products{max-inline-size:none;width:100%;gap:var(--wp--custom--st-card-gap-row) var(--wp--custom--st-card-gap) !important}

@media(min-width:1024px){body.woocommerce .st-facet-drawer{border:0 !important;background:transparent !important;border-radius:0 !important}body.woocommerce .st-facet-drawer .st-facet{border-bottom:1px solid var(--wp--preset--color--ti-line)}}

body.woocommerce-shop .tg-cat-banner{padding-bottom:0 !important}
body.woocommerce-shop main > .container{padding-top:0 !important}
body.woocommerce-shop .dtla-shop-archive{padding-top:1rem !important}
body.woocommerce .dtla-shop-archive__sidebar,body.woocommerce .dtla-shop-archive__filters{border:0 !important;background:transparent !important;border-radius:0 !important;box-shadow:none !important;padding:0 !important}
body.woocommerce-shop main{margin-block-start:0 !important}
body.woocommerce-shop main > .container{margin-block-start:0 !important}
@media(max-width:1023.98px){body.woocommerce-shop main > .container{padding-inline:0 !important}body.woocommerce-shop .tg-cat-banner{padding-inline:0 !important}body.woocommerce-shop .tg-cat-banner__inner{padding-inline:var(--wp--style--root--padding-left,24px) !important}}

@media(min-width:1024px){body.woocommerce .dtla-shop-archive__content{column-gap:2rem !important}}
