/**
 * WLRE Theme - Hero Section Styles
 *
 * Full-bleed hero with overlay heading and search panel.
 */

/* === Hero wrapper ===
 * Header is position:absolute and transparent on hero pages, so it overlays
 * the top of the hero. The heading top edge sits behind the header — this
 * is the intended design.
 *
 * Full viewport height for a cinematic above-the-fold experience.
 * 100dvh adapts to dynamic browser UI (mobile URL bar) without the
 * iOS Safari "100vh overshoots viewport" bug. 100vh kept as fallback
 * for older browsers. */
.wlre-hero {
	position: relative;
	min-height: 100vh;
	min-height: 100dvh;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	padding: var(--wlre-header-height) var(--wlre-space-100) var(--wlre-space-80);
}

/* Background carousel: full-bleed stack of slides; only the .is-active
 * one is visible. hero-carousel.js changes the active class only after
 * explicit dot clicks. */
.wlre-hero__bg {
	position: absolute;
	inset: 0;
	z-index: 0;
	overflow: hidden; /* contain the Ken Burns scale(1.06) so slides don't bleed outside the hero */
}

.wlre-hero__bg-slide {
	position: absolute;
	inset: 0;
	background-color: var(--wlre-color-text-900);
	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
	opacity: 0;
	transition: opacity 0.8s ease;
}

.wlre-hero__bg-slide.is-active {
	opacity: 1;
}

/* Dark overlay on top of the active slide for text readability — placed
 * as a pseudo-element so it composites over every rotating image. */
.wlre-hero__bg::after {
	content: "";
	position: absolute;
	inset: 0;
	background:
		linear-gradient(180deg, rgba(0,0,0,0.4) 0%, rgba(0,0,0,0) 17%),
		linear-gradient(0deg, rgba(0,0,0,0.4) 0%, rgba(0,0,0,0) 17%),
		linear-gradient(90deg, rgba(0,0,0,0.66) 0%, rgba(0,0,0,0.66) 100%);
	pointer-events: none;
	z-index: 1;
}

/* Bar-style slide indicators — Figma 6036-91361. Four full-width bars
 * fill the 1240 content zone (4 × 295 + 3 × 20 gap). Active bar =
 * full-opacity white; inactive = 34% white. Position: bottom 48px from
 * hero edge, horizontally centred and capped at the content width. */
.wlre-hero__dots {
	position: absolute;
	bottom: var(--wlre-space-48);
	left: 50%;
	transform: translateX(-50%);
	display: flex;
	gap: var(--wlre-space-20);
	width: min(var(--wlre-content-width), calc(100vw - var(--wlre-space-100) * 2));
	z-index: 3;
}

.wlre-hero__dot {
	flex: 1 1 0;
	min-width: 0;
	height: 2px;
	border: 0;
	background: rgba(255, 255, 255, 0.34);
	padding: 0;
	cursor: pointer;
	border-radius: 2px;
	transition: background 0.25s ease, opacity 0.25s ease;
	/* Expand hit-target via pseudo-element so the thin bar remains touch-friendly. */
	position: relative;
}

.wlre-hero__dot::after {
	content: "";
	position: absolute;
	inset-block: -14px;
	inset-inline: 0;
	/* invisible extended hit target to keep tap-size ≥ 28px */
}

/* Progress fill — width animates 0% → 100% over the auto-advance window
 * when the dot is active and motion is permitted. Logical-property anchor
 * (inset-inline-start) makes the fill grow from the reading start in both
 * LTR and RTL automatically. Sits below ::after so taps still hit the
 * touch-target extender. */
.wlre-hero__dot::before {
	content: "";
	position: absolute;
	inset-block: 0;
	inset-inline-start: 0;
	inset-inline-end: auto;
	width: 0;
	background: var(--wlre-color-white);
	border-radius: inherit;
	pointer-events: none;
	z-index: 1;
}

.wlre-hero__dot:hover {
	background: rgba(255, 255, 255, 0.6);
}

.wlre-hero__dot.is-active {
	background: var(--wlre-color-white);
}

.wlre-hero__content {
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	width: 100%;
	max-width: var(--wlre-content-width);
	gap: var(--wlre-space-40);
}

/* === Heading === */
.wlre-hero__heading {
	font-family: var(--wlre-font-heading);
	font-weight: 600;
	font-size: var(--wlre-font-size-h1);
	line-height: var(--wlre-line-height-heading);
	text-align: center;
	color: var(--wlre-color-white);
	margin: 0;
}

.wlre-hero__heading-accent {
	color: var(--wlre-color-accent-500);
}

/* === Mobile CTA (hidden on desktop) ==================================
 * Figma 6118-216984 — replaces the full search card on mobile. Opens the
 * Search Filters bottom sheet (patterns/mobile-search-bottomsheet.php). */
.wlre-hero__cta-mobile {
	display: none;
}

@media (max-width: 767px) {
	.wlre-hero__cta-mobile {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		gap: var(--wlre-space-8);
		width: 100%;
		max-width: 343px;
		height: 56px;
		padding: var(--wlre-space-16) var(--wlre-space-24);
		background: var(--wlre-color-white);
		color: var(--wlre-color-text-900);
		border: none;
		border-radius: var(--wlre-radius-sm);
		font-family: var(--wlre-font-body);
		font-weight: 700;
		font-size: var(--wlre-font-size-l);
		line-height: 1;
		cursor: pointer;
		text-decoration: none;
		box-shadow: var(--wlre-shadow-card);
		transition: background-color 0.2s ease;
	}

	.wlre-hero__cta-mobile:hover {
		background: var(--wlre-color-surface-50);
	}

	.wlre-hero__cta-mobile-icon {
		display: inline-flex;
		width: var(--wlre-space-24);
		height: var(--wlre-space-24);
		flex-shrink: 0;
	}

	.wlre-hero__cta-mobile-icon svg {
		width: 100%;
		height: 100%;
	}

	/* Hide the desktop search card on mobile — CTA replaces it. */
	.wlre-hero__search {
		display: none;
	}
}

/* === Search panel ===
 * Content-sized: 3 city cards (282px) + 2 gaps (12px) + 2 paddings (24px)
 * = 918px, matching the desktop Figma frame.
 */
.wlre-hero__search {
	background: var(--wlre-color-white);
	border-radius: var(--wlre-radius-20);
	padding: var(--wlre-space-24);
	width: 100%;
	max-width: min(918px, calc(100vw - 80px));
	box-sizing: border-box;
	box-shadow: var(--wlre-shadow-card);
}

.wlre-hero__search[data-state="many"] {
	max-width: min(711px, calc(100vw - 80px));
	padding: var(--wlre-space-32);
}

/* Standalone single variant (whole hero is one city, no Buy/Rent toggle): the
 * panel collapses to nothing and the white pill IS the search input. When the
 * single state is only one side of a toggle (--solo absent) the white panel is
 * kept so the toggle and label stay legible over the dark hero image. */
.wlre-hero__search--solo[data-state="single"] {
	max-width: min(660px, calc(100vw - 80px));
	padding: 0;
	background: transparent;
	border-radius: 0;
	box-shadow: none;
}

.wlre-hero__search-top {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-bottom: var(--wlre-space-24);
}

.wlre-hero__search-label {
	font-family: var(--wlre-font-heading);
	font-weight: 600;
	font-size: var(--wlre-font-size-h3);
	line-height: var(--wlre-line-height-heading);
	color: var(--wlre-color-text-900);
	margin: 0;
}

/* Buy / Rent toggle — Figma 6478:267120 / 6118:214814. */
.wlre-hero__toggle {
	display: flex;
	gap: 2px;
	align-items: center;
	justify-content: center;
	background: #f5f5f5;
	border: 0.5px solid var(--wlre-color-neutral-300, #d0d0d0);
	border-radius: 999px;
	padding: var(--wlre-space-4);
	height: 64px;
	box-sizing: border-box;
}

.wlre-hero__toggle-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 0;
	height: 56px;
	font-family: var(--wlre-font-body);
	font-weight: 700;
	font-size: var(--wlre-font-size-xl);
	line-height: var(--wlre-line-height-body);
	padding: var(--wlre-space-12) var(--wlre-space-24);
	border: 2.333px solid transparent;
	border-radius: 999px;
	background: transparent;
	color: var(--wlre-color-text-900);
	cursor: pointer;
	box-sizing: border-box;
	transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease, font-weight 0.2s ease;
}

.wlre-hero__toggle-btn.is-active {
	border-color: var(--wlre-color-teal-700, #008d84);
	color: var(--wlre-color-text-900);
	background: var(--wlre-color-success-50, #f3faf4);
}

/* City buttons row — adapts to data-count for the 1/2/3-locations Figma
 * variants. data-count='2' (Figma 6478:264573) shows two wide cards filling
 * the panel; data-count='3' is the canonical default (Figma 6118:214813). */
.wlre-hero__cities {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--wlre-space-12);
}

.wlre-hero__cities[data-count="2"] {
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

.wlre-hero__cities[hidden] {
	display: none;
}

.wlre-hero__city-btn {
	display: flex;
	align-items: center;
	gap: 6px;
	padding: var(--wlre-space-24);
	border-radius: var(--wlre-radius-lg);
	font-family: var(--wlre-font-heading);
	font-weight: 600;
	font-size: var(--wlre-font-size-h6);
	line-height: var(--wlre-line-height-heading);
	cursor: pointer;
	transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
	width: 100%;
	min-height: 76px;
	box-sizing: border-box;
	justify-content: center;
	text-decoration: none;
	white-space: nowrap;
	border: 0.5px solid var(--wlre-color-text-900);
	background: transparent;
	color: var(--wlre-color-text-900);
}

/* In the 2-card variant, give cards a touch more vertical breathing room so
 * the panel feels balanced (Figma 6478:264573). */
.wlre-hero__cities[data-count="2"] .wlre-hero__city-btn {
	min-height: 80px;
	font-size: var(--wlre-font-size-h5);
}

.wlre-hero__city-btn--featured {
	gap: var(--wlre-space-12);
	background: var(--wlre-color-text-900);
	color: var(--wlre-color-white);
	border-color: var(--wlre-color-text-900);
}

.wlre-hero__city-btn:hover {
	background: var(--wlre-color-text-900);
	color: var(--wlre-color-white);
	border-color: var(--wlre-color-text-900);
}

.wlre-hero__city-arrow {
	display: inline-flex;
	flex-shrink: 0;
	width: var(--wlre-space-24);
	height: var(--wlre-space-24);
}

.wlre-hero__city-arrow svg {
	width: 100%;
	height: 100%;
}

.wlre-hero__city-arrow path {
	transition: fill 0.2s ease;
}

.wlre-hero__city-btn--featured .wlre-hero__city-arrow path,
.wlre-hero__city-btn:hover .wlre-hero__city-arrow path,
.wlre-hero__city-btn:focus-visible .wlre-hero__city-arrow path {
	fill: var(--wlre-color-white);
}

/* === Single-search variant (1 city) — Figma 6478:265845
 * When inventory has only 1 city the hero collapses to a single white pill
 * shaped like a search input. Clicking it routes to the prefiltered search
 * for that city. No toggle, no city cards. */
.wlre-hero__simple-search {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--wlre-space-4);
	background: var(--wlre-color-white);
	border-radius: var(--wlre-radius-sm);
	padding-inline: var(--wlre-space-24);
	height: 56px;
	width: 100%;
	color: var(--wlre-color-text-900);
	text-decoration: none;
	font-family: var(--wlre-font-body);
	font-size: var(--wlre-font-size-l);
	font-weight: 700;
	line-height: var(--wlre-line-height-body);
	transition: background-color 0.2s ease;
	border: 0;
}

.wlre-hero__simple-search:hover,
.wlre-hero__simple-search:focus-visible {
	background: var(--wlre-color-surface-50);
}

.wlre-hero__simple-search[hidden] {
	display: none;
}

/* Framed variant — used when the single-city pill sits inside the white panel
 * (single state reached via the Buy/Rent toggle). A plain white pill would be
 * invisible on the white card, so it gets a surface fill + hairline border. */
.wlre-hero__simple-search--framed {
	background: var(--wlre-color-surface-50);
	border: 1px solid var(--wlre-color-neutral-300, #d0d0d0);
}

.wlre-hero__simple-search--framed:hover,
.wlre-hero__simple-search--framed:focus-visible {
	background: var(--wlre-color-white);
}

.wlre-hero__simple-search-icon {
	display: inline-flex;
	flex-shrink: 0;
	width: 24px;
	height: 24px;
	color: var(--wlre-color-text-900);
}

.wlre-hero__simple-search-icon svg {
	width: 100%;
	height: 100%;
}

.wlre-hero__simple-search-label {
	color: var(--wlre-color-text-900);
	font-weight: 700;
}

/* === Many-locations variant (4+ cities) — Figma 6478:267117
 * Two custom listbox controls separated by a hairline, plus an accent submit
 * pill with magnifier icon. The hidden inputs preserve normal GET form
 * behaviour without exposing a browser-native select menu. */
.wlre-hero__filters {
	display: flex;
	align-items: stretch;
	justify-content: center;
	gap: 9px;
	background: transparent;
	border-radius: 0;
	padding: 0;
}

.wlre-hero__filters[hidden] {
	display: none;
}

/* Empty state inside the hero panel (no listings for the active purpose, e.g.
 * no rentals). Reuses the shared .wlre-empty--page component but trims its
 * standalone-404 padding so it sits compactly in the search panel. */
.wlre-hero__empty[hidden] {
	display: none;
}

.wlre-hero__empty .wlre-empty--page {
	padding: 8px 16px;
}

.wlre-hero__empty .wlre-empty__art {
	width: 56px;
	height: 56px;
	margin-bottom: 12px;
}

.wlre-hero__filter-group {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 17px var(--wlre-space-20);
	background: var(--wlre-color-white);
	border-radius: var(--wlre-radius-sm);
	box-shadow: var(--wlre-shadow-card);
}

.wlre-hero__select {
	position: relative;
	flex: 0 0 229px;
	width: 229px;
	min-width: 0;
}

.wlre-hero__select-trigger {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--wlre-space-12);
	width: 100%;
	min-height: 40px;
	padding: 0;
	background: transparent;
	border: 0;
	color: var(--wlre-color-text-900);
	font-family: var(--wlre-font-body);
	text-align: left;
	cursor: pointer;
}

.wlre-hero__select-trigger:focus-visible {
	outline: 2px solid var(--wlre-color-accent-500);
	outline-offset: 6px;
	border-radius: var(--wlre-radius-sm);
}

.wlre-hero__select-copy {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
}

.wlre-hero__filter-label {
	font-family: var(--wlre-font-body);
	font-size: 12px;
	font-weight: 600;
	color: var(--wlre-color-text-900);
	line-height: 1.2;
}

.wlre-hero__select-value {
	font-family: var(--wlre-font-body);
	font-size: var(--wlre-font-size-l);
	font-weight: 400;
	line-height: var(--wlre-line-height-body);
	color: var(--wlre-color-text-900);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.wlre-hero__select-icon {
	display: inline-flex;
	width: var(--wlre-space-16);
	height: var(--wlre-space-16);
	flex-shrink: 0;
	color: var(--wlre-color-text-900);
	transition: transform 0.2s ease;
}

.wlre-hero__select-icon svg {
	width: 100%;
	height: 100%;
}

.wlre-hero__select.is-open .wlre-hero__select-icon {
	transform: rotate(180deg);
}

.wlre-hero__select-menu {
	position: absolute;
	top: calc(100% + var(--wlre-space-12));
	left: -12px;
	z-index: 20;
	width: 278px;
	max-height: min(340px, calc(100vh - 180px));
	overflow-y: auto;
	padding: var(--wlre-space-8) 0;
	background: var(--wlre-color-white);
	border: 0.5px solid rgba(10, 36, 56, 0.14);
	border-radius: var(--wlre-radius-md);
	box-shadow: 0 16px 40px rgba(10, 36, 56, 0.18);
}

.wlre-hero__select-menu[hidden] {
	display: none;
}

.wlre-hero__select-option {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--wlre-space-12);
	width: 100%;
	min-height: 44px;
	padding: var(--wlre-space-10, 10px) var(--wlre-space-20);
	background: var(--wlre-color-white);
	border: 0;
	color: var(--wlre-color-text-900);
	font-family: var(--wlre-font-body);
	font-size: var(--wlre-font-size-l);
	line-height: var(--wlre-line-height-body);
	text-align: left;
	cursor: pointer;
}

.wlre-hero__select-option:hover,
.wlre-hero__select-option:focus-visible {
	background: var(--wlre-color-success-50, #f3faf4);
	outline: none;
}

.wlre-hero__select-option.is-selected {
	font-weight: 700;
	background: var(--wlre-color-success-50, #f3faf4);
}

.wlre-hero__select-check {
	display: inline-flex;
	width: var(--wlre-space-20);
	height: var(--wlre-space-20);
	flex-shrink: 0;
	color: var(--wlre-color-teal-700, #008d84);
	visibility: hidden;
}

.wlre-hero__select-check svg {
	width: 100%;
	height: 100%;
}

.wlre-hero__select-option.is-selected .wlre-hero__select-check {
	visibility: visible;
}

.wlre-hero__filter-divider {
	width: 1px;
	background: rgba(10, 36, 56, 0.18);
	align-self: stretch;
	margin-block: 0;
}

.wlre-hero__filter-submit {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--wlre-space-4);
	width: 120px;
	height: 74px;
	padding: var(--wlre-space-16) var(--wlre-space-24);
	background: var(--wlre-color-accent-500);
	color: var(--wlre-color-text-900);
	border: 0;
	border-radius: var(--wlre-radius-sm);
	font-family: var(--wlre-font-body);
	font-weight: 700;
	font-size: var(--wlre-font-size-l);
	line-height: var(--wlre-line-height-body);
	cursor: pointer;
	transition: background-color 0.2s ease;
	white-space: nowrap;
}

.wlre-hero__filter-submit:hover,
.wlre-hero__filter-submit:focus-visible {
	background: var(--wlre-color-accent-600);
}

.wlre-hero__filter-submit-icon {
	display: inline-flex;
	width: var(--wlre-space-24);
	height: var(--wlre-space-24);
}

.wlre-hero__filter-submit-icon svg {
	width: 100%;
	height: 100%;
}

/* === Trust badges === */
.wlre-hero__trust {
	font-family: var(--wlre-font-body);
	font-weight: 400;
	font-size: var(--wlre-font-size-l);
	line-height: var(--wlre-line-height-body);
	color: var(--wlre-color-white);
	text-align: center;
	margin: 0;
	max-width: 520px;
}

.wlre-hero__trust-break {
	display: none;
}

@media (max-width: 767px) {
	.wlre-hero__trust-break {
		display: block;
	}
}

/* === Responsive === */
@media (max-width: 1180px) and (min-width: 768px) {
	.wlre-hero {
		padding: var(--wlre-space-40) var(--wlre-space-40);
	}

	.wlre-hero__heading {
		font-size: 36px;
	}

	.wlre-hero__cities {
		flex-wrap: wrap;
	}

	.wlre-hero__city-btn {
		flex: 0 0 calc(50% - 6px);
		min-width: 0;
		width: auto;
	}
}

/* === Hero search state transitions ====================================
 * Three-phase choreographed swap (driven by hero-carousel.js):
 *
 *   1. .is-leaving-state — body content fades out (140ms). The search-top
 *      (label + toggle) is intentionally NOT targeted — the toggle stays
 *      anchored and visible throughout, per the segmented-control UX
 *      pattern (Apple/Linear/Stripe).
 *
 *   2. swap point — JS locks panel height, mutates DOM, then transitions
 *      height + max-width + padding + background + border + shadow in
 *      lockstep over 240ms. The panel never contains both old and new
 *      body groups simultaneously, so there's no transient height jump.
 *
 *   3. .is-entering-state — new body's direct children stagger in (50ms,
 *      110ms, 170ms delays) with a small rise. Animation fill-mode "both"
 *      pins the from-state during the delay so children stay invisible
 *      until their turn.
 *
 * Easing: cubic-bezier(0.32, 0.72, 0, 1) — Linear app's signature curve,
 * fast ramp into a gentle settle.
 */

@media (prefers-reduced-motion: no-preference) {
	/* === Ken Burns on the active background slide ====================
	 * Slow, almost-imperceptible zoom (1.0 → 1.06 over 8s) on whichever
	 * slide currently has .is-active. Re-triggers when the class is
	 * re-applied (next cycle through the loop), thanks to the explicit
	 * `animation: none` on the inactive state. forwards keeps the slide
	 * at its zoomed end-state during the 0.8s opacity cross-fade out. */
	.wlre-hero__bg-slide {
		animation: none;
		transform-origin: center center;
	}

	.wlre-hero__bg-slide.is-active {
		animation: wlre-hero-kenburns 8s cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
	}

	@keyframes wlre-hero-kenburns {
		from { transform: scale(1); }
		to { transform: scale(1.06); }
	}

	/* === Dot bar progress indicator ==================================
	 * The active dot's progress fill grows from 0% to 100% width over
	 * the JS auto-advance window (5s, kept in sync with AUTO_ADVANCE_MS
	 * in hero-carousel.js). Active bar's background drops to the same
	 * 34% white as inactive so the white fill is visible against it.
	 * The fill pauses in lockstep with the JS timer via [data-paused]
	 * on .wlre-hero — JS toggles that attribute on hover/focus/hidden,
	 * and the CSS animation-play-state freezes mid-progress. With
	 * reduced-motion the rule below doesn't apply, so the active bar
	 * just shows its solid white background as before. */
	.wlre-hero__dot.is-active {
		background: rgba(255, 255, 255, 0.34);
	}

	.wlre-hero__dot.is-active::before {
		animation: wlre-hero-dot-progress 5s linear forwards;
	}

	.wlre-hero[data-paused] .wlre-hero__dot.is-active::before {
		animation-play-state: paused;
	}

	@keyframes wlre-hero-dot-progress {
		from { width: 0; }
		to   { width: 100%; }
	}

	/* === Entrance animation — one-shot on first paint ================
	 * Heading → search panel → trust → dot bar, staggered. animation-fill
	 * "both" pins the from-state during the delay so each layer stays
	 * invisible until its turn. Curve matches the search-state morph
	 * below for a unified feel. */
	.wlre-hero__heading,
	.wlre-hero__cta-mobile,
	.wlre-hero__search,
	.wlre-hero__trust {
		animation: wlre-hero-rise-in 720ms cubic-bezier(0.32, 0.72, 0, 1) both;
	}

	.wlre-hero__dots {
		animation: wlre-hero-fade-in 720ms cubic-bezier(0.32, 0.72, 0, 1) both;
	}

	.wlre-hero__heading      { animation-delay: 100ms; }
	.wlre-hero__cta-mobile   { animation-delay: 280ms; }
	.wlre-hero__search       { animation-delay: 280ms; }
	.wlre-hero__trust        { animation-delay: 460ms; }
	.wlre-hero__dots         { animation-delay: 600ms; }

	@keyframes wlre-hero-rise-in {
		from {
			opacity: 0;
			transform: translateY(16px);
		}
		to {
			opacity: 1;
			transform: translateY(0);
		}
	}

	@keyframes wlre-hero-fade-in {
		from { opacity: 0; }
		to   { opacity: 1; }
	}

	.wlre-hero__search {
		transition:
			max-width 240ms cubic-bezier(0.32, 0.72, 0, 1),
			padding 240ms cubic-bezier(0.32, 0.72, 0, 1),
			background-color 240ms cubic-bezier(0.32, 0.72, 0, 1),
			border-radius 240ms cubic-bezier(0.32, 0.72, 0, 1),
			box-shadow 240ms cubic-bezier(0.32, 0.72, 0, 1),
			height 240ms cubic-bezier(0.32, 0.72, 0, 1);
	}

	/* Clip body overflow during the morph so the height interpolation
	 * doesn't reveal partially-faded content poking out the bottom. */
	.wlre-hero__search.is-leaving-state,
	.wlre-hero__search.is-entering-state {
		overflow: hidden;
	}

	.wlre-hero__cities,
	.wlre-hero__filters {
		transition: opacity 140ms cubic-bezier(0.32, 0.72, 0, 1);
	}

	/* Phase 1: body fades out. Toggle and label stay at full opacity. */
	.wlre-hero__search.is-leaving-state .wlre-hero__cities,
	.wlre-hero__search.is-leaving-state .wlre-hero__filters {
		opacity: 0;
		pointer-events: none;
	}

	/* Phase 3: each direct child of the entering body group rises into
	 * place sequentially, giving the swap a "content materializes" feel
	 * instead of a flat crossfade. Covers up to 3 children — matches
	 * pair (2 chips), triple (3 chips), and many (filter-group + submit). */
	.wlre-hero__search.is-entering-state .wlre-hero__cities > *,
	.wlre-hero__search.is-entering-state .wlre-hero__filters > * {
		animation: wlre-hero-child-in 320ms cubic-bezier(0.32, 0.72, 0, 1) both;
	}

	.wlre-hero__search.is-entering-state .wlre-hero__cities > *:nth-child(1),
	.wlre-hero__search.is-entering-state .wlre-hero__filters > *:nth-child(1) {
		animation-delay: 50ms;
	}

	.wlre-hero__search.is-entering-state .wlre-hero__cities > *:nth-child(2),
	.wlre-hero__search.is-entering-state .wlre-hero__filters > *:nth-child(2) {
		animation-delay: 110ms;
	}

	.wlre-hero__search.is-entering-state .wlre-hero__cities > *:nth-child(3),
	.wlre-hero__search.is-entering-state .wlre-hero__filters > *:nth-child(3) {
		animation-delay: 170ms;
	}

	@keyframes wlre-hero-child-in {
		from {
			opacity: 0;
			transform: translateY(8px);
		}
		to {
			opacity: 1;
			transform: translateY(0);
		}
	}
}

@media (max-width: 767px) {
	.wlre-hero {
		min-height: 100svh;
		padding: var(--wlre-space-40) var(--wlre-space-16);
		justify-content: center;
	}

	.wlre-hero__bg::after {
		background:
			linear-gradient(-0.820764109deg, rgba(0, 0, 0, 0.4) 10.348%, rgba(0, 0, 0, 0) 16.689%),
			linear-gradient(-3.133082482deg, rgba(0, 0, 0, 0) 81.268%, rgba(0, 0, 0, 0.4) 88.331%),
			linear-gradient(90deg, rgba(0, 0, 0, 0.66) 0%, rgba(0, 0, 0, 0.66) 100%);
	}

	.wlre-hero__content {
		gap: 0;
	}

	.wlre-hero__heading {
		font-size: var(--wlre-font-size-h3);
		max-width: 343px;
		margin-bottom: var(--wlre-space-40);
	}

	.wlre-hero__cta-mobile {
		margin-bottom: var(--wlre-space-20);
	}

	.wlre-hero__search {
		padding: var(--wlre-space-20);
		max-width: calc(100vw - 40px);
	}

	.wlre-hero__search-top {
		flex-direction: column;
		align-items: flex-start;
		gap: var(--wlre-space-16);
	}

	.wlre-hero__search-label {
		font-size: var(--wlre-font-size-xl);
	}

	.wlre-hero__toggle {
		height: var(--wlre-space-48);
	}

	.wlre-hero__toggle-btn {
		min-height: var(--wlre-tap-target);
	}

	.wlre-hero__cities {
		grid-template-columns: 1fr;
	}

	.wlre-hero__cities[data-count="2"] {
		grid-template-columns: 1fr;
	}

	.wlre-hero__filters {
		flex-direction: column;
		gap: var(--wlre-space-8);
		padding: var(--wlre-space-12);
	}

	.wlre-hero__filter-divider {
		display: none;
	}

	.wlre-hero__filter-submit {
		min-height: 48px;
		width: 100%;
	}

	.wlre-hero__city-btn {
		width: 100%;
		white-space: normal;
	}

	.wlre-hero__trust {
		font-size: var(--wlre-font-size-s);
		max-width: 343px;
	}

	.wlre-hero__dots {
		display: none;
	}
}
