/* ==========================================================================
   Front page

   Seven sections making one argument: what we make, where to start, why us
   rather than a dealer, one piece of merchandising, where to come and see it,
   how to pay, and a way to stay in touch.

   The design reference carries no homepage, so this file is built from
   theme.json's own scale rather than converted from an export. No value in it
   is hardcoded. Three values had no token and were added to theme.json rather
   than written here: the hero's two crops, `aspect--hero` (12:5) and
   `aspect--hero-portrait` (4:5), and `scrim-strong`, the scrim colour at the
   alpha white text needs over a bright photograph.

   Motion: the only thing that moves is a room tile's photograph on hover, the
   same 150ms transform the product tile and the room landing already use.
   theme.json's global stylesheet stands every transition down under
   prefers-reduced-motion.
   ========================================================================== */

/*
 * Two things WordPress's constrained layout does to these sections have to be
 * answered here.
 *
 * The blockGap top margin is the first: the sections are spaced by this file's
 * own `gap`, so that second rhythm has to come off or it stacks on top.
 *
 * The second is `margin-inline: auto !important`, which core sets on every
 * constrained child so a block centres inside the content width. On a grid
 * item an auto margin absorbs the free space *instead of* the item stretching
 * into it, so each section collapsed to the width of its own contents and the
 * page came out ragged — a hero one width, the showrooms another, the signup
 * another. The margins cannot be overridden, so the width is given instead:
 * with a definite `width: 100%` there is no free space left for them to eat,
 * the section fills its track, core's own `max-width` caps it at the content
 * size, and the auto margins go back to centring what is left over.
 */
.tfs-home > * {
	width: 100%;
}

.tfs-home > *,
.tfs-home-hero > *,
.tfs-home-rooms > *,
.tfs-home-factory > *,
.tfs-home-collection > *,
.tfs-home-showrooms > *,
.tfs-home-financing > *,
.tfs-home-signup > * {
	margin-block-start: 0;
}

.tfs-home {
	display: grid;
	gap: var(--wp--preset--spacing--60);
	padding-block: var(--wp--preset--spacing--40) var(--wp--preset--spacing--70);
}

@media (min-width: 782px) {
	.tfs-home {
		gap: var(--wp--preset--spacing--70);
	}
}

/*
 * A full-bleed hero meets the header. The air above it is the type-led hero's,
 * and behind a photograph it reads as a band of ground the picture failed to
 * fill. Two sources, so two lines: this file's own top padding, and core's
 * block-gap margin on every child of .wp-site-blocks that is not the first —
 * which `main` never is, with the announcement bar and the header ahead of it.
 * Where :has() is unsupported both simply stay, which is the harmless failure
 * of the two.
 */
.tfs-home:has(> .tfs-home-hero--bleed) {
	margin-block-start: 0;
	padding-block-start: 0;
}

/* Every section but the hero opens on a hairline. It is the only separator
   this system has, and it is what keeps seven stacked sections from reading as
   one long column. */
.tfs-home-rooms,
.tfs-home-collection,
.tfs-home-showrooms,
.tfs-home-financing,
.tfs-home-signup {
	padding-top: var(--wp--preset--spacing--50);
	border-top: var(--wp--custom--hairline);
}

/* --------------------------------------------------------------------------
   Section headings
   -------------------------------------------------------------------------- */

.tfs-home-rooms__heading,
.tfs-home-factory__heading,
.tfs-home-collection__heading,
.tfs-home-showrooms__heading,
.tfs-home-signup__heading {
	margin: 0;
	font-size: var(--wp--preset--font-size--display-small);
	line-height: var(--wp--custom--line-height--display);
}

@media (min-width: 782px) {
	.tfs-home-rooms__heading,
	.tfs-home-factory__heading,
	.tfs-home-collection__heading,
	.tfs-home-showrooms__heading,
	.tfs-home-signup__heading {
		font-size: var(--wp--preset--font-size--display-medium);
	}
}

.tfs-home-rooms__heading,
.tfs-home-showrooms__heading {
	margin-bottom: var(--wp--preset--spacing--40);
}

/* The eyebrow above a heading. Utility face, uppercase, tracked. */
.tfs-home-factory__eyebrow,
.tfs-home-collection__eyebrow {
	margin: 0;
	font-size: var(--wp--preset--font-size--utility);
	text-transform: uppercase;
	letter-spacing: var(--wp--custom--tracking--utility);
	line-height: 1.4;
	color: var(--wp--preset--color--muted);
}

/* Provenance is the one thing on this site that gets the saddle colour.
   `saddle-text`, not `saddle`: 12px type on the strip's `surface` panel, where
   the decorative value is 3.68:1 and fails AA. The darkened one is 4.81:1. */
.tfs-home-factory__eyebrow {
	color: var(--wp--preset--color--saddle-text);
}

/* --------------------------------------------------------------------------
   Hero — full-bleed room scene with the type over it

   This reverses the rule the rest of the build follows. The room landing and
   How It's Built both set their heading beneath the photograph on the grounds that
   an overlay needs a scrim, and a scrim is a depth device on a site that has
   none. The front page is the one page where the trade is worth making, and the
   scrim below is sized so it is not a trade against legibility: it carries
   white text over a pure white pixel, which is the lightest thing an upload can
   contain. Recorded in design-reference/README.md.

   The type sits bottom-left rather than centred. The eye lands on the
   photograph first and the headline second, which is the order the section
   argues in, and it leaves the top of the frame — where a room scene usually
   carries its light and its depth — uncovered.

   With no photograph the hero falls back to --type-led further down this file:
   the same type on `ground`, not a full-bleed frame with nothing in it.
   -------------------------------------------------------------------------- */

/*
 * The hero is the only element on this template that leaves the content width,
 * and on a platform with classic scrollbars a 100vw-wide child of a narrower
 * document is 15px of horizontal scroll. Clipping the site wrapper takes that
 * away. `clip` and not `hidden` on purpose: clip creates no scroll container,
 * so the sticky header keeps its scrollport and nothing inside loses one.
 */
.wp-site-blocks {
	overflow-x: clip;
}

/*
 * The hero frame itself keeps the content width and core's constrained
 * treatment. It is the photograph inside it that bleeds — see the rule below.
 */
.tfs-home-hero--bleed {
	display: grid;
	grid-template-areas: "stack";
	/*
	 * The one column is pinned rather than left to size itself. An `auto` track
	 * takes its width from the widest item's max-content contribution, and the
	 * photograph below is 100vw — so the track grew to the viewport, the type
	 * box grew with it, and at 360px the headline ran off the right of the
	 * screen. `minmax(0, 1fr)` holds the track at the content column and lets
	 * the photograph overflow it, which is the whole point of the photograph.
	 */
	grid-template-columns: minmax(0, 1fr);
}

/* The photograph and the type occupy one cell, so the type is over the picture
   without either being taken out of flow — the cell is as tall as the taller of
   the two, and on a narrow screen that is sometimes the type. */
.tfs-home-hero--bleed > * {
	grid-area: stack;
	min-width: 0;
}

/*
 * The frame is taller than the photograph on a phone and wider than it on a
 * desktop, so the crop is what changes across the breakpoints, not the source.
 * 4:5 at 360px, because a 12:5 strip on a phone is 150px of letterbox nobody
 * reads; 3:2 through the tablet band, where 4:5 would be a 975px-tall hero and
 * 12:5 a 325px one; 12:5 from 782px up, which is the ratio the field asks the
 * editor to upload at, so on a desktop the picture is shown uncropped.
 */
.tfs-home-hero__image {
	display: block;
	/*
	 * The photograph is what leaves the content width, not the hero. Core gives
	 * an .alignfull child of a global-padding container enough negative margin
	 * to clear that container's own padding, but that is not the whole inset
	 * here: theme.json pads the body on top of the root padding
	 * `.has-global-padding` applies, and above the content width there is
	 * centring slack as well. Measuring against the viewport clears all three
	 * and needs to know none of them — factory.css takes the same approach.
	 *
	 * Bleeding the picture rather than the whole hero is what keeps the type
	 * honest: the inner box is left in the normal content column, so the
	 * headline's left edge is the same edge every section below it uses,
	 * without this file re-deriving an inset it would then have to keep in step.
	 */
	width: 100vw;
	max-width: none;
	margin-inline: calc(50% - 50vw);
	height: 100%;
	aspect-ratio: var(--wp--custom--aspect--hero-portrait);
	object-fit: cover;
	/* Slightly above centre. A wide source in a tall frame crops the sides and
	   ignores this; a squarer source in the desktop frame crops top and bottom,
	   and a room scene keeps its light in the upper half. */
	object-position: 50% 40%;
	/* A 2px radius on an edge that runs off the screen is a rounded corner
	   nobody can see, on two corners that are not there. */
	border-radius: 0;
	background-color: var(--wp--preset--color--placeholder);
}

@media (min-width: 600px) {
	.tfs-home-hero__image {
		aspect-ratio: var(--wp--custom--aspect--room);
	}
}

@media (min-width: 782px) {
	.tfs-home-hero__image {
		aspect-ratio: var(--wp--custom--aspect--hero);
	}
}

/*
 * The type column. It is left in the normal content column and given no width
 * of its own, so its left edge is the page's left edge — the same one every
 * section below it sits on — while the photograph behind it runs to the
 * viewport. The grid bottom-aligns it, so its height is the height of the type,
 * which is what makes the scrim below reliable.
 */
.tfs-home-hero--bleed .tfs-home-hero__inner {
	align-self: end;
	position: relative;
	z-index: 1;
	padding-block: var(--wp--preset--spacing--50);
}

@media (min-width: 782px) {
	.tfs-home-hero--bleed .tfs-home-hero__inner {
		padding-block: var(--wp--preset--spacing--60);
	}
}

/*
 * THE SCRIM. This is the part the hero lives or dies on, so it is measured
 * rather than judged by eye.
 *
 * `--scrim-strong` is the scrim token's own ink at the alpha AA needs: white
 * text over it clears 4.5:1 against a *pure white* pixel — the lightest thing
 * a photograph can contain — at 7.06:1, so no editor's upload can break it.
 * The 0.32 the modal scrim uses reaches 2.05:1 there and would have failed on
 * any bright picture. Both alphas are the same ink; only the strength differs.
 *
 * It is drawn on the inner box and not on the frame because the inner box is
 * bottom-aligned and self-sizing: its height is the height of the type. Stops
 * against the *frame* would have drifted, since the type is a third of a 1920px
 * hero and two thirds of a 1024px one.
 *
 * The fade is a length and not a percentage for the same reason one step down.
 * The box is extended above the type by exactly the distance the fade runs, so
 * full strength is reached at the inner box's own top edge and the type — which
 * starts a padding step below that — is never in the ramp, at any headline
 * length. A percentage fade grows with the type it is meant to clear: measured
 * at 1440px, a two-line headline put its cap line at alpha 0.57 rather than
 * 0.72, which is 4.21:1 on a white photograph. That still passes AA for 60px
 * display type, which is large text at 3:1, but it fails the 4.5:1 a reader
 * would assume and it gets worse as the headline gets longer. A fixed ramp
 * cannot drift.
 *
 * It is stretched back out to the viewport with the same calc the hero uses,
 * because the inner box stops at the content width and the scrim must not.
 */
.tfs-home-hero--bleed .tfs-home-hero__inner::before {
	content: "";
	position: absolute;
	z-index: -1;
	inset-inline: calc(50% - 50vw);
	inset-block: calc(var(--wp--preset--spacing--80) * -2) 0;
	background-image: linear-gradient(
		to top,
		var(--wp--custom--scrim-strong) 0,
		var(--wp--custom--scrim-strong) calc(100% - (var(--wp--preset--spacing--80) * 2)),
		transparent 100%
	);
	pointer-events: none;
}

.tfs-home-hero__text {
	display: grid;
	justify-items: start;
	gap: var(--wp--preset--spacing--30);
	min-width: 0;
	/* One reading column, the same measure How It's Built and My List use. */
	max-width: var(--wp--custom--measure);
}

/*
 * display-large on a phone, display-hero from the tablet breakpoint up. The
 * 60px step exists for this one heading and no other, but at 360px it costs
 * three lines and pushes the button toward the fold — and the button is what
 * the hero is for. 44px is still unmistakably hero scale and is well clear of
 * the 28px floor display type is held to.
 */
.tfs-home-hero__title {
	margin: 0;
	font-size: var(--wp--preset--font-size--display-large);
	line-height: 1.02;
}

@media (min-width: 782px) {
	.tfs-home-hero__title {
		font-size: var(--wp--preset--font-size--display-hero);
	}
}

/*
 * Body face, not display. Display type on this site floors at 28px, which would
 * put this line in an argument with the H1 directly above it.
 */
.tfs-home-hero__standfirst {
	margin: 0;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--sub);
	line-height: 1.4;
	color: var(--wp--preset--color--muted);
}

.tfs-home-hero__actions {
	margin: 0;
}

/* Full width on a phone, where a pill next to nothing reads as an
   afterthought; sized to its text once there is a row to sit in. */
.tfs-home-hero__cta {
	width: 100%;
}

@media (min-width: 600px) {
	.tfs-home-hero__cta {
		width: auto;
	}
}

/* --------------------------------------------------------------------------
   Hero — over the photograph

   Everything in this group applies only when there is a picture underneath.
   The type-led fallback keeps `ink` and `muted` on `ground`, where `surface`
   would be invisible.
   -------------------------------------------------------------------------- */

.tfs-home-hero--bleed .tfs-home-hero__title,
.tfs-home-hero--bleed .tfs-home-hero__standfirst {
	color: var(--wp--preset--color--surface);
}

/*
 * The button keeps the site's accent fill and surface label — 5.30:1, unchanged
 * over a photograph because the fill is opaque. What does change is its edge:
 * accent against a scrimmed *light* photograph is 1.33:1, so the control has no
 * visible boundary, which is 1.4.11's 3:1 and not 1.4.3's. The hairline in
 * surface gives it one at 5.30:1 against its own fill without making it an
 * outline button or touching the fill.
 */
.tfs-home-hero--bleed .tfs-home-hero__cta {
	border-color: var(--wp--preset--color--surface);
}

/*
 * The focus ring is `surface` here and `accent` everywhere else on the site.
 * The ring is offset, so what sits in the gap is the background — on `ground`
 * that is a 5.08:1 accent-on-paper ring, which is why the site-wide rule works.
 * In the hero the gap is the scrimmed photograph, where the same ring is
 * 1.33:1, and the ring also has to read against the accent button it surrounds,
 * where accent-on-accent is 1.00:1 — invisible. Surface clears both: 7.06:1
 * against the worst-case scrim and 5.30:1 against the button. CLAUDE.md's rule
 * is that a focus ring is a visible outline; this is that rule applied, not an
 * exception to it.
 */
.tfs-home-hero--bleed .tfs-home-hero__cta:focus-visible {
	outline-color: var(--wp--preset--color--surface);
}

/* --------------------------------------------------------------------------
   Hero — type-led fallback

   No photograph, so no bleed, no scrim, and no white type. This is the hero
   the page had before the picture, on `ground`, and it is what an empty Hero
   Image field falls back to rather than an empty black frame.
   -------------------------------------------------------------------------- */

.tfs-home-hero--type-led {
	padding-block: var(--wp--preset--spacing--40) var(--wp--preset--spacing--20);
}

.tfs-home-hero--type-led .tfs-home-hero__text {
	max-width: 34ch;
}

/* --------------------------------------------------------------------------
   Shop by room

   The anchor of the page below the hero: two large cards to a row rather than
   a shelf of thumbnails, because this is the section that decides whether
   somebody who arrived on a brand search goes any further.

   Each card is a photograph with a surface panel lifted over its lower edge and
   hung past one side of it. The overlap is a negative margin, not absolute
   positioning — the panel stays in flow, so the card's own height accounts for
   it, the row measures correctly, and the stretched link still resolves against
   the card rather than against the panel.

   Which side the panel hangs past alternates 4n+1/4n+4 against 4n+2/4n+3, so a
   two-column grid reads left-right on one row and right-left on the next. A
   single alternation would have made each column uniform, which is the
   opposite of the rhythm this is for.

   Nothing moves on hover. An image that scales would need a transform, a
   transform makes a stacking context, and a stacking context would paint the
   photograph over the panel — so the feedback is the panel's border going to
   ink and the action underlining, which costs no motion and needs no
   prefers-reduced-motion exception.
   -------------------------------------------------------------------------- */

.tfs-home-rooms__items {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--wp--preset--spacing--60);
	/* A card with no photograph is shorter than its neighbour, and should look
	   shorter rather than have its panel stretched to match. */
	align-items: start;
	margin: 0;
	padding: 0;
	list-style: none;
}

@media (min-width: 782px) {
	.tfs-home-rooms__items {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		/* Generous down the page, tighter across it: the row gap is what makes
		   the section feel deliberate rather than dense. */
		gap: var(--wp--preset--spacing--70) var(--wp--preset--spacing--40);
	}
}

.tfs-home-rooms__item {
	margin: 0;
	min-width: 0;
}

/*
 * A grid, for one reason: grid items honour z-index without being positioned.
 *
 * The panel has to paint over the photograph, and DOM order alone will not do
 * it — an <img> is replaced content, which paints after every block background
 * in the same stacking context however late that block appears in the markup.
 * The obvious fix, position: relative on the panel, would make the panel the
 * nearest positioned ancestor and collapse the link's ::after onto it, losing
 * the card-wide click target. Making the card a grid gets the stacking without
 * touching positioning.
 */
.tfs-home-room {
	position: relative;
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	color: var(--wp--preset--color--ink);
}

/* --------------------------------------------------------------------------
   The photograph
   -------------------------------------------------------------------------- */

.tfs-home-room__media {
	overflow: hidden;
	aspect-ratio: var(--wp--custom--aspect--room);
	background-color: var(--wp--preset--color--placeholder);
	border-radius: var(--wp--custom--radius);
}

.tfs-home-room__image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* --------------------------------------------------------------------------
   The panel
   -------------------------------------------------------------------------- */

.tfs-home-room__panel {
	/* Above the photograph. See the note on .tfs-home-room for why this works
	   without position: relative, and why it must. */
	z-index: 1;
	/* Lifts the panel over the lower part of the photograph. */
	margin-block-start: calc(var(--wp--preset--spacing--50) * -1);
	padding: var(--wp--preset--spacing--30);
	background-color: var(--wp--preset--color--surface);
	border: var(--wp--custom--hairline);
	border-radius: var(--wp--custom--radius);
	transition: border-color var(--wp--custom--motion--duration) var(--wp--custom--motion--easing);
}

@media (min-width: 782px) {
	.tfs-home-room__panel {
		margin-block-start: calc(var(--wp--preset--spacing--60) * -1);
		padding: var(--wp--preset--spacing--40);
	}
}

/*
 * The offset. The photograph is inset from one edge of the card and the panel
 * runs to it, so the panel hangs past the photograph without either of them
 * leaving the card — which is what keeps the overhang from colliding with the
 * next column at 1440px or with the page gutter at 360px.
 */
.tfs-home-room__media {
	margin-inline: var(--wp--preset--spacing--40) 0;
}

.tfs-home-room__panel {
	margin-inline: 0 var(--wp--preset--spacing--40);
}

@media (min-width: 782px) {
	.tfs-home-room__panel {
		margin-inline: 0 var(--wp--preset--spacing--70);
	}
}

/* Mirrored: second and third of every four, so the rows alternate. */
.tfs-home-rooms__item:nth-child(4n + 2) .tfs-home-room__media,
.tfs-home-rooms__item:nth-child(4n + 3) .tfs-home-room__media {
	margin-inline: 0 var(--wp--preset--spacing--40);
}

.tfs-home-rooms__item:nth-child(4n + 2) .tfs-home-room__panel,
.tfs-home-rooms__item:nth-child(4n + 3) .tfs-home-room__panel {
	margin-inline: var(--wp--preset--spacing--40) 0;
}

@media (min-width: 782px) {
	.tfs-home-rooms__item:nth-child(4n + 2) .tfs-home-room__panel,
	.tfs-home-rooms__item:nth-child(4n + 3) .tfs-home-room__panel {
		margin-inline: var(--wp--preset--spacing--70) 0;
	}
}

/*
 * A room with no photograph. The panel stands on its own rather than sitting
 * over a grey rectangle pretending to be one — the same call the hero makes
 * when no image is set. It runs the full width of the card, because there is
 * no longer an edge for it to hang past.
 */
.tfs-home-room--type-led .tfs-home-room__panel {
	margin-block-start: 0;
	margin-inline: 0;
	padding: var(--wp--preset--spacing--40);
}

/* --------------------------------------------------------------------------
   Panel contents
   -------------------------------------------------------------------------- */

/*
 * The display face on an H3. CLAUDE.md reserves it for H1 and H2, and this is
 * the one place the build breaks that: the brief asks for a display-face
 * heading on the card, and the card is the page's anchor. The 28px floor is
 * kept — display-small is exactly it — and the section's own H2 stays a step
 * larger on a desktop, so the outline still reads top-down.
 * Recorded in design-reference/README.md.
 */
.tfs-home-room__name {
	margin: 0;
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--display-small);
	letter-spacing: var(--wp--custom--tracking--display);
	line-height: var(--wp--custom--line-height--display);
	color: var(--wp--preset--color--ink);
}

.tfs-home-room__description {
	margin: var(--wp--custom--step--12) 0 0;
	max-width: var(--wp--custom--measure);
	font-size: var(--wp--preset--font-size--body);
	line-height: var(--wp--custom--line-height--body);
	color: var(--wp--preset--color--muted);
}

.tfs-home-room__action {
	margin: var(--wp--preset--spacing--20) 0 0;
}

.tfs-home-room__link {
	display: inline-flex;
	align-items: baseline;
	gap: var(--wp--custom--step--8);
	font-size: var(--wp--preset--font-size--utility);
	text-transform: uppercase;
	letter-spacing: var(--wp--custom--tracking--utility);
	line-height: 1.4;
	color: var(--wp--preset--color--accent);
	text-decoration: none;
}

/* What makes the whole card clickable. The panel is not positioned, so this
   resolves against the card and covers the photograph too. */
.tfs-home-room__link::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}

.tfs-home-room:hover .tfs-home-room__link {
	color: var(--wp--preset--color--accent-hover);
	text-decoration: underline;
}

.tfs-home-room:hover .tfs-home-room__panel {
	border-color: var(--wp--preset--color--ink);
}

/*
 * The focus ring goes round the whole card, not round the four words of the
 * action — what is focused should look like what activating it will open.
 * Focus indicators are exempt from the no-shadow rule: outline, never shadow.
 */
.tfs-home-room:has(.tfs-home-room__link:focus-visible) {
	outline: var(--wp--custom--focus--width) solid var(--wp--preset--color--accent);
	outline-offset: var(--wp--custom--focus--offset);
}

/* Where :has() is not supported the link rings itself, so a keyboard is never
   left without an indicator. */
@supports not selector(:has(*)) {
	.tfs-home-room__link:focus-visible {
		outline: var(--wp--custom--focus--width) solid var(--wp--preset--color--accent);
		outline-offset: var(--wp--custom--focus--offset);
	}
}

/* --------------------------------------------------------------------------
   Factory strip — the argument for choosing us

   Weight comes from the panel, the space inside it, and a photograph at hero
   size. Not from a larger typeface: the heading sits at the same step as every
   other section's, because a section that shouts is a section a reader
   discounts.
   -------------------------------------------------------------------------- */

.tfs-home-factory {
	display: grid;
	gap: var(--wp--preset--spacing--40);
	align-items: center;
	padding: var(--wp--preset--spacing--50) var(--wp--preset--spacing--30);
	background-color: var(--wp--preset--color--surface);
	border-block: var(--wp--custom--rule-strong);
}

@media (min-width: 782px) {
	.tfs-home-factory {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--wp--preset--spacing--50);
		padding: var(--wp--preset--spacing--70) var(--wp--preset--spacing--50);
	}

	.tfs-home-factory--type-led {
		grid-template-columns: minmax(0, 1fr);
	}
}

.tfs-home-factory__figure {
	margin: 0;
	min-width: 0;
}

.tfs-home-factory__image {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: var(--wp--custom--aspect--room);
	object-fit: cover;
	border-radius: var(--wp--custom--radius);
	background-color: var(--wp--preset--color--placeholder);
}

.tfs-home-factory__text {
	display: grid;
	justify-items: start;
	gap: var(--wp--preset--spacing--20);
	min-width: 0;
	max-width: 52ch;
}

.tfs-home-factory__copy {
	margin: 0;
	font-size: var(--wp--preset--font-size--body);
	line-height: var(--wp--custom--line-height--body);
}

.tfs-home-factory__actions,
.tfs-home-collection__actions {
	margin-block: var(--wp--preset--spacing--20) 0;
}

/* --------------------------------------------------------------------------
   Featured collection
   -------------------------------------------------------------------------- */

.tfs-home-collection {
	display: grid;
	gap: var(--wp--preset--spacing--40);
	align-items: center;
}

@media (min-width: 782px) {
	.tfs-home-collection {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--wp--preset--spacing--50);
	}
}

.tfs-home-collection__figure {
	margin: 0;
	min-width: 0;
}

.tfs-home-collection__image {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: var(--wp--custom--aspect--room);
	object-fit: cover;
	border-radius: var(--wp--custom--radius);
	background-color: var(--wp--preset--color--placeholder);
}

.tfs-home-collection__text {
	display: grid;
	justify-items: start;
	gap: var(--wp--preset--spacing--20);
	min-width: 0;
	max-width: 52ch;
}

.tfs-home-collection__summary {
	margin: 0;
	font-size: var(--wp--preset--font-size--body);
	line-height: var(--wp--custom--line-height--body);
	color: var(--wp--preset--color--muted);
}

/* --------------------------------------------------------------------------
   Showrooms
   -------------------------------------------------------------------------- */

.tfs-home-showrooms__items {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--wp--preset--spacing--50);
	margin: 0;
	padding: 0;
	list-style: none;
}

/* However many are published, they share the row. auto-flow rather than a
   fixed count, so two and three both look deliberate.

   Not before 1260px, the first width at which each of two cards is 552px —
   what a card needs to hold its photograph beside its text (see below). Two-up
   any earlier, each card is too narrow: the photograph either becomes a tall
   sliver beside the text or stacks above it, and a stacked photograph makes
   one card twice the height of a neighbour without one. Until there is room
   for two, the cards stack, full width. */
@media (min-width: 600px) {
	/* Every row the height of the tallest, so a card with no photograph is as
	   tall as one with, stacked or side by side. Not on a phone, where the
	   photograph sits above the text and matching it would leave a
	   photograph's worth of empty card. */
	.tfs-home-showrooms__items {
		grid-auto-rows: 1fr;
	}
}

@media (min-width: 1260px) {
	.tfs-home-showrooms__items {
		grid-auto-flow: column;
		grid-auto-columns: minmax(0, 1fr);
		gap: var(--wp--preset--spacing--40);
	}
}

/* The card lays itself out by its own width, not the viewport's, so the same
   rule holds one-up on a tablet and two-up on a desktop. */
.tfs-home-showrooms__item {
	margin: 0;
	min-width: 0;
	container-type: inline-size;
}

/* The card is the frame — surface, hairline, full height of its row so two
   cards always sit level, photograph or not. The padding lives on the body
   rather than here, so a photograph meets the hairline without negative
   margins. Nothing on the card clips: overflow: hidden here would cut off the
   focus rings on the call button and the link, so the photograph rounds its
   own corners instead. */
.tfs-home-showroom {
	display: flex;
	flex-direction: column;
	height: 100%;
	background-color: var(--wp--preset--color--surface);
	border: var(--wp--custom--hairline);
	border-radius: var(--wp--custom--radius);
}

/* Flex rather than grid, so the actions block's `margin-block-start: auto`
   below has free space to absorb — an auto margin in a grid centres within its
   own track instead of pushing to the container's end. It grows to fill the
   card, so a card with no photograph is text from edge to edge and still as
   tall as its neighbour, with the buttons on the same line. */
.tfs-home-showroom__body {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--wp--custom--step--12);
	min-width: 0;
	padding: var(--wp--preset--spacing--30);
}

/* Stacked above the text on a phone, where 40% of a 360px card would be a
   thumbnail nobody could read. */
.tfs-home-showroom__media {
	overflow: hidden;
	aspect-ratio: var(--wp--custom--aspect--tile);
	margin: 0;
	background-color: var(--wp--preset--color--placeholder);
	border-start-start-radius: var(--wp--custom--radius);
	border-start-end-radius: var(--wp--custom--radius);
}

.tfs-home-showroom__image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Beside the text once the card is 552px wide — a 600px screen with the cards
   stacked, and from 1260px with two across. Narrower than that, 40% of
   the card is too small a picture to read, so it stays above the text.

   Two fifths of the card, the full height of it. 4:3 is the floor rather than
   a fixed shape: the photograph is never shorter than three quarters of its
   width, so a wide card does not get a letterbox strip, and where the text runs
   taller the photograph stretches with it and the crop takes up the
   difference. It never leaves a gap beneath itself. */
@container (min-width: 552px) {
	.tfs-home-showroom--has-photo {
		flex-direction: row;
	}

	.tfs-home-showroom--has-photo .tfs-home-showroom__media {
		flex: 0 0 40%;
		align-self: stretch;
		aspect-ratio: var(--wp--custom--aspect--tile);
		border-start-end-radius: 0;
		border-end-start-radius: var(--wp--custom--radius);
	}
}

.tfs-home-showroom__city {
	margin: 0;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--lead);
	letter-spacing: 0;
	line-height: var(--wp--custom--line-height--tight);
}

.tfs-home-showroom__address {
	display: grid;
	gap: var(--wp--custom--step--4);
	margin: 0;
	font-style: normal;
	font-size: var(--wp--preset--font-size--small);
	line-height: var(--wp--custom--line-height--body);
	color: var(--wp--preset--color--muted);
}

/*
 * Overrides .tfs-avail's 12px uppercase utility face. It reuses the dot —
 * filled for open, hollow for closed — but this is the one line somebody reads
 * from a phone in a car park, and `utility` is sized for spec labels. The same
 * override the showroom page makes, for the same reason.
 */
.tfs-home-showroom__status {
	margin: var(--wp--custom--step--4) 0 0;
	font-size: var(--wp--preset--font-size--sub);
	text-transform: none;
	letter-spacing: 0;
	line-height: var(--wp--custom--line-height--tight);
}

.tfs-home-showroom__raw {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	line-height: var(--wp--custom--line-height--body);
	color: var(--wp--preset--color--muted);
}

/* Pushed to the foot of the card so two cards of unequal address length still
   line their buttons up. */
.tfs-home-showroom__actions {
	display: grid;
	justify-items: start;
	gap: var(--wp--custom--step--12);
	width: 100%;
	margin-block-start: auto;
	padding-block-start: var(--wp--custom--step--8);
}

/* Full width at 360px, where the call button is the card's whole purpose. */
.tfs-home-showroom__call {
	width: 100%;
}

@media (min-width: 600px) {
	.tfs-home-showroom__call {
		width: auto;
	}
}

.tfs-home-showroom__link {
	font-size: var(--wp--preset--font-size--small);
	line-height: var(--wp--custom--line-height--body);
	color: var(--wp--preset--color--accent);
	text-decoration: underline;
}

.tfs-home-showroom__link:hover {
	color: var(--wp--preset--color--accent-hover);
}

.tfs-home-showroom__link:focus-visible {
	outline: var(--wp--custom--focus--width) solid var(--wp--preset--color--accent);
	outline-offset: var(--wp--custom--focus--offset);
}

/* --------------------------------------------------------------------------
   Financing band
   -------------------------------------------------------------------------- */

.tfs-home-financing {
	display: grid;
	gap: var(--wp--custom--step--8);
}

@media (min-width: 600px) {
	.tfs-home-financing {
		grid-template-columns: 1fr auto;
		align-items: baseline;
		gap: var(--wp--preset--spacing--30);
	}
}

.tfs-home-financing__copy {
	margin: 0;
	max-width: 62ch;
	font-size: var(--wp--preset--font-size--sub);
	line-height: 1.4;
}

.tfs-home-financing__actions {
	margin: 0;
}

.tfs-home-financing__link {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--accent);
	text-decoration: underline;
	white-space: nowrap;
}

.tfs-home-financing__link:hover {
	color: var(--wp--preset--color--accent-hover);
}

.tfs-home-financing__link:focus-visible {
	outline: var(--wp--custom--focus--width) solid var(--wp--preset--color--accent);
	outline-offset: var(--wp--custom--focus--offset);
}

/* --------------------------------------------------------------------------
   Email signup

   The fields and the button are form.css and button.css unchanged; only the
   layout around them lives here.
   -------------------------------------------------------------------------- */

.tfs-home-signup {
	display: grid;
	gap: var(--wp--preset--spacing--30);
}

@media (min-width: 1024px) {
	.tfs-home-signup {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		column-gap: var(--wp--preset--spacing--50);
		align-items: start;
	}

	/* The note belongs under the form, not under the intro copy. */
	.tfs-home-signup__note {
		grid-column: 2;
	}
}

.tfs-home-signup__intro {
	display: grid;
	gap: var(--wp--custom--step--12);
	max-width: 42ch;
}

.tfs-home-signup__copy {
	margin: 0;
	font-size: var(--wp--preset--font-size--body);
	line-height: var(--wp--custom--line-height--body);
	color: var(--wp--preset--color--muted);
}

.tfs-home-signup__fields {
	display: grid;
	gap: var(--wp--preset--spacing--20);
}

/* Name and email share a row once there is room, with the button beneath them
   across both. At 360px everything stacks. */
@media (min-width: 600px) {
	.tfs-home-signup__fields {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.tfs-home-signup__submit {
		grid-column: 1 / -1;
	}
}

.tfs-home-signup__submit {
	display: grid;
}

/* Empty until the module writes to it, and it must not hold open a gap while
   it is. :empty rather than [hidden] because the module sets textContent. */
.tfs-home-signup__status {
	margin: var(--wp--preset--spacing--20) 0 0;
	font-size: var(--wp--preset--font-size--small);
	line-height: var(--wp--custom--line-height--body);
	color: var(--wp--preset--color--ink);
}

.tfs-home-signup__status:empty {
	display: none;
}

.tfs-home-signup__note {
	margin: 0;
	max-width: 62ch;
	font-size: var(--wp--preset--font-size--caption);
	line-height: 1.5;
	color: var(--wp--preset--color--muted);
}
