/* ==========================================================================
   ITV STORE — SHOP (front page product rows, shop archive, category
   archive, search results)
   ========================================================================== */

/* Row heading used by the shop-by-category and product-row dynamic block
   render callbacks (inc/blocks.php) — eyebrow+heading on the left,
   view-all/quote link on the right. */
.itv-row-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap; margin-bottom: 28px; }
/* 0.1.37: was its own separate clamp(22px, 2.4vw, 30px) — this is the
   actual root cause of the inconsistency this release fixes: headings
   inside .itv-row-head (Best-Selling Business Hardware, Configured By
   Quote, New Products) were already rendering compact via this rule,
   while "Shop by Category" (not wrapped in .itv-row-head) fell through to
   theme.json's own h2 element default instead — which was 52px before
   this same release's theme.json fix brought it down to this same
   clamp(28px, 1.5vw + 24px, 36px). Now both code paths use the identical
   formula, so no homepage H2 can drift out of sync with another again. */
.itv-row-head h2 { margin: 0; font-size: clamp(28px, 1.5vw + 24px, 36px); }
.itv-row-head .itv-row-link { font-family: var(--font-head); font-weight: 700; font-size: 14px; text-decoration: none; }

/* 0.1.31: hover border changed from black to brand yellow, icon color now
   swaps to yellow on hover too, and the card is given an explicit
   min-height (approved preview spec: ~150–170px, 32–36px icon) — matches
   the approved header-category-preview.html exactly. */
.cat-grid { display: grid; grid-template-columns: repeat(8, minmax(0,1fr)); gap: 12px; }
/* 0.1.37: min-height 150px -> 140px, title 13px -> 14px — density pass;
   150px was already inside the target range, this is a light trim, not a
   fix. Icon size (32px) unchanged. */
.cat-tile { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; text-align: center; padding: 18px 10px; min-height: 140px; border: 1px solid var(--c-border); border-radius: var(--radius-card); background: #fff; text-decoration: none; color: inherit; transition: border-color .2s ease, box-shadow .2s ease, transform .2s ease; }
.cat-tile:hover { border-color: var(--c-yellow); box-shadow: 0 10px 26px rgba(11,11,11,.1); transform: translateY(-2px); }
.cat-tile .icon { width: 32px; height: 32px; color: var(--c-black); transition: color .15s ease; }
.cat-tile:hover .icon { color: var(--c-yellow); }
/* line-height:1.25 (was the browser default, ~1.4-ish) keeps 2-line labels
   like "Servers & Storage" / "CCTV & Security" / "Cabling & Racks" from
   pushing the tile taller than necessary at the desktop density below —
   min-height (not height) means the tile still grows if a label genuinely
   needs the second line, it just doesn't waste extra space when it does. */
.cat-tile span { font-family: var(--font-head); font-weight: 700; font-size: 14px; line-height: 1.25; }

@media (max-width: 1200px) { .cat-grid { grid-template-columns: repeat(4, minmax(0,1fr)); } }
@media (max-width: 560px) { .cat-grid { grid-template-columns: repeat(3, minmax(0,1fr)); gap: 8px; } .cat-tile { padding: 16px 6px; } .cat-tile span { font-size: 11.5px; } }

/* Card image stage uses a fixed height (not aspect-ratio, which scales
   with column width and was rendering oversized on wide viewports — see
   CHANGELOG.md 0.1.16) so card height stays visually consistent regardless
   of the uploaded image's own dimensions. */
/* align-items:start (0.1.39): without it, CSS Grid's default stretch
   behavior forces every <li> in a row to match the row's tallest sibling —
   this, combined with the old flex:1/margin-top:auto pairing on
   .card-body/.card-footer above, was the actual root cause of the
   empty-space bug (see the comment above .card-body). Unconditional, not
   gated to the >=1024px density block below — this is a correctness fix,
   not a density choice, and looks wrong at every width it was present at. */
.product-grid { display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 20px; list-style: none; margin: 0; padding: 0; align-items: start; }
.product-grid.cols-4 { grid-template-columns: repeat(4, minmax(0,1fr)); }
.product-grid.cols-3 { grid-template-columns: repeat(3, minmax(0,1fr)); }

.product-card { display: flex; flex-direction: column; border: 1px solid var(--c-border); border-radius: var(--radius-card); background: #fff; overflow: hidden; transition: box-shadow .2s ease, border-color .2s ease, transform .2s ease; position: relative; }
.product-card:hover { border-color: #d8d8d8; box-shadow: 0 12px 30px rgba(11,11,11,.09); transform: translateY(-2px); }
/* 0.1.37: 240px -> 195px — this is the homepage product row's default;
   the shop/category archive's own .card-media rule (below, 220px) is
   intentionally separate and untouched — this round's density pass is
   homepage-scoped, per instruction. object-fit:contain (below) is
   unchanged, so nothing crops differently, images just sit in a shorter
   stage. */
.card-media { position: relative; height: 195px; background: #fff; display: flex; align-items: center; justify-content: center; overflow: hidden; }
.card-media img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
.card-media .icon-lg { color: #c6c6c6; }
.card-badges { position: absolute; top: 10px; left: 10px; display: flex; flex-direction: column; gap: 6px; }
.card-wish { position: absolute; top: 8px; right: 8px; width: 34px; height: 34px; border-radius: 50%; background: #fff; border: 1px solid var(--c-border); display: flex; align-items: center; justify-content: center; color: var(--c-black); cursor: pointer; }
.card-wish .icon { width: 16px; height: 16px; }
.card-wish:hover, .card-wish[aria-pressed="true"] { border-color: var(--c-black); }
.card-wish[aria-pressed="true"] .icon { color: var(--c-danger); }
/* 0.1.39: gap:8px + flex:1 removed from .card-body, margin-top:auto removed
   from .card-footer — this pairing (a flex column stretched to the grid
   row's full height, then its footer pushed to the very bottom) was the
   root cause of a real, confirmed-live empty-space bug: cards with a
   shorter 1-line title sitting in the same grid row as a 2-line-title
   sibling showed a 25px dead gap above the price/stock line, vs 5px for
   the 2-line card (measured live on "Cameras & Photography", see
   CHANGELOG.md 0.1.39). Fixed at the root two ways together: (1) the grid
   container itself now uses align-items:start (below, both here and in the
   WooCommerce-archive block further down) so a `<li>` never stretches to
   match its tallest row sibling in the first place; (2) .card-body/
   .card-footer no longer try to fill or anchor to a height that no longer
   gets imposed on them. Explicit per-element margins (below, in the
   >=1024px density block) replace the old uniform `gap` for the approved
   image->title/title->meta/meta->price/price->CTA spacing. */
.card-body { padding: 14px 16px 16px; display: flex; flex-direction: column; }
.card-brand { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--c-slate); font-weight: 700; }
.card-title { font-family: var(--font-head); font-weight: 700; font-size: 14.5px; line-height: 1.35; margin: 0 0 8px; }
.card-title a { color: inherit; text-decoration: none; }
.card-title a:hover { text-decoration: underline; }
.card-specs { font-size: 12.5px; color: var(--c-slate); line-height: 1.6; margin-bottom: 8px; }
.card-rating { display: flex; align-items: center; gap: 5px; font-size: 12px; color: var(--c-slate); margin-bottom: 8px; }
.card-rating .stars { display: flex; color: var(--c-yellow); gap: 1px; }
.card-rating .stars .icon { width: 13px; height: 13px; }
.card-footer { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.card-cta { display: flex; gap: 8px; padding: 0 16px 16px; margin-top: 8px; }
.card-cta .btn { flex: 1; }

/* Grid: 4/row wide desktop -> 3/row medium desktop & tablet landscape ->
   2/row tablet -> 1/row narrow mobile. Card image stage: 240px desktop ->
   190px tablet -> 160px mobile -> 150px narrow mobile. */
@media (max-width: 1200px) {
	.product-grid, .product-grid.cols-4 { grid-template-columns: repeat(3, minmax(0,1fr)); }
}
/* 0.1.38: max-width 1024px -> 1023px — this theme's new density block
   below uses min-width:1024px for the desktop card-media override
   (162px); leaving both at 1024 would make them ambiguously overlap at
   exactly that one pixel width. */
@media (max-width: 1023px) {
	.card-media { height: 190px; }
}
@media (max-width: 900px) {
	.product-grid, .product-grid.cols-4, .product-grid.cols-3 { grid-template-columns: repeat(2, minmax(0,1fr)); }
}
@media (max-width: 700px) {
	.product-grid, .product-grid.cols-4, .product-grid.cols-3 { gap: 12px; }
	.card-media { height: 160px; }
	.card-body { padding: 10px 12px 12px; }
	.card-cta { padding: 0 12px 12px; }
}

/* ==========================================================================
   WOOCOMMERCE ARCHIVE GRID — shop / product category / product tag / product
   search only. See reports/admin-safety-audit.md §5-6: WooCommerce's
   woocommerce/legacy-template block renders these pages through its own
   ClassicTemplate::render_archive_product() method, which builds
   <ul class="products columns-N"><li class="product"> itself — it never
   loads this theme's woocommerce/archive-product.php or
   taxonomy-product_cat.php (confirmed dead code; left in place untouched,
   not deleted, per CHANGELOG.md 0.1.17 — a future cleanup, not this
   release). content-product.php's own card markup (.product-card,
   .card-media, etc., styled above) already renders correctly inside that
   wrapper via wc_get_template_part(); only the grid CONTAINER needed CSS.

   Scoped strictly to WordPress's own archive body classes (post-type-archive-
   product = the shop page, tax-product_cat / tax-product_tag = category/tag
   archives, search-results.woocommerce-page = product search) so this can
   never reach single-product, cart, checkout, my-account, or the homepage's
   own .product-grid rows (a completely different class, used only by the
   [itv_product_row] shortcode — see inc/shortcodes.php).
   ========================================================================== */

/* max-width/margin/padding here (rather than a separate ".container"
   selector) because templates/taxonomy-product_cat.html wraps the
   woocommerce/legacy-template block in nothing at all — no #main, no
   .container — confirmed by reading that file directly. Constraining the
   grid element itself is the only wrapper that actually exists on the
   rendered page. */
.post-type-archive-product ul.products,
.tax-product_cat ul.products,
.tax-product_tag ul.products,
.search-results.woocommerce-page ul.products {
	display: grid;
	grid-template-columns: repeat(5, minmax(0,1fr));
	gap: 16px;
	list-style: none;
	margin: 0 auto 40px;
	padding: 0 20px;
	max-width: 1380px;
	box-sizing: border-box;
	/* See the align-items:start comment above .product-grid — same fix,
	   same reason, applied to the WooCommerce archive's own grid. */
	align-items: start;
}

/* WooCommerce's own stylesheet (dequeued sitewide — see inc/enqueue.php's
   itv_store_dequeue_woocommerce_defaults()) would normally supply float-based
   li.product width rules; some setups still apply legacy inline/float rules
   to li.product regardless, so they're neutralized explicitly rather than
   assumed absent. */
.post-type-archive-product ul.products li.product,
.tax-product_cat ul.products li.product,
.tax-product_tag ul.products li.product,
.search-results.woocommerce-page ul.products li.product {
	float: none;
	width: auto;
	margin: 0;
	display: flex;
	flex-direction: column;
}

/* Card image stage — archive-specific sizing (220/190/165px), independent
   of .card-media's shared default (used by homepage rows too, left
   unchanged above so this cannot affect the homepage). */
.post-type-archive-product ul.products .card-media,
.tax-product_cat ul.products .card-media,
.tax-product_tag ul.products .card-media,
.search-results.woocommerce-page ul.products .card-media {
	height: 220px;
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
}
.post-type-archive-product ul.products .card-media img,
.tax-product_cat ul.products .card-media img,
.tax-product_tag ul.products .card-media img,
.search-results.woocommerce-page ul.products .card-media img {
	max-width: 100%;
	max-height: 100%;
	width: auto;
	height: auto;
	object-fit: contain;
	margin: auto;
}

/* Title: clamp to 2 lines so a long product name can't stretch the card. */
.post-type-archive-product ul.products .card-title,
.tax-product_cat ul.products .card-title,
.tax-product_tag ul.products .card-title,
.search-results.woocommerce-page ul.products .card-title {
	font-size: 15px;
	line-height: 1.35;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* 0.1.39: was margin-top:auto, pinning the CTA to the bottom of a card
   stretched tall by its row's tallest sibling — half of the same
   empty-space bug described above .card-body, duplicated here for the
   WooCommerce archive context. align-items:start on the grid (above) means
   cards are no longer stretched in the first place, so this rule is no
   longer needed; natural flow (the explicit per-element margins on
   .card-title/.card-specs/.card-rating/.card-cta) now does the job. */

/* Grid: 5/row wide desktop -> 4/row 1024-1279 -> 3/row 768-1023 ->
   2/row 540-767 -> 2/row down to 390 (dropping to 1 below that would waste
   horizontal space on a compact card; card width stays usable at 2/row
   even at 390px). Image stage: 220px desktop -> 190px tablet -> 165px mobile. */
@media (max-width: 1279px) {
	.post-type-archive-product ul.products,
	.tax-product_cat ul.products,
	.tax-product_tag ul.products,
	.search-results.woocommerce-page ul.products {
		grid-template-columns: repeat(4, minmax(0,1fr));
	}
}
@media (max-width: 1023px) {
	.post-type-archive-product ul.products,
	.tax-product_cat ul.products,
	.tax-product_tag ul.products,
	.search-results.woocommerce-page ul.products {
		grid-template-columns: repeat(3, minmax(0,1fr));
	}
	.post-type-archive-product ul.products .card-media,
	.tax-product_cat ul.products .card-media,
	.tax-product_tag ul.products .card-media,
	.search-results.woocommerce-page ul.products .card-media {
		height: 190px;
	}
}
@media (max-width: 767px) {
	.post-type-archive-product ul.products,
	.tax-product_cat ul.products,
	.tax-product_tag ul.products,
	.search-results.woocommerce-page ul.products {
		grid-template-columns: repeat(2, minmax(0,1fr));
		gap: 12px;
	}
	.post-type-archive-product ul.products .card-media,
	.tax-product_cat ul.products .card-media,
	.tax-product_tag ul.products .card-media,
	.search-results.woocommerce-page ul.products .card-media {
		height: 165px;
	}
}

/* Category H1 — reduced from the oversized default down to a professional
   catalog size. Targets WooCommerce's own real output for this route,
   .woocommerce-products-header__title / .page-title (confirmed live —
   woocommerce/archive-product.php's .category-intro markup is dead code
   here for the same reason the grid wrapper is, see the top of this
   section, so a selector matching that dead markup would never have
   applied on the live site). No inline style competes with this class on
   WooCommerce's own header markup, so !important isn't needed. */
.post-type-archive-product .woocommerce-products-header,
.tax-product_cat .woocommerce-products-header,
.tax-product_tag .woocommerce-products-header,
.search-results.woocommerce-page .woocommerce-products-header,
.post-type-archive-product .woocommerce-notices-wrapper,
.tax-product_cat .woocommerce-notices-wrapper,
.tax-product_tag .woocommerce-notices-wrapper,
.search-results.woocommerce-page .woocommerce-notices-wrapper {
	max-width: 1380px;
	margin-inline: auto;
	padding-inline: 20px;
	box-sizing: border-box;
}
.post-type-archive-product .woocommerce-products-header__title,
.tax-product_cat .woocommerce-products-header__title,
.tax-product_tag .woocommerce-products-header__title,
.search-results.woocommerce-page .woocommerce-products-header__title {
	font-size: clamp(28px, 3vw, 42px);
	line-height: 1.15;
}
@media (max-width: 767px) {
	.post-type-archive-product .woocommerce-products-header__title,
	.tax-product_cat .woocommerce-products-header__title,
	.tax-product_tag .woocommerce-products-header__title,
	.search-results.woocommerce-page .woocommerce-products-header__title {
		font-size: clamp(26px, 6vw, 32px);
	}
}

@media (max-width: 480px) {
	/* Stays 2/row (not 1) at phone widths — a single full-width card wastes
	   horizontal space and is unusual for a product grid; 2 narrow columns
	   with a shorter image stage reads better at 390-430px. */
	.card-media { height: 150px; }
}


/* ---- filters ---- */
.shop-layout { display: grid; grid-template-columns: 260px 1fr; gap: 32px; align-items: start; }
.filters { border: 1px solid var(--c-border); border-radius: var(--radius-card); overflow: hidden; background: #fff; }
.filters-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 16px; background: var(--c-mist); }
.filters-head h2 { font-size: 14px; margin: 0; }
.filters-head button { background: none; border: 0; font-size: 12.5px; font-weight: 700; color: var(--c-slate); cursor: pointer; }
.filter-group { border-top: 1px solid var(--c-border); }
.filter-group summary { display: flex; align-items: center; justify-content: space-between; padding: 14px 16px; font-family: var(--font-head); font-weight: 700; font-size: 13.5px; cursor: pointer; list-style: none; }
.filter-group summary::-webkit-details-marker { display: none; }
.filter-group summary .icon { width: 15px; height: 15px; transition: transform .2s ease; }
.filter-group[open] summary .icon { transform: rotate(180deg); }
.filter-body { padding: 0 16px 16px; display: flex; flex-direction: column; gap: 10px; }
.filter-check { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 13.5px; }
.filter-check label { display: flex; align-items: center; gap: 9px; }
.filter-check input { width: 16px; height: 16px; accent-color: var(--c-black); }
.filter-check .n { color: var(--c-slate); font-variant-numeric: tabular-nums; }

.shop-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 20px; }
.shop-count { font-size: 13.5px; color: var(--c-slate); }
.shop-sort { display: flex; align-items: center; gap: 18px; }
.shop-sort select { padding: 9px 12px; border: 1px solid var(--c-border); border-radius: 5px; font-size: 13.5px; font-family: var(--font-body); }
.mobile-filter-btn { display: none; }

.pagination { display: flex; justify-content: center; align-items: center; gap: 6px; margin-top: 36px; }
.pagination a, .pagination span { width: 38px; height: 38px; display: flex; align-items: center; justify-content: center; border-radius: 6px; font-family: var(--font-head); font-weight: 700; font-size: 13.5px; color: var(--c-slate); text-decoration: none; }
.pagination a:hover { background: var(--c-mist); }
.pagination .current { background: var(--c-black); color: #fff; }

.category-intro { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; margin-bottom: 26px; flex-wrap: wrap; }
.category-intro p { max-width: 62ch; color: var(--c-slate); font-size: 14.5px; margin-top: 8px; }
.subcat-chips { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 26px; }
.subcat-chips a { padding: 8px 16px; border: 1px solid var(--c-border); border-radius: var(--radius-chip); font-family: var(--font-head); font-weight: 700; font-size: 13px; text-decoration: none; color: inherit; }
.subcat-chips a[aria-current="page"] { background: var(--c-black); color: #fff; border-color: var(--c-black); }
.subcat-chips a:hover:not([aria-current="page"]) { border-color: var(--c-black); }

@media (max-width: 900px) {
	.shop-layout { grid-template-columns: 1fr; }
	/* 0.1.33: z-index raised 1000 -> 10000 (scrim 999 -> 9990) so this panel
	   still covers the header's .itv-sticky-wrap (raised to 9999 this
	   release) when open — same reasoning as .itv-mobile-menu in
	   header-v3.css. */
	.filters { position: fixed; inset: 0 0 0 auto; width: min(340px, 88vw); z-index: 10000; transform: translateX(100%); transition: transform .25s ease; border-radius: 0; overflow-y: auto; }
	.filters.is-open { transform: translateX(0); }
	.filters-scrim { position: fixed; inset: 0; background: rgba(11,11,11,.5); z-index: 9990; display: none; }
	.filters-scrim.is-open { display: block; }
	.mobile-filter-btn { display: inline-flex; }
}

/* ==========================================================================
   HOMEPAGE-ONLY SECTIONS — hero, services cross-sell, trust/USP strip.
   Lives here (not base.css) because it's only needed where itv-shop.css is
   already conditionally loaded (front page) — see inc/enqueue.php. Ported
   from previews/preview-assets/css/preview.css, which these rules were
   missing from every theme stylesheet since the Phase 4 CSS split — see
   CHANGELOG.md 0.1.3.
   ========================================================================== */

/* 0.1.37: min-height 560px -> clamp(480px, 52vw, 550px) — measured live at
   664px actual rendered height (86% of a 768px viewport) before this
   change; the flat 560px floor plus hero-inner's own padding/content was
   what pushed it that tall. align-items:center (unchanged) keeps content
   vertically centered regardless of the new height. */
.itv-hero {
	position: relative;
	background: var(--c-black);
	color: #fff;
	overflow: hidden;
	min-height: clamp(480px, 52vw, 550px);
	display: flex;
	align-items: center;
}
.itv-hero .hero-bg {
	position: absolute; inset: 0;
	width: 100%; height: 100%;
	object-fit: cover; object-position: center 30%;
	filter: brightness(0.55) saturate(1.05);
}
.itv-hero .hero-overlay {
	position: absolute; inset: 0;
	background: linear-gradient(90deg, rgba(11,11,11,.97) 0%, rgba(11,11,11,.9) 32%, rgba(11,11,11,.65) 58%, rgba(11,11,11,.45) 100%);
}
.itv-hero .container { position: relative; z-index: 2; width: 100%; }
/* Solid backdrop directly behind the headline column, on top of the photo +
   gradient. Automated contrast checkers can't reliably resolve text sitting
   over an <img> + gradient overlay (the algorithm only walks declared
   background-color, not stacked/painted-behind elements); this gives them
   — and the small number of real users on very bright hero photos — an
   unambiguous solid, opaque background for the eyebrow/heading/lede text. */
.itv-hero-inner { max-width: 680px; padding-block: 48px; position: relative; background: rgba(11,11,11,.35); }
/* 0.1.37: was clamp(32px, 4vw, 52px) — same 52px ceiling, but the 32px
   floor let the title shrink further than intended on ordinary desktop
   widths. 40px floor + slower growth (3.6vw, was 4vw) keeps it reading as
   a strong headline without needing 60-70px text. */
.itv-hero h1 { font-size: clamp(40px, 3.6vw, 52px); line-height: 1.08; margin-bottom: 16px; color: #fff; }
.itv-hero h1 mark { background: none; color: var(--c-yellow); }
.itv-hero h1 mark .itv-type.is-typing::after {
	content: "";
	display: inline-block;
	width: 3px;
	height: 0.86em;
	margin-left: 0.06em;
	vertical-align: -0.06em;
	background: var(--c-yellow);
	animation: itv-caret 1s steps(1) infinite;
}
@keyframes itv-caret {
	0%, 49% { opacity: 1; }
	50%, 100% { opacity: 0; }
}
.itv-hero p.lede { font-size: 17px; line-height: 1.6; color: rgba(255,255,255,.85); max-width: 640px; margin-bottom: 26px; }
.hero-usps { display: flex; gap: 18px; flex-wrap: wrap; margin-bottom: 24px; }
.hero-usp { display: flex; align-items: center; gap: 10px; font-size: 13.5px; }
.hero-usp .icon { color: var(--c-yellow); width: 18px; height: 18px; }
.hero-usp strong { display: block; font-family: var(--font-head); font-size: 13.5px; }
.hero-usp span { color: rgba(255,255,255,.65); font-size: 12px; }
.hero-cta { display: flex; gap: 14px; flex-wrap: wrap; }

@media (max-width: 900px) {
	.itv-hero { min-height: 480px; }
	.itv-hero-inner { max-width: 100%; padding-block: 48px; }
}
@media (max-width: 560px) {
	.hero-cta .btn, .hero-cta { width: 100%; }
	.hero-usps { gap: 16px; }
}

.services-band { display: grid; grid-template-columns: 1fr 1fr 1.1fr; gap: 16px; }
.service-tile {
	position: relative; border-radius: var(--radius-card); overflow: hidden; min-height: 220px;
	display: flex; align-items: flex-end; color: #fff; padding: 26px;
}
.service-tile img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; filter: brightness(.5); }
.service-tile .content { position: relative; z-index: 1; }
.service-tile h3 { font-size: 19px; margin-bottom: 8px; color: #fff; }
.service-tile .btn { margin-top: 14px; }
.quote-panel {
	background: var(--c-yellow); border-radius: var(--radius-card); padding: 26px;
	display: flex; flex-direction: column; justify-content: center; gap: 8px; color: var(--c-black);
}
.quote-panel h3 { font-size: 20px; }
.quote-panel p { font-size: 14px; margin-bottom: 6px; color: rgba(11,11,11,.75); }
.quote-panel .btn { margin-top: 8px; align-self: flex-start; }

@media (max-width: 1024px) { .services-band { grid-template-columns: 1fr 1fr; } .quote-panel { grid-column: 1 / -1; } }
@media (max-width: 640px) { .services-band { grid-template-columns: 1fr; } }

.usp-strip { display: grid; grid-template-columns: repeat(5, 1fr); gap: 0; }
.usp-item {
	display: flex; align-items: center; gap: 12px; padding: 18px clamp(12px, 2vw, 20px);
	border-right: 1px solid var(--c-border-dark);
}
.usp-item:last-child { border-right: 0; }
.usp-item .icon { color: var(--c-yellow); width: 30px; height: 30px; flex: 0 0 auto; }
.usp-item strong { display: block; font-family: var(--font-head); font-size: 13.5px; }
.usp-item span { font-size: 12px; color: rgba(255,255,255,.6); }

@media (max-width: 1024px) { .usp-strip { grid-template-columns: repeat(3, 1fr); } .usp-item:nth-child(3) { border-right: 0; } .usp-item { border-bottom: 1px solid var(--c-border-dark); } }
@media (max-width: 640px) { .usp-strip { grid-template-columns: repeat(2, 1fr); } .usp-item:nth-child(2n) { border-right: 0; } }

/* ---- WooCommerce archive pagination ----
   Confirmed live markup, re-verified 0.1.21 directly against the actual
   page-load network response (not a guess): <nav class="woocommerce-pagination">
   <ul class="page-numbers"><li><span class="page-numbers current">1</span></li>
   <li><a class="page-numbers" href="...">2</a></li>...
   <li><a class="next page-numbers" href="...">→</a></li></ul></nav>
   This selector list has matched that exact markup since 0.1.18 and still
   does — the selectors were never the problem.

   0.1.21 ROOT CAUSE, proven with hard evidence, not inferred: fetching the
   live category page's actual enqueued CSS URL two ways gave two different
   results. (1) A request carrying a cache-busting query param + cache:
   'reload', bypassing both the browser's disk cache and Hostinger's hCDN
   edge (confirmed via x-hcdn-cache-status: MISS/BYPASS), returned this exact
   rule set, correct and present. (2) The real, unmodified page-load request
   to the SAME URL — captured directly from the network log, not re-fetched —
   returned an entirely different, much older stylesheet body that predates
   the 0.1.18 release and contains no nav.woocommerce-pagination rule at
   all (only the older, unrelated dead .pagination class below). That is
   direct proof the origin has always had the correct file; a downstream
   cache (Hostinger's hCDN edge, and/or long-lived browser caching per
   Cache-Control: public, max-age=604800) has been serving a stale copy of
   this specific asset URL since before 0.1.18, and never re-validated it
   against the origin since. 0.1.20's fix (relocating this block within the
   file, unchanged content) did not change the asset's served URL/hash, so
   it could not and did not bust that cache — this is why the previous fix
   was invisible despite being correct.

   REAL 0.1.21 fix: shop.css was renamed to shop-v2.css (see inc/enqueue.php)
   specifically to force a brand-new URL that no browser or edge cache has
   ever stored anything under, guaranteeing a fresh fetch regardless of any
   cache TTL. No selector changed. !important was NOT added: the previous
   analysis already proved this isn't a specificity/cascade conflict (grepped
   every other theme CSS file for ul/li/page-numbers/pagination rules —
   only the unrelated, differently-named .pagination class exists, and nothing
   else touches this markup), so !important would not achieve anything here.
   A LiteSpeed Cache + hCDN purge after every future CSS deploy is still the
   robust long-term fix on the hosting side — this rename only guarantees
   *this* release becomes visible without depending on that. */
.post-type-archive-product nav.woocommerce-pagination,
.tax-product_cat nav.woocommerce-pagination,
.tax-product_tag nav.woocommerce-pagination,
.search-results.woocommerce-page nav.woocommerce-pagination {
	margin: 0;
	padding: 0;
	border: 0;
	text-align: center;
}
.post-type-archive-product nav.woocommerce-pagination ul,
.tax-product_cat nav.woocommerce-pagination ul,
.tax-product_tag nav.woocommerce-pagination ul,
.search-results.woocommerce-page nav.woocommerce-pagination ul {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 8px;
	list-style: none;
	margin: 32px auto 0;
	padding: 0;
	border: 0;
	width: 100%;
}
.post-type-archive-product nav.woocommerce-pagination ul li,
.tax-product_cat nav.woocommerce-pagination ul li,
.tax-product_tag nav.woocommerce-pagination ul li,
.search-results.woocommerce-page nav.woocommerce-pagination ul li {
	list-style: none;
	display: block;
	margin: 0;
	padding: 0;
	border: 0;
	float: none;
}
.post-type-archive-product nav.woocommerce-pagination ul li a,
.post-type-archive-product nav.woocommerce-pagination ul li span,
.tax-product_cat nav.woocommerce-pagination ul li a,
.tax-product_cat nav.woocommerce-pagination ul li span,
.tax-product_tag nav.woocommerce-pagination ul li a,
.tax-product_tag nav.woocommerce-pagination ul li span,
.search-results.woocommerce-page nav.woocommerce-pagination ul li a,
.search-results.woocommerce-page nav.woocommerce-pagination ul li span {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 42px;
	height: 42px;
	border: 1px solid var(--c-border);
	border-radius: 8px;
	background: #fff;
	color: var(--c-black);
	font-family: var(--font-head);
	font-weight: 700;
	font-size: 14px;
	text-decoration: none;
	line-height: 1;
}
.post-type-archive-product nav.woocommerce-pagination ul li a:hover,
.post-type-archive-product nav.woocommerce-pagination ul li a:focus-visible,
.tax-product_cat nav.woocommerce-pagination ul li a:hover,
.tax-product_cat nav.woocommerce-pagination ul li a:focus-visible,
.tax-product_tag nav.woocommerce-pagination ul li a:hover,
.tax-product_tag nav.woocommerce-pagination ul li a:focus-visible,
.search-results.woocommerce-page nav.woocommerce-pagination ul li a:hover,
.search-results.woocommerce-page nav.woocommerce-pagination ul li a:focus-visible {
	border-color: var(--c-yellow);
	background: var(--c-yellow);
	color: var(--c-black);
}
.post-type-archive-product nav.woocommerce-pagination ul li a:focus-visible,
.tax-product_cat nav.woocommerce-pagination ul li a:focus-visible,
.tax-product_tag nav.woocommerce-pagination ul li a:focus-visible,
.search-results.woocommerce-page nav.woocommerce-pagination ul li a:focus-visible {
	outline: 3px solid var(--c-black);
	outline-offset: 2px;
}
.post-type-archive-product nav.woocommerce-pagination ul li span.current,
.tax-product_cat nav.woocommerce-pagination ul li span.current,
.tax-product_tag nav.woocommerce-pagination ul li span.current,
.search-results.woocommerce-page nav.woocommerce-pagination ul li span.current {
	background: var(--c-yellow);
	border-color: var(--c-yellow);
	color: var(--c-black);
	font-weight: 800;
}
@media (max-width: 767px) {
	.post-type-archive-product nav.woocommerce-pagination ul li a,
	.post-type-archive-product nav.woocommerce-pagination ul li span,
	.tax-product_cat nav.woocommerce-pagination ul li a,
	.tax-product_cat nav.woocommerce-pagination ul li span,
	.tax-product_tag nav.woocommerce-pagination ul li a,
	.tax-product_tag nav.woocommerce-pagination ul li span,
	.search-results.woocommerce-page nav.woocommerce-pagination ul li a,
	.search-results.woocommerce-page nav.woocommerce-pagination ul li span {
		width: 38px;
		height: 38px;
		font-size: 13px;
	}
}

/* ==========================================================================
   0.1.39 — DESKTOP DENSITY (>=1024px only)
   Approved "NEW 55-60%" tier — replaces 0.1.38's "COMPACT 75-80%" values
   below (same block, new content). See previews/store-55-density-preview.html
   (approved) and the equivalent note in base-v3.css for the full rationale.
   Everything above this block (0.1.37 values) is the unconditional
   baseline, serving 768-1023px tablet sizing; existing
   @media(max-width:...) blocks above continue to govern narrower widths
   untouched — mobile/tablet are explicitly excluded from this density tier
   per instruction. This is the ONE place homepage hero/heading/card/
   service/trust-strip dimensions get a >=1024px override in this file —
   extend this block for future desktop density changes rather than adding
   a second, competing @media(min-width:1024px) block.

   Scope change from 0.1.38: the homepage's .card-media and the shop/
   category archive's own .card-media are now BOTH set to 120px, no longer
   intentionally separate — this round's approved spec explicitly asks for
   "the SAME compact card system" across the homepage product rows, the
   shop/category archive, and Related Products/You May Also Like, so the
   previous 162px/220px split is retired at this density tier. Product
   gallery and pagination are not touched by this block. */
@media (min-width: 1024px) {
	.itv-hero { min-height: 320px; }
	.itv-hero-inner { max-width: 520px; padding-block: 22px; }
	.itv-hero .itv-eyebrow { font-size: 9.5px; }
	.itv-hero h1 { font-size: clamp(28px, 1.9vw, 34px); line-height: 1.08; margin-bottom: 8px; }
	.itv-hero p.lede { font-size: 13.5px; line-height: 1.5; max-width: 500px; margin-bottom: 12px; }
	.hero-usps { gap: 10px; margin-bottom: 12px; }
	.hero-usp { gap: 6px; }
	.hero-usp .icon { width: 15px; height: 15px; }
	.hero-usp strong { font-size: 10.5px; }
	.hero-usp span { font-size: 9.5px; }

	/* Both H2 code paths (see the 0.1.37 comment above .itv-row-head h2)
	   converge on the same formula here too, so "Shop by Category" and
	   "Best-Selling Business Hardware" (etc.) stay identical at this
	   density as well — no leftover heading can win by accident. */
	.itv-row-head h2,
	.itv-section--tight > .container > h2 {
		font-size: clamp(20px, 1.35vw, 24px);
	}

	.cat-tile { min-height: 100px; padding: 9px 8px; gap: 5px; }
	.cat-tile .icon { width: 22px; height: 22px; }
	.cat-tile span { font-size: 11.5px; }

	/* Homepage product rows: same compact card system as the shop/archive
	   grid further down, including the same 5-across-desktop /
	   6-across-1600px+ column count — see item 27 of the approved spec
	   ("Use the same compact product card system... 5 at 1366px, 6 if
	   visually good at wider desktop"). */
	.product-grid, .product-grid.cols-4 { grid-template-columns: repeat(5, minmax(0,1fr)); gap: 12px; }

	.card-media { height: 120px; }
	.card-wish { width: 29px; height: 29px; }
	.card-wish .icon { width: 13px; height: 13px; }
	.card-body { padding: 9px; }
	.card-title { font-size: 12px; line-height: 1.3; margin-bottom: 5px; }
	.card-specs { font-size: 10px; margin-bottom: 5px; }
	.card-rating { font-size: 10.5px; margin-bottom: 6px; }
	/* Scoped to the stock/config pill only (.badge-stock-in/.badge-stock-out,
	   rendered by itv_store_stock_badge()) — base-v3.css's shared .badge
	   class is used for other badge types too (promo/new corner badges)
	   that aren't part of this round's approved card spec, so the size
	   reduction is scoped to the card-footer context rather than applied
	   to .badge globally. */
	.card-footer .badge { font-size: 9.5px; padding: 2px 6px; }
	.price-tag { font-size: 13.5px; }
	.card-cta { padding: 8px 9px 9px; margin-top: 0; }
	.card-cta .btn { min-height: 33px; padding: 0 10px; font-size: 11px; }

	/* Explicit height (not min-height) on both tile types — .services-band
	   is a CSS grid, so without this the three items stretch to match
	   whichever has the tallest natural content. 230px here is exact, per
	   the approved density spec (was 270px in 0.1.38). */
	.service-tile, .quote-panel { height: 230px; }
	.service-tile { padding: 16px; }
	.service-tile h3 { font-size: 19.5px; }
	.service-tile p { font-size: 12px; }
	.service-tile .btn { min-height: 33px; padding: 0 14px; font-size: 11px; }
	.quote-panel { padding: 16px; }
	.quote-panel h3 { font-size: 19px; }
	.quote-panel p { font-size: 12.5px; }
	.quote-panel .btn { min-height: 35px; padding: 0 15px; font-size: 11.5px; }

	.usp-item { padding: 8px 12px; gap: 6px; }
	.usp-item .icon { width: 17px; height: 17px; }
	.usp-item strong { font-size: 10.5px; }
	.usp-item span { font-size: 9.5px; }

	/* ---- shop / category archive: compact container + card system,
	   matching the homepage rules above exactly (image stage, padding,
	   title, price, CTA, wishlist) plus the archive-specific container
	   width and page title. ---- */
	.post-type-archive-product ul.products,
	.tax-product_cat ul.products,
	.tax-product_tag ul.products,
	.search-results.woocommerce-page ul.products,
	.post-type-archive-product .woocommerce-products-header,
	.tax-product_cat .woocommerce-products-header,
	.tax-product_tag .woocommerce-products-header,
	.search-results.woocommerce-page .woocommerce-products-header,
	.post-type-archive-product .woocommerce-notices-wrapper,
	.tax-product_cat .woocommerce-notices-wrapper,
	.tax-product_tag .woocommerce-notices-wrapper,
	.search-results.woocommerce-page .woocommerce-notices-wrapper {
		max-width: 1220px;
	}
	.post-type-archive-product ul.products,
	.tax-product_cat ul.products,
	.tax-product_tag ul.products,
	.search-results.woocommerce-page ul.products {
		gap: 12px;
	}
	.post-type-archive-product .woocommerce-products-header__title,
	.tax-product_cat .woocommerce-products-header__title,
	.tax-product_tag .woocommerce-products-header__title,
	.search-results.woocommerce-page .woocommerce-products-header__title {
		font-size: 28px;
		margin-block: 22px 0;
	}
	.post-type-archive-product ul.products .card-media,
	.tax-product_cat ul.products .card-media,
	.tax-product_tag ul.products .card-media,
	.search-results.woocommerce-page ul.products .card-media {
		height: 120px;
	}
	.post-type-archive-product ul.products .card-title,
	.tax-product_cat ul.products .card-title,
	.tax-product_tag ul.products .card-title,
	.search-results.woocommerce-page ul.products .card-title {
		font-size: 12px;
		line-height: 1.3;
	}
}

/* Wide desktop only: 6 columns where the approved spec allows it ("6 across
   preferred" at >=1600px) — a genuinely new breakpoint, not a second
   competing >=1024px block, so it coexists with the block above rather
   than replacing any of it. Applies to both the homepage product rows and
   the WooCommerce shop/category archive grid, per items 8 and 27 of the
   approved spec. A lone product (see .post-type-archive-product ul.products
   li.product above, float:none/width:auto/display:flex) still only
   occupies one of the 6 fixed tracks here, same non-stretch guarantee as
   the 5-column layout below 1600px. */
@media (min-width: 1600px) {
	.product-grid, .product-grid.cols-4,
	.post-type-archive-product ul.products,
	.tax-product_cat ul.products,
	.tax-product_tag ul.products,
	.search-results.woocommerce-page ul.products {
		grid-template-columns: repeat(6, minmax(0,1fr));
	}
}
