/**
 * Page-specific styles.
 */

/* --- Page hero --- */

.page-hero {
	position: relative;
	display: grid;
	isolation: isolate;
	overflow: hidden;
}

.page-hero--tall  { min-height: clamp(360px, 42vw, 560px); }
.page-hero--short { min-height: clamp(240px, 26vw, 360px); }

/*
 * Bug fix (whole-site sweep, same class as components.css's
 * .product-card__media .product-card__img fix, PLUS a second bug the
 * specificity fix alone does not solve — see below): WooCommerce's own
 * stylesheet ships `.woocommerce img, .woocommerce-page img { height: auto }`
 * on every WC-flagged template — every taxonomy-product_cat.php and
 * single-product.php page, i.e. every collection and product page on this
 * site. That compound selector (one class + one type) is more specific
 * than a lone `.page-hero__img` class, so it silently won the cascade there.
 * Qualifying the selector with its parent (two classes, below) restores the
 * specificity this needs to win, with no !important — necessary, but on its
 * own NOT sufficient: verified live (Playwright, computed styles) that
 * raising specificity alone left the rendered height unchanged, because
 * `.page-hero` only ever declared `min-height` (never `height`), so its own
 * block size was never definite, and a percentage `height` on a descendant
 * of a non-definite-height box resolves as `auto` regardless of which
 * cascade rule wins (CSS 2.1 §10.5) — this <img> was still sizing itself to
 * its own intrinsic aspect ratio at the resolved width either way, growing
 * .page-hero's own auto/grid-content-based height right past the intended
 * `--tall`/`--short` clamp() (a floor, not a ceiling) in the process: a
 * 1350x900 collection banner rendered 960px tall against a 360px cap.
 * Taking this layer (and the decorative gradient below it) out of normal
 * flow with `position: absolute; inset: 0` removes it from that circular
 * content-based sizing altogether, so `.page-hero`'s own height resolves
 * from its one remaining in-flow child, `.page-hero__inner` (copy block:
 * padding + a line or two of text, well under the clamp floor) — which
 * makes `.page-hero` itself definite-height, sized to the clamp(), for the
 * first time. Only then does this rule's `height: 100%` have a definite
 * containing block to resolve against, and only then does raising its
 * specificity over WooCommerce's `height: auto` change anything visible.
 * `.page-hero__inner` is deliberately left as a grid item (not absolute):
 * unusually long title/subtitle copy can still grow the hero past the
 * clamp() floor instead of being clipped.
 */
.page-hero .page-hero__img {
	position: absolute;
	inset: 0;
	width: 100%; height: 100%;
	object-fit: cover;
	z-index: -2;
}

.page-hero__overlay {
	position: absolute;
	inset: 0;
	z-index: -1;
	background: linear-gradient(to top, rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0) 55%);
}

/*
 * Slideshow variant (Company page): the slides share one clock, set inline
 * by template-parts/hero/page-hero.php (--count, --cycle), and each takes
 * its --i slot in turn with the immersive hero's fade, hold and slow
 * push-in. The keyframes (page-hero-slide, page-hero-slide-first) are
 * generated for the count by inc/hero-motion.php and added inline after
 * this sheet. No intro: slide 1 starts visible. A near-black base shows for
 * a moment on every crossfade, as on the home hero.
 */
.page-hero--slides { background: #14161A; }

.page-hero__slide {
	position: absolute;
	inset: 0;
	z-index: -2;
	animation: page-hero-slide var(--cycle, 42s) linear infinite both;
	animation-delay: calc(var(--i, 0) * var(--cycle, 42s) / var(--count, 6));
}

.page-hero__slide--first { animation-name: page-hero-slide-first; }

/* The slide owns the img's position; the img fills it and is pushed in by the slide's transform. */
.page-hero .page-hero__slide .page-hero__img { position: absolute; inset: 0; z-index: auto; }

/* Stronger scrim than the single-photo hero: these are busy photographs. */
.page-hero--slides .page-hero__overlay {
	background: linear-gradient(to top, rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.12) 60%, rgba(0, 0, 0, 0.18) 100%);
}

@media (prefers-reduced-motion: reduce) {
	.page-hero__slide { animation: none; opacity: 0; }
	.page-hero__slide--first { opacity: 1; }
}

.page-hero__inner {
	grid-area: 1 / 1;
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: var(--sp-8);
	padding-block: var(--sp-8);
}

.page-hero__eyebrow {
	margin-bottom: var(--sp-2);
	font-size: var(--fs-xs);
	letter-spacing: var(--tracking-wider);
	text-transform: uppercase;
	color: var(--ink-invert);
}

.page-hero__title {
	margin-bottom: var(--sp-2);
	/*
	 * Pinned explicitly (not left to the base h1-h4 reset) because
	 * template-parts/hero/page-hero.php can render this element as a <p>
	 * (see $title_tag) to avoid a second <h1> on leaf collection pages.
	 * Without these two, a <p> would pick up the body's normal weight and
	 * line-height instead of the heading reset, changing the render.
	 */
	font-weight: 700;
	line-height: var(--lh-tight);
	font-size: clamp(1.5rem, 3.4vw, 2.5rem);
	letter-spacing: var(--tracking-wide);
	text-transform: uppercase;
	color: var(--ink-invert);
	text-shadow: 0 2px 12px rgba(0, 0, 0, 0.35);
}

.page-hero__subtitle {
	margin: 0;
	font-family: var(--font-serif);
	font-style: italic;
	font-size: var(--fs-lg);
	color: var(--ink-invert);
}

.page-hero__mark { align-self: flex-end; opacity: 0.9; }

/* --- Home feature cards --- */

.home-features { margin-bottom: var(--sp-16); }
.home-features--center { max-width: 760px; margin-inline: auto; }

.feature-card__title {
	margin-bottom: var(--sp-4);
	font-size: var(--fs-base);
	font-weight: 700;
	letter-spacing: var(--tracking-wide);
	text-transform: uppercase;
}

.feature-card__body { position: relative; display: grid; }

.feature-card__media { grid-area: 1 / 1; }

.feature-card__img {
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
}

.feature-card__panel {
	grid-area: 1 / 1;
	align-self: start;
	width: min(72%, 440px);
	padding: var(--sp-4) var(--sp-5);
	background: rgba(255, 255, 255, 0.95);
}

/*
 * Both rules resolve to the same `justify-self: start` on purpose — not a
 * copy-paste bug. Checked against docs/design/01-home.jpg: the copy panel
 * sits top-left on BOTH the "left" and "right" feature-card variants: only
 * the photo's crop/subject changes between them, not the panel's corner.
 * --right exists as its own selector so a future design change to one
 * variant's panel position has an obvious, already-there place to land
 * without guessing whether omitting it was intentional.
 */
.feature-card--left  .feature-card__panel { justify-self: start; }
.feature-card--right .feature-card__panel { justify-self: start; }

.feature-card__text {
	margin-bottom: var(--sp-3);
	font-size: var(--fs-xs);
	line-height: 1.5;
	color: var(--ink-muted);
}

/*
 * Keep the photos in a two-up row aligned to a common top and bottom edge.
 * Each .feature-card is a block whose height is title + body, and the titles
 * are not the same number of lines ("High-Performance Waterproof / Laminate
 * Flooring" wraps to two, "Waterproof StoneCoreX LVP Flooring" to one), so
 * the second card's photo started roughly one line-height higher than the
 * first's. Subgrid puts every card's title in the row's first track and every
 * card's body in the second, so the tallest title sets one shared height and
 * the photos line up. Scoped to the 2-up rows: .home-features--center holds a
 * single card with nothing to align against.
 */
@media (min-width: 768px) {
	.home-features.grid--2 { grid-template-rows: auto 1fr; }

	.home-features.grid--2 .feature-card {
		display: grid;
		grid-row: span 2;
		grid-template-rows: subgrid;
	}
}

@media (max-width: 767px) {
	/*
	 * Bug fix (post-review): .page-hero__inner keeps the desktop
	 * `justify-content: space-between` when it switches to a column flex
	 * direction here. In a column flex container that property governs the
	 * vertical axis, so with a single copy block it collapsed to the TOP of
	 * the hero — landing white text on the fully-transparent top edge of
	 * .page-hero__overlay's gradient (dark only at the bottom), making the
	 * title/subtitle unreadable. Pin it to the bottom, where the gradient
	 * is dark, matching the desktop `align-items: flex-end` intent.
	 */
	.page-hero__inner { flex-direction: column; justify-content: flex-end; align-items: flex-start; }
	.page-hero__mark { align-self: flex-start; }

	/*
	 * Bug fix (post-review): the desktop overlap (.feature-card__body as a
	 * grid with media + panel both on grid-area: 1 / 1) was still active
	 * here, and only the panel's width changed to 100%. A full-width panel
	 * in the same grid cell as the photo sits directly on top of it —
	 * translucent background over image, and copy taller than the photo
	 * spills past its edges. Below this breakpoint the card should stack
	 * instead of overlap; the desktop grid overlap is untouched above 767px.
	 */
	.feature-card__body { display: flex; flex-direction: column; gap: var(--sp-4); }
	.feature-card__panel { width: 100%; }
}

/* --- Taxonomy pages --- */

/*
 * Wider than it was, to sit closer to the grid's edges (Alan, 2026-10-20),
 * with the type grown to match so a line stays near 70 characters: 36em
 * at 19px is ~680px. Full grid width would need text big enough to push
 * the products well down the page.
 */
.tax-intro {
	max-width: 36em;
	margin-inline: auto;
	margin-bottom: var(--sp-12);
	font-size: clamp(16px, 1.35vw, 19px);
	line-height: 1.6;
	text-align: center;
	color: var(--ink-muted);
}

/*
 * With the "Natural Wood" mark present the intro stops being a centred
 * block and becomes a two-column row — mark left, copy left-aligned beside
 * it — as in docs/design/04-engineered-hardwood-landing.jpg. The copy needs
 * more room than the centred variant's 68ch once it no longer has the full
 * column to itself, hence the wider max-width.
 */
.tax-intro--marked {
	display: grid;
	grid-template-columns: 7.5rem minmax(0, 1fr);
	gap: var(--sp-6);
	align-items: start;
	max-width: 80ch;
	font-size: var(--fs-sm);
	text-align: left;
}

/* Below the collection cards (engineered hardwood) it needs room above, too. */
.tax-intro--after { margin-top: var(--sp-16); }

.tax-intro__mark-img {
	display: block;
	width: 100%;
	height: auto;
}

@media (max-width: 640px) {
	/*
	 * Stacking keeps the mark from squeezing the paragraph to a few words
	 * per line on a phone. It stays above the copy, matching reading order.
	 */
	.tax-intro--marked {
		grid-template-columns: minmax(0, 1fr);
		justify-items: center;
		text-align: center;
	}

	.tax-intro__mark { max-width: 7.5rem; }
}

.tax-empty { text-align: center; color: var(--ink-subtle); }

.collections-stack { display: grid; gap: var(--sp-12); }

.group-landing__grid { margin-bottom: var(--sp-16); }

/* Centered like the collection grids, but at this page's six columns. */
@media (min-width: 1200px) {
	.group-landing__grid.grid--centered { --cols: 6; }
}

/* --- Collection page --- */

/*
 * collection-grid.php's heading is visible by default (styled in
 * components.css) — the product page (single-product.php) shows it as
 * designed, per docs/design/05-single-product.jpg. collection.php is the
 * one caller that opts out: its own h1 already names the collection, and
 * the design (docs/design/04-casablanca-collection.jpg) has no second
 * visible heading between the intro copy and the grid, so it passes
 * 'heading_hidden' => true and collection-grid.php adds this modifier
 * class. Mirrors base.css's .screen-reader-text utility rather than
 * reusing that class directly — collection-grid.php's markup isn't ours
 * to add a class to.
 */
.collection-grid__heading--hidden {
	position: absolute;
	width: 1px; height: 1px;
	margin: -1px; padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
	border: 0;
}

.collection-lockup { padding-block: var(--sp-8) var(--sp-4); text-align: center; }

.collection-lockup__title {
	margin-bottom: var(--sp-1);
	font-size: var(--fs-2xl);
	letter-spacing: var(--tracking-wide);
	text-transform: uppercase;
}

.collection-lockup__title--logo { margin-bottom: 0; }

.collection-lockup__logo {
	display: block;
	width: min(100%, 640px);
	height: auto;
	margin-inline: auto;
}

.collection-lockup__sub {
	margin: 0;
	font-size: var(--fs-sm);
	font-weight: 700;
	letter-spacing: var(--tracking-wide);
	color: var(--ink-muted);
}

/* --- Single product --- */

.product-main__title {
	margin-bottom: var(--sp-3);
	font-size: var(--fs-xl);
	font-weight: 400;
	text-align: center;
	color: var(--brand-navy);
}

.product-main__desc {
	margin-bottom: var(--sp-6);
	font-size: var(--fs-sm);
	color: var(--ink-muted);
}

.product-gallery__main { background: var(--surface-alt); }
.product-gallery__img { width: 100%; height: auto; }

.product-gallery__thumbs {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: var(--sp-2);
	margin: var(--sp-2) 0 0;
	padding: 0;
	list-style: none;
}

.product-gallery__thumb {
	display: block;
	width: 100%;
	padding: 0;
	border: 1px solid var(--rule);
	background: none;
	cursor: pointer;
	transition: border-color var(--transition);
}

.product-gallery__thumb.is-active,
.product-gallery__thumb:hover { border-color: var(--brand-navy); }

/*
 * Spec sizing. This block used to be --fs-xs (11px), but that is not what
 * reached the screen: simple-flooring's own stylesheet sets
 * .sf-product-specs__label / __value to 0.875em, so 11 x 0.875 rendered the
 * specs at 9.625px — smaller than the 13px description directly above them,
 * and smaller than the token file's own annotations, which call --fs-xs the
 * spec LABEL size and --fs-sm the spec VALUE size. Neither number was
 * reaching the page.
 *
 * Measured against page 05 of the 2026V1 design file, the spec text and the
 * description are the same size there (15px and ~15px of ink height), so
 * --fs-sm for both is the design's intent, not a preference.
 *
 * The label and value are set explicitly rather than left to inherit. That
 * ends the 0.875em compounding, so the number in this file is the number on
 * the screen — otherwise every future change to this block has to be
 * divided by 0.875 to predict the result.
 */
.spec-table { margin-bottom: var(--sp-6); font-size: var(--fs-sm); }

.spec-table .sf-product-specs__label,
.spec-table .sf-product-specs__value { font-size: var(--fs-sm); }

.spec-table__extra {
	display: grid;
	grid-template-columns: max-content 1fr;
	gap: var(--sp-1) var(--sp-4);
	margin: var(--sp-4) 0 0;
}

.spec-table__extra dt {
	font-style: italic;
	letter-spacing: var(--tracking-wide);
	text-transform: uppercase;
	color: var(--ink-subtle);
}

.spec-table__extra dd { margin: 0; font-weight: 700; }

.warranty { display: flex; gap: var(--sp-4); align-items: flex-start; }

.warranty__badge {
	flex: 0 0 64px;
	display: grid;
	place-items: center;
	aspect-ratio: 1;
	padding: var(--sp-2);
	border-radius: 50%;
	background: var(--accent-bronze);
	font-size: 0.5rem;
	font-weight: 700;
	line-height: 1.1;
	text-align: center;
	color: var(--ink-invert);
}

.warranty__list { margin: 0 0 var(--sp-2); padding-left: var(--sp-5); }
/*
 * The warranty block sits immediately under the spec table, and the design
 * draws its bullets at the same size as the spec values (12-16px ink height
 * against the specs' 12-15px). Leaving these at --fs-xs while the specs
 * moved to --fs-sm would have made the warranty the smallest thing on the
 * page for no reason.
 *
 * The note stays deliberately smaller — it is fine print in the design too,
 * at roughly 83% of the bullets. --fs-xs is that ratio, and replaces a
 * hardcoded 0.625rem that sat outside the type scale.
 */
.warranty__list li { font-size: var(--fs-sm); font-weight: 700; }
.warranty__note { margin: 0; font-size: var(--fs-xs); color: var(--ink-subtle); }

/*
 * Color variation guide. Both of Alston's references lay the planks side by
 * side as one wide strip, split by thin white lines, not as a grid of tiles.
 * Each plank is cropped tall and narrow (object-fit) so a strip of 4 and a
 * strip of 10 both read as boards.
 */
.plank-guide {
	margin-top: var(--sp-8);
	padding-top: var(--sp-6);
	border-top: 1px solid var(--rule);
}

.plank-guide__heading {
	margin-bottom: var(--sp-2);
	font-size: var(--fs-base);
	font-weight: 400;
	letter-spacing: var(--tracking-wide);
	text-transform: uppercase;
	color: var(--ink-muted);
}

.plank-guide__text {
	margin: 0 0 var(--sp-4);
	font-size: var(--fs-sm);
	color: var(--ink-muted);
}

.plank-guide__strip,
.plank-guide__large {
	display: flex;
	gap: 3px;
	background: var(--surface);
}

.plank-guide__strip {
	position: relative;
	width: 100%;
	aspect-ratio: 5 / 2;
	min-height: 0;
	overflow: hidden;
	padding: 0;
	border: 0;
	cursor: zoom-in;
}

/*
 * Two classes on purpose: WooCommerce's `.woocommerce img { height: auto }`
 * outranks a lone class on product pages, and with height: auto each tall
 * plank photo stretches the 5:2 strip to its own proportions.
 */
.plank-guide .plank-guide__plank {
	flex: 1 1 0;
	width: 0;
	height: 100%;
	object-fit: cover;
}

.plank-guide__zoom {
	position: absolute;
	right: var(--sp-2);
	bottom: var(--sp-2);
	padding: var(--sp-1) var(--sp-2);
	background: rgb(0 0 0 / 0.6);
	font-size: var(--fs-xs);
	letter-spacing: var(--tracking-wide);
	text-transform: uppercase;
	color: var(--ink-invert);
	opacity: 0;
	transition: opacity var(--transition);
}

.plank-guide__strip:hover .plank-guide__zoom,
.plank-guide__strip:focus-visible .plank-guide__zoom { opacity: 1; }

/* Touch screens have no hover, so the hint stays on. */
@media (hover: none) {
	.plank-guide__zoom { opacity: 1; }
}

html:has(.plank-guide__dialog[open]) { overflow: hidden; }

.plank-guide__dialog {
	width: min(92vw, 1200px);
	max-height: 90dvh;
	padding: 0;
	border: 0;
	background: var(--surface);
	overflow: visible;
}

.plank-guide__dialog::backdrop { background: rgb(0 0 0 / 0.75); }

.plank-guide__large { height: min(80dvh, 640px); }

.plank-guide__close {
	position: absolute;
	top: calc(var(--sp-8) * -1.25);
	right: 0;
	padding: 0 var(--sp-2);
	border: 0;
	background: none;
	font-size: 2rem;
	line-height: 1;
	color: var(--ink-invert);
	cursor: pointer;
}

/*
 * On phones, ten planks across 92vw would be slivers. Give each a usable
 * width and let the row scroll sideways, and bring the × inside the box
 * where a short screen can't push it off the top.
 */
@media (max-width: 767px) {
	.plank-guide__large { overflow-x: auto; }
	.plank-guide .plank-guide__large .plank-guide__plank { flex: 0 0 22vw; }

	.plank-guide__close {
		z-index: 1;
		top: var(--sp-2);
		right: var(--sp-2);
		background: rgb(0 0 0 / 0.6);
	}
}

.product-extras__heading {
	margin-bottom: var(--sp-4);
	font-size: var(--fs-base);
	letter-spacing: var(--tracking-wide);
	text-transform: uppercase;
}

.product-extras { max-width: 72ch; }
.product-extras__text { font-size: var(--fs-sm); color: var(--ink-muted); }

@media (max-width: 767px) {
	.spec-table__extra { grid-template-columns: 1fr; }
	.spec-table__extra dd { margin-bottom: var(--sp-2); }

	/*
	 * The simple-flooring plugin lays sf-product-specs--cols-2 out with
	 * CSS multi-column (column-count: 2) and each row internally as a
	 * 35%/65% grid. Grid items don't shrink below their content's
	 * intrinsic width by default, so at the ~155px column width this
	 * produces on a 375px screen, a label like "Hardness/Janka" overflows
	 * into its value cell instead of wrapping — e.g. "Hardness/Jal360"
	 * observed in testing. This is real overlapping, illegible text, not
	 * just tight spacing. Forcing a single CSS column at mobile gives
	 * every row the full container width and removes the overlap; the
	 * plugin file is out of theme scope, so the fix targets its own
	 * class names from here.
	 */
	.spec-table .sf-product-specs--cols-2 .sf-product-specs__table {
		column-count: 1;
	}
}

/* --- Generic page (page.php) --- */

/*
 * Bare page content from the_content() has no wrapper width of its own, so
 * on wrap--wide-adjacent pages a single line of body copy runs the full
 * ~1200px measure — unreadable line length, not merely "responsive". This
 * caps it at a comfortable prose width and applies the same muted body
 * color used everywhere else (product descriptions, term descriptions),
 * plus spacing for headings/lists an editor is free to add in the block
 * editor.
 */
.entry__content {
	max-width: 68ch;
	margin-inline: auto;
	color: var(--ink-muted);
}

.entry__content > :last-child { margin-bottom: 0; }

.entry__content h2,
.entry__content h3,
.entry__content h4 {
	margin-top: var(--sp-8);
	color: var(--ink);
}

.entry__content ul,
.entry__content ol {
	color: var(--ink-muted);
}

/* --- 404 --- */

.error-404 { text-align: center; }
.error-404__text { max-width: 52ch; margin-inline: auto; color: var(--ink-muted); }
.error-404__actions { margin-top: var(--sp-6); }

/*
 * Bug fix (whole-site sweep): .page-hero's only backdrop below the optional
 * <img> is .page-hero__overlay, a gradient that is fully transparent for
 * roughly its top half (see the linear-gradient stop above, under "Page
 * hero"). When a page has no featured image — true today for 6 of the 8
 * real pages the new page.php serves (Visualizer, Support, Photo Gallery,
 * Contact, Rewards, Retailers all have no _thumbnail_id set; only Company
 * does) — .page-hero__img never renders, so .page-hero__title/__subtitle
 * (white, sized for sitting on photography) are left on the surrounding
 * section/body background, which is plain white. White-on-white: unreadable
 * at every width, not just mobile. A solid fallback here paints behind the
 * image (when present, the image still fully covers it — see
 * .page-hero__img's z-index: -2, which stacks above this element's own
 * background paint) and gives the white title/subtitle the dark backdrop
 * the overlay gradient assumes will always be there.
 */
.page-hero { background: var(--brand-navy); }

/*
 * Ornament model lists (bin/import-ornaments.php): one line per model,
 * in two columns beside the gallery.
 */
.product-main__desc .ornament-models {
	columns: 2;
	column-gap: var(--sp-6);
	margin: 0 0 var(--sp-4);
	padding: 0;
	list-style: none;
	font-size: var(--fs-sm);
}

.product-main__desc .ornament-models li {
	break-inside: avoid;
	padding-block: 2px;
}

.product-main__desc h2 {
	margin-block: var(--sp-6) var(--sp-3);
	font-size: var(--fs-base);
	letter-spacing: 0.12em;
	text-transform: uppercase;
}

@media (max-width: 767px) {
	.product-main__desc .ornament-models { columns: 1; }
}
