/*
 * FigmaMCP-Test.css
 * Standalone recreation of Figma node 76:10557 ("Homepage").
 * Styles ONLY this page's main content via .ft-* classes — it does not
 * reuse or depend on homePage_design.css. The shared header/footer chrome
 * keeps its own storefront styling.
 *
 * Figma tokens:
 *   Blue_Main #2DA7FA · Blue_Subtle #EDF7FF · Text #333536 · Muted #737A82
 *   Title/Display 36/44 · Title/Title 24/30 · Title/H1 20 · Title/H2 16
 *   Body/Lead 16/22 · Body/Body-B 14 · Label/Button 16
 */

.ft-main {
	--ft-blue: #2da7fa;
	--ft-blue-subtle: #edf7ff;
	--ft-text: #333536;
	--ft-muted: #737a82;
	--ft-border: #e4e4e4;
	--ft-shell: min(1480px, 100% - 80px);
	color: var(--ft-text);
	font-family: "Montserrat", sans-serif;
}

.ft-main *,
.ft-main *::before,
.ft-main *::after {
	box-sizing: border-box;
}

.ft-shell {
	width: var(--ft-shell);
	margin-inline: auto;
}

/* ---- Sections ---- */
.ft-section {
	padding: 80px 0;
}

.ft-section--hero {
	background: #f7f7f9;
	padding: 56px 0 36px;
}

/* Hero side margins follow Figma (node 76:10571): the hero content is inset
 * 18.75% per side (360px on the 1920 design) — intentionally wider than the
 * shared --ft-shell gutter, matching the Figma source. Desktop two-column hero
 * only; the stacked mobile hero (<=990px) keeps the shared shell so its
 * separately tuned gutters aren't squeezed.
 *
 * A flat 62.5% collapses the hero on smaller desktops: at 1920 it resolves to
 * 1200px (copy 480 + gap 48 + media 672, the design), but at e.g. 1040px it is
 * only 650px, starving the media column to ~120px and shrinking the image+blob
 * to a sliver. Instead hold a 1200px content block down to where the viewport
 * can no longer afford it (then fall back to full width minus a small gutter),
 * and keep the 18.75% inset only once 62.5% is wider than that block (>=1920).
 * This keeps the hero media a consistent size across all desktop widths. */
@media (min-width: 991px) {
	.ft-section--hero .ft-shell {
		width: min(100% - 48px, max(1200px, 62.5%));
	}
}

.ft-section--products {
	background: #fdfdfd;
}

.ft-section--teo {
	background: var(--ft-blue-subtle);
}

.ft-section--onescreen,
.ft-section--about {
	background: #fdfdfd;
}

.ft-section--toothview {
	background: #f7f7f9;
}

/* ---- Headings ---- */
.ft-heading {
	display: grid;
	gap: 8px;
}

.ft-eyebrow {
	margin: 0;
	font-size: 14px;
	font-weight: 600;
	line-height: 1.2;
	text-transform: uppercase;
	color: var(--ft-text);
}

.ft-title {
	margin: 0;
	font-size: 24px;
	line-height: 30px;
	font-weight: 700;
	color: var(--ft-text);
}

.ft-accent {
	color: var(--ft-blue);
}

.ft-lead {
	margin: 0;
	font-size: 16px;
	line-height: 22px;
	font-weight: 500;
	color: var(--ft-muted);
}

/* ---- Buttons ---- */
.ft-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 12px;
	width: fit-content;
	padding: 12px 32px;
	border: 1.5px solid transparent;
	border-radius: 8px;
	font-size: 16px;
	font-weight: 600;
	line-height: 1;
	cursor: pointer;
}

.ft-btn i {
	font-size: 16px;
}

.ft-btn--primary {
	background: var(--ft-blue);
	color: #f6f6f6;
}

.ft-btn--outline {
	padding: 8px 24px;
	background: transparent;
	color: var(--ft-blue);
	border-color: var(--ft-blue);
}

/* ---- Hero ---- */
/* Copy keeps its full 480px so the headline holds its design line count; the
 * media takes the rest. The shell width override (see .ft-section--hero .ft-shell)
 * keeps the shell from collapsing on smaller desktops, so the media column — and
 * with it the image+blob — stays a consistent size instead of shrinking to a
 * sliver as it did when the shell tracked a flat 62.5%. */
.ft-hero {
	display: grid;
	grid-template-columns: minmax(0, 480px) minmax(0, 1fr);
	gap: 48px;
	align-items: center;
}

.ft-hero__copy {
	display: grid;
	gap: 24px;
	max-width: 480px; /* Figma node 76:10571 copy column = 480px */
}

.ft-hero__badge {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	width: fit-content;
	padding: 8px 14px;
	background: #fff;
	border-radius: 999px;
	box-shadow: 0 8px 24px rgba(39, 55, 75, 0.08);
	font-size: 14px;
	font-weight: 600;
}

.ft-hero__badge img {
	width: 19px;
	height: 19px;
}

.ft-hero__title {
	margin: 0;
	font-size: 36px;
	line-height: 44px;
	font-weight: 700;
	color: var(--ft-text);
}

.ft-hero__desc {
	margin: 0;
	max-width: 448px;
	font-size: 16px;
	line-height: 22px;
	font-weight: 500;
	color: var(--ft-muted);
}

.ft-hero__media {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: flex-start;
	/* Slide 1 only (slides 2/3 set their own min-height via the --circle/--devices
	 * rules below). A touch taller than the others so the trays sit low enough that
	 * the blob's upward peek clears the carousel's top overflow:hidden instead of
	 * being sliced off on wide screens. */
	min-height: 380px;
}

/* Slide 1 trays + blob wrapper. The blob is anchored to THIS box (which is
 * sized to the trays), not to the media cell — so the blob↔trays relationship is
 * locked at every resolution (Figma node 76:10558). Only the wrapper's size
 * changes across breakpoints; the blob keeps its position relative to the trays.
 * The media cell still left-aligns (desktop) / centers (mobile) the whole unit. */
.ft-hero__media-stack {
	position: relative;
	width: 94%;
	/* Cap the trays (and with them the blob, which is sized as a % of this box) so
	 * the blob doesn't grow oversized — and overflow the carousel's top — on wide
	 * desktops. Held at the 1080p size; 4K scales it up via its own override. */
	max-width: 600px;
}

/* Slide 1 blob (hero_modupro_bg.svg) — tilt baked into the path; sits behind the
 * trays, peeking out above-left and below-right. Offsets are % of the wrapper
 * (= the trays box), measured from the Figma desktop layout, so they hold at any
 * width. */
.ft-hero__shape {
	position: absolute;
	z-index: 0;
	left: 15.96%;
	top: -27.35%;
	width: 69.15%;
}

/* Trays fill the wrapper; the wrapper carries the width cap. */
.ft-hero__product {
	position: relative;
	z-index: 1;
	display: block;
	width: 100%;
	object-fit: contain;
}

.ft-hero__dots {
	display: flex;
	justify-content: center;
	gap: 8px;
	margin-top: 28px;
}

.ft-hero__dots button {
	width: 8px;
	height: 8px;
	padding: 0;
	border: 0;
	border-radius: 999px;
	background: #c7d0d8;
	cursor: pointer;
	transition: width 0.3s ease, background 0.3s ease;
}

.ft-hero__dots button.is-active {
	width: 80px;
	background: var(--ft-blue);
}

/* ---- Hero carousel ---- */
/* The hero gutter is governed by the .ft-section--hero .ft-shell override
 * (18.75% per side, Figma node 76:10571) — intentionally wider than the split
 * sections (15.625%), matching Figma. The carousel just fills that shell, so no
 * extra max-width cap here (an old 1252px cap forced hero to align with the
 * splits and would now fight the %-based gutter at wide/4K widths). */
.ft-carousel {
	overflow: hidden;
}

.ft-carousel__track {
	display: flex;
	/* Slides stretch to the track's height. The track height is set per active
	 * slide in JS (setupHeroCarousel → setHeight), so the active slide is exactly
	 * tall enough to contain its content AND its overflowing decorative blob —
	 * without inheriting the tallest slide's height (which left a gap on mobile). */
	align-items: stretch;
	width: 100%;
	transition: transform 0.45s ease, height 0.45s ease;
	will-change: transform;
	touch-action: pan-y;
}

.ft-slide {
	flex: 0 0 100%;
	min-width: 100%;
	width: 100%;
	/* Clip each slide's decorative blobs to its own bounds so they don't bleed
	 * into the neighbouring slides (the track lays all slides side by side). */
	overflow: hidden;
}

/* Slide subtitle (e.g. "Practice + Visualize + Repeat") */
.ft-hero__text {
	display: grid;
	gap: 8px;
}

.ft-hero__subtitle {
	margin: 0;
	font-size: 16px;
	font-weight: 600;
	line-height: 1.2;
	color: #4f545a;
}

/* "Watch Demo" text link with play icon (slide 3) */
.ft-hero__watch {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	justify-self: start;
	margin-top: 4px;
	color: var(--ft-blue);
	font-size: 16px;
	font-weight: 600;
}

.ft-hero__watch i {
	font-size: 13px;
}

/* Laptop + phone composite media (slide 3) */
.ft-hero__media--devices {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 360px;
}

/* Slide 3 wrapper. Like .ft-hero__media-stack (slide 1), the blob is anchored to
 * THIS box (sized to the devices image), not the media cell — so the blob↔devices
 * relationship is locked at every resolution. Only the wrapper's size changes
 * across breakpoints. */
.ft-hero__devices-wrap {
	position: relative;
	width: 88%;
	max-width: 700px;
}

/* Devices fill the wrapper; the wrapper carries the width cap. */
.ft-hero__devices {
	position: relative;
	z-index: 1;
	display: block;
	width: 100%;
	object-fit: contain;
}

/* Slide 3 blob (hero_onescreen_bg.svg) — tilt baked into the path; large soft
 * blob behind the lower half of the laptop. Offsets are % of the wrapper (= the
 * devices box), from the Figma desktop layout, so they hold at any width. */
.ft-hero__devices-blob {
	position: absolute;
	z-index: 0;
	left: 1.14%;
	top: 24.86%;
	width: 79.54%;
}

/* Circular photo media (slide 2) */
.ft-hero__media--circle {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: flex-start;
	min-height: 360px;
}

/* Circle pushed off the left edge so the blob has room to its lower-right.
 * % width keeps it scaling at 4K. */
.ft-hero__circle-wrap {
	position: relative;
	width: 56%;
	margin-left: 4%;
}

/* Round photo "frame cutout": a rectangular photo clipped by the organic round
 * mask shape from Figma (Design 13). Replicates the Figma mask group rather
 * than relying on a pre-cropped circular PNG. */
.ft-hero__circle {
	position: relative;
	z-index: 1;
	width: 100%;
	aspect-ratio: 488.094 / 494.771;
	overflow: hidden;
	-webkit-mask: url(/images/new/homepage/hero_vr_mask.svg) center / contain no-repeat;
	mask: url(/images/new/homepage/hero_vr_mask.svg) center / contain no-repeat;
}

/* Photo sized/offset inside the frame exactly as in Figma so the subject is
 * framed correctly by the cutout. */
.ft-hero__circle img {
	position: absolute;
	left: -13.26%;
	top: -6.72%;
	width: 144.33%;
	height: 106.71%;
	max-width: none;
	display: block;
}

/* Slide 2 blob (hero_vr_bg.svg) — tilt baked into the path; solid blue
 * shape sitting just off the circle's lower-right, fully visible. */
.ft-hero__blob {
	position: absolute;
	z-index: 0;
	left: 90%;
	bottom: 3%;
	width: 58%;
}

/* ---- Physical Products ---- */
.ft-products__head {
	max-width: 640px;
	margin: 0 auto 56px;
	text-align: center;
	justify-items: center;
}

.ft-cards {
	display: grid;
	grid-template-columns: repeat(3, 240px);
	justify-content: center;
	gap: 120px;
}

/* Products carousel dots — mobile only (see responsive block) */
.ft-products__dots {
	display: none;
	justify-content: center;
	gap: 8px;
	margin-top: 28px;
}

.ft-products__dots button {
	width: 8px;
	height: 8px;
	padding: 0;
	border: 0;
	border-radius: 999px;
	background: #c7d0d8;
	cursor: pointer;
	transition: width 0.3s ease, background 0.3s ease;
}

.ft-products__dots button.is-active {
	width: 80px;
	background: var(--ft-blue);
}

.ft-card {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 16px;
	height: 100%;
}

/* Pin every card's button to a common baseline (Figma: all "Explore Now"
 * buttons sit at the same top). The cards already stretch to equal height as
 * grid items, so margin-top:auto keeps the buttons aligned even when one
 * description wraps to a different number of lines (e.g. Charlie at 4K). */
.ft-card .ft-btn {
	margin-top: auto;
}

.ft-card__img {
	display: flex;
	align-items: flex-end;
	justify-content: center;
	height: 190px;
}

.ft-card__img img {
	max-height: 190px;
	object-fit: contain;
}

.ft-card__info {
	display: grid;
	gap: 8px;
	text-align: center;
}

.ft-card__info h3 {
	margin: 0;
	font-size: 20px;
	font-weight: 600;
	color: var(--ft-text);
}

.ft-card__info p {
	margin: 0;
	font-size: 16px;
	line-height: 22px;
	font-weight: 500;
	color: var(--ft-muted);
}

/* ---- Split layouts (Teo / OneScreen / ToothView / About) ---- */
/* Figma side margins: the split content/media pin to a 15.625% gutter per side
 * (300px on the 1920 design). max-width 1320 = 1920 − 2×300; space-between
 * pins the text to the left gutter and the media to the right gutter, with the
 * inter-column gap absorbing the slack (Figma's gap varies per section). */
.ft-split {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	align-items: center;
	gap: 72px;
	max-width: 1320px;
	margin-inline: auto;
}

.ft-split__content {
	flex: 1 1 460px;
	max-width: 540px;
	display: grid;
	gap: 32px;
}

.ft-split__media {
	flex: 1 1 460px;
	max-width: 640px;
}

.ft-split__media img {
	display: block;
	width: 100%;
	border-radius: 24px;
	box-shadow: 0 24px 60px rgba(20, 33, 50, 0.08);
}

/* OneScreen media is a transparent device mockup — no frame/shadow */
.ft-split--onescreen .ft-split__media img {
	border-radius: 0;
	box-shadow: none;
}

/* Teo content is top-anchored (matching Figma, where the image is centered
   but the copy sits at a fixed top). This keeps the heading fixed while the
   active step's description animates open/closed — otherwise the vertically
   centered column re-centers each frame and the title jitters. */
.ft-split--teo .ft-split__content {
	align-self: flex-start;
}

/* ---- Feature list (OneScreen) ---- */
.ft-features {
	display: grid;
	gap: 16px;
}

.ft-feature__head {
	display: flex;
	align-items: center;
	gap: 8px;
}

.ft-feature__head img {
	width: 22px;
	height: 22px;
}

.ft-feature__head h3 {
	margin: 0;
	font-size: 16px;
	font-weight: 600;
	color: var(--ft-text);
}

.ft-feature p {
	margin: 8px 0 0;
	padding-left: 30px;
	font-size: 16px;
	line-height: 22px;
	font-weight: 500;
	color: var(--ft-muted);
}

/* ---- Timeline (Teo) — only the active step is expanded ---- */
.ft-timeline {
	display: grid;
	gap: 16px;
}

.ft-tl {
	display: grid;
	padding: 8px 0 8px 24px;
	border-left: 3px solid var(--ft-border);
	transition: border-left-color 0.35s ease;
}

.ft-tl.is-active {
	border-left-color: var(--ft-blue);
}

.ft-tl__head {
	display: flex;
	align-items: center;
	gap: 8px;
	cursor: pointer;
}

.ft-tl__head img {
	width: 24px;
	height: 24px;
}

.ft-tl__head h3 {
	margin: 0;
	font-size: 16px;
	font-weight: 600;
	color: var(--ft-text);
}

/* Collapsible description — animate height via grid-template-rows (0fr → 1fr) */
.ft-tl__body {
	display: grid;
	grid-template-rows: 0fr;
	transition: grid-template-rows 0.4s ease;
}

.ft-tl.is-active .ft-tl__body {
	grid-template-rows: 1fr;
}

.ft-tl p {
	overflow: hidden;
	min-height: 0;
	margin: 0;
	padding-left: 32px;
	padding-top: 0;
	font-size: 16px;
	line-height: 22px;
	font-weight: 500;
	color: var(--ft-muted);
	opacity: 0;
	transition: opacity 0.3s ease, padding-top 0.4s ease;
}

.ft-tl.is-active p {
	padding-top: 8px;
	opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
	.ft-tl,
	.ft-tl__body,
	.ft-tl p {
		transition: none;
	}
}

/* ---- ToothView store buttons ---- */
.ft-stores {
	display: flex;
	flex-wrap: wrap;
	gap: 24px;
}

.ft-stores img {
	height: 40px;
}

/* ---- Responsive ---- */
/* The two-column splits (Teo / OneScreen / ToothView / About) use flex-wrap, so
 * below ~1072px (shell < the 460+72+460 two-column basis) each half wraps onto
 * its own row but keeps its desktop max-width — leaving the media stuck to the
 * left with a large empty gap on the right. Switch the splits to the centered,
 * image-on-top single-column mobile layout a touch before that wrap point so
 * they read centered like the mobile design. Hero and products keep the 990px
 * breakpoint below — only the splits move up here. */
@media (max-width: 1080px) {
	.ft-split {
		flex-direction: column;
		gap: 32px;
	}

	.ft-split__content,
	.ft-split__media {
		/* In column mode the flex-basis becomes a VERTICAL basis — reset it so
		 * each half takes its natural height instead of inflating to 460px. */
		flex: 0 0 auto;
		max-width: 100%;
		width: 100%;
	}

	/* Figma mobile: every split section leads with its image on top */
	.ft-split__media {
		order: -1;
	}
}

@media (max-width: 990px) {
	.ft-section {
		padding: 64px 0;
	}

	.ft-hero {
		grid-template-columns: 1fr;
		/* Roomier copy↔media gap than the splits: slide 1's blob is anchored to the
		 * trays (see .ft-hero__media-stack) and peeks above them, so this gap gives
		 * that peek clear space below the Buy Now button instead of crowding it. */
		gap: 64px;
	}

	/* ---- Hero: centered column (Figma mobile) ---- */
	.ft-hero__copy {
		max-width: none;
		justify-items: center;
		text-align: center;
	}

	.ft-hero__title {
		text-align: center;
	}

	.ft-hero__desc {
		max-width: 448px;
		margin-inline: auto;
	}

	.ft-hero__text {
		justify-items: center;
	}

	.ft-hero__subtitle {
		text-align: center;
	}

	.ft-hero__watch {
		justify-self: center;
	}

	.ft-hero__media,
	.ft-hero__media--circle,
	.ft-hero__media--devices {
		justify-content: center;
		min-height: 240px;
	}

	/* Slide 1 trays + blob keep a locked relationship via .ft-hero__media-stack
	 * (blob anchored to the trays box; size capped by the base rule). On mobile the
	 * media gets a little top padding so the blob's upward peek clears the Buy Now
	 * button instead of crowding it. Targeting the bare .ft-hero__media (slide 1
	 * only — slides 2/3 carry a --circle/--devices modifier) keeps this nudge off
	 * the other slides, whose blobs sit lower. */
	.ft-hero__media:not(.ft-hero__media--circle):not(.ft-hero__media--devices) {
		padding-top: 28px;
	}

	/* Slide 2 circle: blob stays anchored to the circle via .ft-hero__circle-wrap,
	 * so its offsets (base rule) hold at every width — no per-breakpoint override.
	 * The single-column layout centres the wrap, so the circle is sized small
	 * enough that the locked lower-right blob still fits without the slide's
	 * overflow:hidden clipping it. */
	.ft-hero__circle-wrap {
		width: 48%;
		margin-left: 0;
	}

	.ft-cards {
		grid-template-columns: repeat(3, minmax(0, 1fr));
		gap: 32px;
	}
}

@media (max-width: 680px) {
	/* Tighter vertical rhythm so sections sit close together (Figma mobile) */
	.ft-section {
		padding: 48px 0;
	}

	.ft-section--hero {
		padding: 40px 0 28px;
	}

	.ft-hero__title {
		font-size: 36px;
		line-height: 44px;
	}

	/* ---- Products: single-card carousel (Figma mobile) ---- */
	.ft-cards {
		position: relative; /* anchor children offsetLeft to the track for dot sync */
		display: flex;
		grid-template-columns: none;
		justify-content: flex-start; /* override desktop centering — keeps card 1 at scroll origin */
		gap: 16px;
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
	}

	.ft-cards::-webkit-scrollbar {
		display: none;
	}

	.ft-card {
		flex: 0 0 100%;
		scroll-snap-align: start;
	}

	.ft-products__dots {
		display: flex;
	}

	/* ---- Hero media per slide (centered, image below) ---- */
	/* Slide 1 — trays + blob. The blob↔trays relationship is locked via
	 * .ft-hero__media-stack, so phones only shrink the wrapper; the blob keeps
	 * its position relative to the trays. */
	.ft-hero__media-stack {
		max-width: 430px;
	}

	/* Slide 2 circle (circle-wrap + blob) is handled in the <=990 block — its
	 * locked offsets and centered sizing apply across the whole single-column range. */

	/* Slide 3 — devices + blob. Locked via .ft-hero__devices-wrap, so phones only
	 * shrink the wrapper; the blob keeps its position relative to the devices. */
	.ft-hero__devices-wrap {
		width: 92%;
		max-width: 380px;
	}
}

/* ---- Extra-small phones (down to the 325px min target) ----
 * The default shell reserves 40px of padding EACH side (--ft-shell: 100% - 80px).
 * At ~325px that leaves only ~245px of content, which forces the ToothView store
 * badges onto two rows and squeezes the copy. Halve the side padding here so the
 * two store buttons fit one row and the content has room. */
@media (max-width: 380px) {
	.ft-main {
		--ft-shell: min(1480px, 100% - 40px);
	}

	.ft-stores {
		gap: 16px;
	}
}

/* ---- 4K / ultra-wide ----
 * Same desktop design, uniformly scaled up ~2.2x so it reads as the desktop
 * layout zoomed in — not a small island of text in a huge shell. The shell
 * widens 1480->3320px (2.24x) to line up with the shared header
 * (homePage_design.css scales --shop-shell: 3320px at this same breakpoint),
 * so content widths AND type/spacing are scaled by the SAME factor. This keeps
 * the desktop ratios intact: splits stay ~90% of the shell and the hero sits
 * on the same side margin as the sections below it (previously the hero filled
 * the full shell while the sections were stuck in a narrow centered column,
 * which made the hero look like it had no left/right padding).
 */
@media (min-width: 3000px) {
	.ft-main {
		--ft-shell: min(3320px, 100% - 180px);
	}

	.ft-section {
		padding: 176px 0;
	}

	.ft-section--hero {
		padding: 124px 0 80px;
	}

	/* Type scale (~2.2x) */
	.ft-eyebrow {
		font-size: 30px;
	}

	.ft-title {
		font-size: 52px;
		line-height: 64px;
	}

	.ft-hero__title {
		font-size: 78px;
		line-height: 96px;
	}

	.ft-hero__subtitle,
	.ft-feature__head h3,
	.ft-tl__head h3 {
		font-size: 34px;
	}

	.ft-card__info h3 {
		font-size: 44px;
	}

	.ft-lead,
	.ft-hero__desc,
	.ft-card__info p,
	.ft-feature p,
	.ft-tl p {
		font-size: 34px;
		line-height: 48px;
	}

	.ft-feature p {
		padding-left: 66px;
	}

	.ft-tl p {
		padding-left: 70px;
	}

	/* Buttons (~2.2x) */
	.ft-btn,
	.ft-btn i,
	.ft-hero__watch {
		font-size: 34px;
		gap: 26px;
	}

	.ft-btn--primary {
		padding: 26px 70px;
	}

	.ft-btn--outline {
		padding: 18px 53px;
	}

	/* Hero (~2x of the 1920 design) — gutter stays 18.75% via the %-based shell
	 * override, so no carousel cap is needed (the old 2798px cap aligned the hero
	 * with the splits and would fight the %-based gutter here). */
	.ft-hero {
		grid-template-columns: minmax(0, 960px) minmax(0, 1fr);
		gap: 96px;
	}

	.ft-hero__copy {
		max-width: 960px; /* 480 × 2 */
		gap: 53px;
	}

	.ft-hero__desc {
		max-width: 896px; /* 448 × 2 */
	}

	.ft-hero__badge {
		padding: 18px 31px;
		font-size: 30px;
	}

	.ft-hero__badge img {
		width: 42px;
		height: 42px;
	}

	.ft-hero__media,
	.ft-hero__media--devices,
	.ft-hero__media--circle {
		min-height: 792px;
	}

	/* Foreground slide images keep their desktop max-widths by default, so in
	 * the wider 4K media column (~1532px) they look half-size. Scale the caps
	 * ~2.24x to match the column: product/devices fill it (as on desktop) and
	 * the circle stays ~71% of it (its desktop ratio). Blobs/shapes are % based
	 * and already scale. The slide 1 trays now fill their wrapper, so the cap
	 * lives on the wrapper here (the blob, being % of the wrapper, scales with it). */
	.ft-hero__media-stack {
		max-width: 1560px;
	}

	.ft-hero__devices-wrap {
		max-width: 1560px;
	}

	.ft-hero__dots {
		gap: 18px;
		margin-top: 62px;
	}

	.ft-hero__dots button {
		width: 18px;
		height: 18px;
	}

	.ft-hero__dots button.is-active {
		width: 176px;
	}

	/* Physical products (~2.2x) */
	.ft-products__head {
		max-width: 1408px;
		margin-bottom: 124px;
	}

	.ft-cards {
		grid-template-columns: repeat(3, 480px); /* 240 × 2 → 960px block, 25% gutter */
		gap: 240px; /* 120 × 2 */
	}

	.ft-card {
		gap: 35px;
	}

	.ft-card__img,
	.ft-card__img img {
		height: 418px;
		max-height: 418px;
	}

	.ft-card__info {
		gap: 18px;
	}

	/* Split layouts (~2x of the 1920 design) — 15.625% gutter per side:
	 * max-width 2640 = 3840 − 2×600; space-between pins content/media to the
	 * gutters (inherited from the base .ft-split). */
	.ft-split {
		max-width: 2640px;
		gap: 158px;
	}

	.ft-split__content {
		flex-basis: 1030px;
		max-width: 1080px; /* 540 × 2 */
		gap: 70px;
	}

	.ft-split__media {
		flex-basis: 1030px;
		max-width: 1280px; /* 640 × 2 */
	}

	.ft-split__media img {
		border-radius: 53px;
	}

	/* Feature list / timeline */
	.ft-features,
	.ft-timeline {
		gap: 35px;
	}

	.ft-feature__head,
	.ft-tl__head {
		gap: 18px;
	}

	.ft-feature__head img {
		width: 48px;
		height: 48px;
	}

	.ft-tl {
		padding: 18px 0 18px 53px;
		border-left-width: 6px;
	}

	.ft-tl__head img {
		width: 53px;
		height: 53px;
	}

	/* ToothView store buttons */
	.ft-stores {
		gap: 53px;
	}

	.ft-stores img {
		height: 88px;
	}
}

/* ---- Footer (Figma Frame 1000011867) ----
 * Override the shared footer grid: brand pinned far left, the four link
 * columns clustered on the right ~100px apart. Desktop-only — the shared
 * mobile footer layout is left as-is.
 *
 * Scoped to body.ft-page (Nuxt port): in the PHP site this page was the last
 * stylesheet so an unscoped rule won on source order. Here index.css is shared
 * by every ft-page (terms/shipping/accessibility/about/contact) and is NOT
 * always the last sheet, so the unscoped rule lost to footer.css and the footer
 * fell back to the evenly-spread base grid. Scoping to body.ft-page gives it
 * higher specificity than footer.css so it wins regardless of load order —
 * exactly how every other page CSS (e.g. body.mp-page in modupro.css) does it.
 */
@media (min-width: 991px) {
	body.ft-page .shop-footer__grid {
		grid-template-columns: 1fr repeat(4, minmax(0, max-content));
		gap: 100px;
		align-items: start;
	}

	body.ft-page .shop-footer__brand {
		max-width: 370px;
	}
}

/* ---- Mobile footer (Figma): brand on top, link columns in a 3-up grid ----
 * Page-scoped to body.ft-page so it only restyles THIS page's footer; the
 * shared footer.css collapses to a single column at <=765px on every other
 * page. Higher specificity than footer.css's rules, so it wins regardless of
 * load order. */
@media (max-width: 680px) {
	body.ft-page .shop-footer__main {
		padding: 48px 0;
	}

	body.ft-page .shop-footer__grid {
		display: grid;
		grid-template-columns: repeat(3, minmax(0, 1fr));
		gap: 28px 16px;
		align-items: start;
	}

	body.ft-page .shop-footer__brand {
		grid-column: 1 / -1;
		margin-bottom: 4px;
	}

	body.ft-page .shop-footer__column h3 {
		font-size: 16px;
	}

	body.ft-page .shop-footer__column a,
	body.ft-page .shop-footer__brand p {
		font-size: 15px;
		line-height: 1.9;
	}

	/* Keep the policy bar on a single horizontal row (Figma) — override the
	 * shared <=400px rule that stacks it vertically. */
	body.ft-page .shop-footer__bar-inner {
		gap: 12px;
	}

	body.ft-page .shop-footer__policies {
		flex-direction: row;
		flex-wrap: nowrap;
		align-items: center;
		gap: 14px;
	}

	body.ft-page .shop-footer__policies a {
		font-size: 10px;
		white-space: nowrap;
	}

	body.ft-page .shop-footer__youtube img {
		height: 22px;
	}
}

/* Extra-small phones (down to the 325px min target): the rule above pins the
 * policy bar to a single nowrap row, which overflows the viewport at this size
 * ("Accessibility Statement" + the YouTube icon get clipped off the right edge,
 * adding horizontal page scroll). Let it wrap onto multiple lines so nothing is
 * cut off. Placed AFTER the <=680 block so it wins on source order (same
 * specificity). */
@media (max-width: 380px) {
	body.ft-page .shop-footer__bar-inner {
		flex-wrap: wrap;
		gap: 10px;
	}

	body.ft-page .shop-footer__policies {
		flex-wrap: wrap;
		gap: 8px 12px;
	}
}

/* ---- 4K / ultra-wide: shared header + footer ----
 * The header (header.css) only scales ~1.25x at 4K and the footer (footer.css)
 * not at all, so on a 3840px screen both bars look tiny next to this page's
 * ~2.2x-scaled content. Scale them by the same ~2.2x here. Scoped to
 * body.ft-page so ONLY this page is affected — the shared header/footer keep
 * their default 4K sizing on every other storefront page (whose content is
 * not scaled up). The shell stays at --shop-shell: 3320px, so the bars' inner
 * content still lines up edge-to-edge with the page content.
 */
@media (min-width: 3000px) {
	body.ft-page {
		--shop-header-height: 210px;
	}

	/* Header */
	body.ft-page .shop-header__brand img {
		width: 388px;
	}

	body.ft-page .shop-nav__link {
		gap: 18px;
		padding: 20px 26px;
		font-size: 33px;
	}

	body.ft-page .shop-nav__caret {
		font-size: 31px;
	}

	body.ft-page .shop-header__actions {
		gap: 31px;
	}

	body.ft-page .shop-header__actions a,
	body.ft-page .shop-header__icon-btn,
	body.ft-page .shop-header__search-trigger {
		width: 88px;
		height: 88px;
		font-size: 44px;
	}

	body.ft-page .shop-desktop-search {
		width: 88px;
		height: 106px;
	}

	body.ft-page .shop-desktop-search input {
		font-size: 40px;
	}

	/* Footer */
	body.ft-page .shop-footer__main {
		padding: 158px 0;
	}

	body.ft-page .shop-footer__grid {
		gap: 220px;
	}

	body.ft-page .shop-footer__brand {
		max-width: 810px;
	}

	body.ft-page .shop-footer__brand img {
		width: 360px;
		margin-bottom: 35px;
	}

	body.ft-page .shop-footer__brand p,
	body.ft-page .shop-footer__column a {
		font-size: 35px;
	}

	body.ft-page .shop-footer__column h3 {
		margin-bottom: 26px;
		font-size: 40px;
	}

	body.ft-page .shop-footer__bar-inner {
		gap: 53px;
		padding: 62px 0;
	}

	body.ft-page .shop-footer__policies {
		gap: 106px;
	}

	body.ft-page .shop-footer__policies a {
		font-size: 35px;
	}

	body.ft-page .shop-footer__youtube img {
		height: 62px;
	}
}
