// Hero search screen - cinematic landing with destination cards const ScreenSearch = ({ onSearch, query, setQuery }) => { const [activeDest, setActiveDest] = useState(0); const [originOpen, setOriginOpen] = useState(false); const [destOpen, setDestOpen] = useState(false); const [parallaxX, setParallaxX] = useState(0); const [parallaxY, setParallaxY] = useState(0); const [mode, setMode] = useState("flights"); // flights | hotels | cars const heroRef = useRef(null); // gentle parallax on the hero image based on cursor position useEffect(() => { const onMove = (e) => { if (!heroRef.current) return; const r = heroRef.current.getBoundingClientRect(); const px = (e.clientX - r.left) / r.width - .5; const py = (e.clientY - r.top) / r.height - .5; setParallaxX(px); setParallaxY(py); }; window.addEventListener("mousemove", onMove); return () => window.removeEventListener("mousemove", onMove); }, []); // auto-rotate the destination strip useEffect(() => { const t = setInterval(() => setActiveDest(d => (d + 1) % DESTINATIONS.length), 5200); return () => clearInterval(t); }, []); const dest = DESTINATIONS[activeDest]; const dropdownOpen = originOpen || destOpen; return (
{/* Cinematic hero image */}
{DESTINATIONS.map((d, i) => (
))} {/* graded overlay */}
{/* subtle film grain */}
{/* Ambient color orbs */}
{/* Drifting plane far behind */}
{/* Live status pill */}
Live · 12,408 flying now
{/* Main hero content */}
{/* Eyebrow */}
↳ Issue 04 — Spring corridor open
{/* Headline */}

Pack light.
Fly somewhere
worth telling.

{/* Active destination caption */}
Now showing — {dest.tag}
{dest.city}, {dest.country}
{DESTINATIONS.map((d, i) => (
{/* ── Search panel — light glassmorphic with push-content dropdown ── */}
{/* Product mode switcher — Flights / Hotels / Cars (additive) */}
{[ { key: "flights", label: "Flights", accent: "var(--sun)", accentDeep: "var(--sun-deep)" }, { key: "hotels", label: "Hotels", accent: "var(--sky)", accentDeep: "#3d6f8f" }, { key: "cars", label: "Cars", accent: "var(--grass)", accentDeep: "#1e3d26" }, ].map((m) => { const on = mode === m.key; return ( ); })}
{mode === "flights" && (<> {/* Trip type tabs */}
{["Round trip", "One way", "Multi-city"].map((t) => ( ))}
{/* Fields — white row with sun-colored icons, ink text */}
} onClick={() => { setOriginOpen(o => !o); setDestOpen(false); }} open={originOpen} > {originOpen && ( { setQuery(q => ({ ...q, origin: a })); setOriginOpen(false); }} exclude={query.dest.code} /> )} } onClick={() => { setDestOpen(o => !o); setOriginOpen(false); }} open={destOpen} > {destOpen && ( { setQuery(q => ({ ...q, dest: a })); setDestOpen(false); }} exclude={query.origin.code} /> )} } /> } />
{/* ── Push-content spacer (animates when dropdown is open) ── */}
{/* Quick filter chips */}
{["Direct only", "Daytime departures", "Window seat", "Carbon-light routes", "+ Use 12,400 miles"].map((c, i) => ( ))}
)} {mode === "hotels" &&
} {mode === "cars" &&
}
{/* Bottom row: featured destinations */}
This week — corridor pricing
← drag →
{[...DESTINATIONS, ...DESTINATIONS].map((d, i) => { const realIdx = i % DESTINATIONS.length; return ( );})}
); }; function Field({ label, value, sub, icon, onClick, open, children }) { return ( ); } function AirportPicker({ onPick, exclude }) { const [q, setQ] = useState(""); const filtered = useMemo(() => { const ql = q.trim().toLowerCase(); return AIRPORTS.filter(a => a.code !== exclude && ( !ql || a.city.toLowerCase().includes(ql) || a.code.toLowerCase().includes(ql) || a.name.toLowerCase().includes(ql) )); }, [q, exclude]); return (
e.stopPropagation()} style={{ position: "absolute", top: "calc(100% + 6px)", left: 0, width: 360, zIndex: 30, background: "white", border: "1px solid var(--line)", borderRadius: 14, boxShadow: "0 24px 60px -20px rgba(0,0,0,.4)", overflow: "hidden", color: "var(--ink)" }}>
setQ(e.target.value)} placeholder="Search city or airport" style={{ flex: 1, border: "none", outline: "none", fontSize: 14, background: "transparent", color: "var(--ink)" }} />
{filtered.map(a => ( ))} {!filtered.length &&
No airports match.
}
); } window.ScreenSearch = ScreenSearch;