Files

1315 lines
65 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ============================================================
// atlas-pages.jsx — Atlas marketplace page bodies
// ------------------------------------------------------------
// Eight pages composing a coherent stays-marketplace product.
// All pages assume the .theme-atlas wrapper applied by the
// showcase. Built from vibn-ai-templates + vibn-marketplace
// components.
// ============================================================
// ─── Sample data — re-used across pages ─────────────────────
const sampleListings = [
{ id: "l1", title: "Cliffside cabin in the pines", subtitle: "Big Sur, California", price: { amount: 318, period: "/ night" }, rating: 4.94, reviews: 218, badges: ["superhost"], photo: { tone: "sand", label: "Big Sur · A-frame" } },
{ id: "l2", title: "Off-grid farmstead with hot pool", subtitle: "Mendocino, California", price: { amount: 246, period: "/ night" }, rating: 4.88, reviews: 176, badges: ["verified"], photo: { tone: "sage", label: "Off-grid farmstead" } },
{ id: "l3", title: "Modernist villa with quiet pool", subtitle: "Joshua Tree, California", price: { amount: 412, period: "/ night" }, rating: 4.97, reviews: 304, badges: ["superhost","instant"], photo: { tone: "warm", label: "Joshua Tree villa" } },
{ id: "l4", title: "Hillside cottage with garden", subtitle: "Sonoma, California", price: { amount: 184, period: "/ night" }, rating: 4.79, reviews: 92, badges: ["new"], photo: { tone: "blush", label: "Sonoma cottage" } },
{ id: "l5", title: "Loft above the harbor", subtitle: "Mendocino, California", price: { amount: 268, period: "/ night" }, rating: 4.91, reviews: 142, badges: ["verified"], photo: { tone: "ocean", label: "Harbor loft" } },
{ id: "l6", title: "Quiet ranch with grass paths", subtitle: "Carmel Valley, California", price: { amount: 295, period: "/ night" }, rating: 4.95, reviews: 256, badges: ["superhost"], photo: { tone: "sand", label: "Carmel Valley ranch" } },
{ id: "l7", title: "Painted barn with fields", subtitle: "Healdsburg, California", price: { amount: 220, period: "/ night" }, rating: 4.83, reviews: 78, badges: [], photo: { tone: "blush", label: "Painted barn" } },
{ id: "l8", title: "Bungalow with stone fireplace", subtitle: "Tahoe, California", price: { amount: 178, period: "/ night" }, rating: 4.86, reviews: 121, badges: ["instant"], photo: { tone: "night", label: "Tahoe bungalow" } },
];
const sampleCategories = [
{ id: "trending", label: "Trending", emoji: "🌅" },
{ id: "cabins", label: "Cabins", emoji: "🌲" },
{ id: "amazing", label: "Amazing views", emoji: "🏔" },
{ id: "tiny", label: "Tiny homes", emoji: "🏠" },
{ id: "design", label: "Design", emoji: "✦" },
{ id: "beach", label: "Beachfront", emoji: "🌊" },
{ id: "country", label: "Countryside", emoji: "🌾" },
{ id: "farms", label: "Farms", emoji: "🐎" },
{ id: "domes", label: "Domes", emoji: "◐" },
{ id: "creative", label: "Creative", emoji: "✎" },
{ id: "national", label: "National parks", emoji: "🌲" },
{ id: "ski", label: "Ski-in/out", emoji: "⛷" },
];
const userMira = { name: "Mira Reyes", color: "#d4b8a8" };
// ============================================================
// 1 · HOME / DISCOVERY
// ============================================================
const AtlasHome = () => {
const featured = sampleListings.slice(0, 8);
const cities = [
{ name: "Mendocino", sub: "5 hr drive", tone: "ocean" },
{ name: "Joshua Tree", sub: "Direct flight", tone: "warm" },
{ name: "Big Sur", sub: "3 hr drive", tone: "sand" },
{ name: "Tahoe", sub: "4 hr drive", tone: "night" },
];
return (
<MarketplaceTopShell user={userMira}>
{/* Hero — big editorial banner + inline search */}
<section style={{
padding: "60px 40px 30px", position: "relative",
background: "var(--surface-2)",
borderBottom: "1px solid var(--border)",
}}>
<div style={{ maxWidth: 1180, margin: "0 auto" }}>
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 48, alignItems: "center" }}>
<div>
<Badge tone="accent" leadingIcon={<Icon name="spark" size={11}/>} style={{ marginBottom: 18 }}>
Atlas Originals · 2026
</Badge>
<h1 style={{
fontFamily: "var(--font-display)",
fontSize: 68, lineHeight: 1, margin: 0,
fontWeight: 500, letterSpacing: "-0.03em",
textWrap: "balance",
}}>
Stays that feel{" "}
<span className="accent-script" style={{ color: "var(--accent)" }}>
like the place
</span>.
</h1>
<p style={{
fontSize: 18, color: "var(--text-2)", lineHeight: 1.55,
margin: "20px 0 32px", maxWidth: 480,
}}>
4,820 homes hand-picked by the Atlas team no chains,
no copy-paste. Hosted by people who actually live there.
</p>
<div style={{ display: "flex", gap: 12 }}>
<Button size="lg">Start browsing </Button>
<Button size="lg" variant="secondary">How Atlas works</Button>
</div>
</div>
<PhotoSlot label="hero · stay photograph" tone="sand" aspect="4/5"
style={{ borderRadius: "var(--card-radius)", boxShadow: "var(--shadow-lg)" }}/>
</div>
{/* Inline search */}
<div style={{ marginTop: 56 }}>
<SearchBar destination="Northern California" dates={{ in: "Jun 14", out: "Jun 19" }} guests="2 adults · 1 dog"/>
</div>
</div>
</section>
{/* Category rail */}
<section style={{
padding: "8px 40px 0", background: "var(--surface)",
borderBottom: "1px solid var(--border)", position: "sticky", top: 88, zIndex: 4,
}}>
<div style={{ maxWidth: 1180, margin: "0 auto" }}>
<CategoryRail categories={sampleCategories} active="cabins"/>
</div>
</section>
{/* Featured listings */}
<section style={{ padding: "40px 40px 30px" }}>
<div style={{ maxWidth: 1180, margin: "0 auto" }}>
<div style={{
display: "flex", justifyContent: "space-between", alignItems: "baseline",
marginBottom: 22,
}}>
<div>
<div style={{
fontSize: "var(--text-xs)", color: "var(--text-3)",
textTransform: "uppercase", letterSpacing: "0.08em",
fontWeight: 500, marginBottom: 4,
}}>Editors' picks · Northern California</div>
<h2 style={{
fontFamily: "var(--font-display)", fontSize: 32, margin: 0,
fontWeight: 500, letterSpacing: "-0.02em",
}}>This week's stays</h2>
</div>
<Button variant="ghost" trailingIcon={<Icon name="arrow" size={13}/>}>See all 184</Button>
</div>
<div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 28 }}>
{featured.map((l, i) => (
<ListingCard key={l.id} listing={{
...l,
tags: i === 0 ? ["Editor's pick"] : i === 2 ? ["Rare find"] : [],
favorite: i === 1,
}}/>
))}
</div>
</div>
</section>
{/* Inspiration row */}
<section style={{ padding: "40px 40px", background: "var(--surface-2)", borderTop: "1px solid var(--border)" }}>
<div style={{ maxWidth: 1180, margin: "0 auto" }}>
<h2 style={{
fontFamily: "var(--font-display)", fontSize: 32, margin: "0 0 22px",
fontWeight: 500, letterSpacing: "-0.02em",
}}>Closer than you think</h2>
<div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 16 }}>
{cities.map(c => (
<div key={c.name} style={{
position: "relative", borderRadius: "var(--card-radius)", overflow: "hidden",
aspectRatio: "5/6", cursor: "pointer",
}}>
<PhotoSlot label={c.name} tone={c.tone} aspect="auto" style={{ height: "100%", aspectRatio: "auto" }}/>
<div style={{
position: "absolute", left: 18, bottom: 18, color: "#fff",
textShadow: "0 1px 3px rgba(0,0,0,0.4)",
}}>
<div style={{
fontFamily: "var(--font-display)", fontSize: 22,
fontWeight: 500, letterSpacing: "-0.01em",
}}>{c.name}</div>
<div style={{ fontSize: 13, opacity: 0.9 }}>{c.sub}</div>
</div>
</div>
))}
</div>
</div>
</section>
{/* How Atlas works */}
<section style={{ padding: "60px 40px" }}>
<div style={{ maxWidth: 1180, margin: "0 auto" }}>
<div style={{ textAlign: "center", maxWidth: 540, margin: "0 auto 40px" }}>
<Badge tone="accent" style={{ marginBottom: 14 }}>How Atlas works</Badge>
<h2 style={{
fontFamily: "var(--font-display)", fontSize: 38, margin: "0 0 14px",
fontWeight: 500, letterSpacing: "-0.02em",
}}>
Booking, but considered.
</h2>
<p style={{ fontSize: 16, color: "var(--text-2)", lineHeight: 1.55, margin: 0 }}>
Every host is interviewed. Every photo is real. Every refund is
easy. The way it should be.
</p>
</div>
<div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 24 }}>
{[
{ i: "people", t: "Hosted by humans", b: "Every Atlas host meets our team. No corporate brands, no auto-replies." },
{ i: "shield", t: "Vetted for the truth", b: "We visit and photograph each listing ourselves. What you see is what you sleep in." },
{ i: "spark", t: "Refund first", b: "Cancel up to 48 hours before for any reason. No questions, no fine print." },
].map(c => (
<Card key={c.t} padding={28}>
<div style={{
width: 44, height: 44, borderRadius: 12,
background: "var(--accent-soft)", color: "var(--accent)",
display: "flex", alignItems: "center", justifyContent: "center",
marginBottom: 16,
}}><Icon name={c.i} size={20}/></div>
<h3 style={{
fontFamily: "var(--font-display)", fontSize: 22, margin: 0,
fontWeight: 500, letterSpacing: "-0.01em",
}}>{c.t}</h3>
<p style={{ margin: "8px 0 0", fontSize: 14, color: "var(--text-2)", lineHeight: 1.55 }}>{c.b}</p>
</Card>
))}
</div>
</div>
</section>
</MarketplaceTopShell>
);
};
// ============================================================
// 2 · SEARCH RESULTS + MAP
// ============================================================
const AtlasSearch = () => {
return (
<MarketplaceTopShell user={userMira} compact showSearch
searchProps={{ destination: "Mendocino · Northern California", dates: { in: "Jun 14", out: "Jun 19" }, guests: "2 adults" }}>
{/* Filters strip */}
<section style={{
padding: "16px 40px", borderBottom: "1px solid var(--border)",
background: "var(--surface)", display: "flex",
justifyContent: "space-between", alignItems: "center", gap: 20,
}}>
<FilterChips filters={[
{ label: "Any type", active: true },
{ label: "Cabin", count: 84 },
{ label: "House" },
{ label: "Cottage" },
{ label: "Tiny home" },
{ label: "Yurt" },
{ label: "Filters", icon: "settings" },
]} onClear={() => {}}/>
<div style={{ display: "flex", alignItems: "center", gap: 12 }}>
<span style={{ fontSize: "var(--text-sm)", color: "var(--text-2)" }}>
<b style={{ color: "var(--text)" }}>184</b> stays
</span>
<Select value="Recommended"/>
</div>
</section>
{/* Split: list + map */}
<section style={{
display: "grid", gridTemplateColumns: "minmax(0, 1.2fr) minmax(0, 1fr)",
height: "calc(100% - 145px)",
}}>
<div style={{ padding: "20px 40px", overflowY: "auto", display: "flex", flexDirection: "column", gap: 16 }}>
{sampleListings.slice(0, 5).map((l, i) => (
<ListingCardHorizontal key={l.id} listing={{
...l,
description: i === 0
? "A serene A-frame cabin with floor-to-ceiling windows, a sunken fireplace, and a wraparound deck overlooking the redwoods."
: "Sun-drenched home with thoughtful design, full kitchen, and outdoor soaking tub. Walk to the river in 5 minutes.",
amenities: ["Wifi","Kitchen","Hot tub","Fireplace","EV charger","Pet friendly"],
}}/>
))}
</div>
<div style={{ position: "sticky", top: 0, height: "100%", padding: 16 }}>
<MiniMap pins={[
{ x: 28, y: 36, price: 318, active: true },
{ x: 42, y: 28, price: 246 },
{ x: 56, y: 50, price: 412 },
{ x: 68, y: 32, price: 184 },
{ x: 38, y: 64, price: 268 },
{ x: 22, y: 58, price: 295 },
{ x: 76, y: 50, price: 220 },
{ x: 62, y: 18, price: 178 },
]}/>
</div>
</section>
</MarketplaceTopShell>
);
};
// ============================================================
// 3 · LISTING DETAIL
// ============================================================
const AtlasListing = () => {
const photos = [
{ label: "Photo 1 · exterior", tone: "sand" },
{ label: "Photo 2 · living", tone: "warm" },
{ label: "Photo 3 · kitchen", tone: "blush" },
{ label: "Photo 4 · bedroom", tone: "ocean" },
{ label: "Photo 5 · view", tone: "sage" },
];
const reviews = [
{ author: "Tomás Olivar", avatarColor: "#c8e8a8", rating: 5, date: "May 2026", location: "Berlin, DE", body: "We arrived after a long flight and the cabin felt like it had been waiting for us. Coffee already ground, fire laid in the stove. We extended a night." },
{ author: "Naila Choudhury", avatarColor: "#e8a87c", rating: 5, date: "April 2026", location: "Mumbai, IN", body: "Photos don't do it justice. The light at golden hour through those west-facing windows is something you should plan for. Bring a camera." },
{ author: "Henri Lamarck", avatarColor: "#a8c8e8", rating: 4.5, date: "March 2026", location: "Lyon, FR", body: "Beautiful design, very thoughtful. Wifi was a little patchy for video calls, but that's almost certainly a feature, not a bug." },
{ author: "Emi Hara", avatarColor: "#c8a8e8", rating: 5, date: "March 2026", location: "Kyoto, JP", body: "Mara is the kind of host who anticipates things. The local bakery list alone was worth the trip." },
];
return (
<MarketplaceTopShell user={userMira} compact>
<article style={{ padding: "28px 40px 60px", maxWidth: 1180, margin: "0 auto" }}>
{/* Title block */}
<header style={{ marginBottom: 18 }}>
<h1 style={{
fontFamily: "var(--font-display)", fontSize: 36, margin: 0,
fontWeight: 500, letterSpacing: "-0.02em",
}}>Cliffside cabin in the pines</h1>
<div style={{
display: "flex", alignItems: "center", gap: 16, marginTop: 8,
fontSize: "var(--text-sm)", color: "var(--text-2)",
}}>
<RatingStars value={4.94} size={12}/>
<span>· 218 reviews</span>
<span>·</span>
<TrustBadge kind="superhost"/>
<span style={{ flex: 1 }}/>
<Button variant="ghost" size="sm" leadingIcon={<Icon name="link" size={13}/>}>Share</Button>
<Button variant="ghost" size="sm" leadingIcon={<Icon name="star" size={13}/>}>Save</Button>
</div>
</header>
{/* Gallery */}
<PhotoGallery photos={photos} style={{ marginBottom: 36 }}/>
{/* 2-column body + booking card */}
<div style={{ display: "grid", gridTemplateColumns: "1.5fr 1fr", gap: 56, alignItems: "start" }}>
<div>
{/* Summary */}
<div style={{ paddingBottom: 24, borderBottom: "1px solid var(--border)" }}>
<div style={{
display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 16,
marginBottom: 12,
}}>
<div>
<h2 style={{
fontFamily: "var(--font-display)", fontSize: 24, margin: 0,
fontWeight: 500, letterSpacing: "-0.01em",
}}>Entire cabin in Big Sur · hosted by Mara</h2>
<div style={{ fontSize: "var(--text-sm)", color: "var(--text-2)", marginTop: 6 }}>
4 guests · 2 bedrooms · 2 beds · 1.5 baths
</div>
</div>
<Avatar name="Mara H" color="#e8a87c" size={56}/>
</div>
<p style={{
fontSize: 16, color: "var(--text)", lineHeight: 1.65,
margin: "10px 0 0", maxWidth: 540,
}}>
Set 80 feet above the Pacific, this A-frame is a quiet,
light-soaked retreat. Architecturally restored in 2024 with
radiant floors, a wood-burning stove, and a Furlong soaking tub
on the deck. Stargazing is the only TV.
</p>
<Button variant="ghost" size="sm" style={{ marginTop: 14, padding: 0 }}>
Show more
</Button>
</div>
{/* Amenities */}
<div style={{ padding: "26px 0", borderBottom: "1px solid var(--border)" }}>
<h3 style={{
fontFamily: "var(--font-display)", fontSize: 22, margin: "0 0 18px",
fontWeight: 500, letterSpacing: "-0.01em",
}}>What this place offers</h3>
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "12px 32px" }}>
{[
["Pacific Ocean view", "home"], ["Wood-burning stove", "spark"],
["Soaking tub on deck", "home"], ["Fast wifi · 320Mbps", "bolt"],
["Equipped kitchen", "home"], ["Hairdryer + amenities", "shield"],
["EV charger · Level 2", "bolt"], ["Pet-friendly · 1 dog ok", "people"],
].map(([t, i]) => (
<div key={t} style={{ display: "flex", alignItems: "center", gap: 12, padding: "4px 0" }}>
<Icon name={i} size={18} style={{ color: "var(--text-2)" }}/>
<span style={{ fontSize: "var(--text-md)", color: "var(--text)" }}>{t}</span>
</div>
))}
</div>
<Button variant="secondary" style={{ marginTop: 18 }}>Show all 28 amenities</Button>
</div>
{/* Calendar */}
<div style={{ padding: "26px 0", borderBottom: "1px solid var(--border)" }}>
<h3 style={{
fontFamily: "var(--font-display)", fontSize: 22, margin: "0 0 4px",
fontWeight: 500, letterSpacing: "-0.01em",
}}>5 nights in Big Sur</h3>
<div style={{ fontSize: "var(--text-sm)", color: "var(--text-3)", marginBottom: 18 }}>
Jun 14 Jun 19, 2026
</div>
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 32 }}>
<CalendarMonth month="June 2026" firstWeekday={1} daysInMonth={30}
start={14} end={19} today={2} blocked={[7, 8, 21, 22, 23]}/>
<CalendarMonth month="July 2026" firstWeekday={3} daysInMonth={31}
blocked={[3, 4, 5, 11, 12, 19, 20, 27, 28]}/>
</div>
</div>
{/* Reviews */}
<div style={{ padding: "26px 0", borderBottom: "1px solid var(--border)" }}>
<RatingsSummary value={4.94} total={218} categories={[
{ label: "Cleanliness", value: 4.98 },
{ label: "Communication", value: 5.00 },
{ label: "Accuracy", value: 4.92 },
{ label: "Check-in", value: 5.00 },
{ label: "Value", value: 4.82 },
{ label: "Location", value: 4.96 },
]}/>
<div style={{
display: "grid", gridTemplateColumns: "1fr 1fr", gap: "32px 48px", marginTop: 32,
}}>
{reviews.map(r => <ReviewCard key={r.author} {...r}/>)}
</div>
<Button variant="secondary" style={{ marginTop: 26 }}>Show all 218 reviews</Button>
</div>
{/* Host */}
<div style={{ paddingTop: 26 }}>
<h3 style={{
fontFamily: "var(--font-display)", fontSize: 22, margin: "0 0 18px",
fontWeight: 500, letterSpacing: "-0.01em",
}}>Meet your host</h3>
<HostHeader
name="Mara H" color="#e8a87c"
joined="2019" location="Big Sur, CA"
languages={["English", "Spanish"]}
kpis={[
{ label: "Reviews", value: "612" },
{ label: "Rating", value: "4.96" },
{ label: "Years hosting", value: "6" },
]}
blurb="I'm an architect by training and gardener by necessity. I share this cabin and a tiny cottage two ridges over. I'll send you a hand-drawn map of my favorite tide pools when you book."
/>
</div>
</div>
{/* Sticky booking card */}
<aside style={{ position: "sticky", top: 100 }}>
<Card padding={28} variant="raised">
<div style={{
display: "flex", justifyContent: "space-between", alignItems: "baseline",
marginBottom: 18,
}}>
<PriceTag amount={318} period="/ night" size="lg" original={365}/>
<RatingStars value={4.94} size={12}/>
</div>
{/* Date + guests inputs */}
<div style={{
border: "1px solid var(--border-strong)", borderRadius: 10, overflow: "hidden",
marginBottom: 14,
}}>
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", borderBottom: "1px solid var(--border-strong)" }}>
<div style={{ padding: "10px 14px", borderRight: "1px solid var(--border-strong)" }}>
<div style={{ fontSize: 10, fontWeight: 700, color: "var(--text)", letterSpacing: "0.05em", textTransform: "uppercase" }}>Check in</div>
<div style={{ fontSize: "var(--text-sm)", color: "var(--text)", marginTop: 2 }}>Jun 14, 2026</div>
</div>
<div style={{ padding: "10px 14px" }}>
<div style={{ fontSize: 10, fontWeight: 700, color: "var(--text)", letterSpacing: "0.05em", textTransform: "uppercase" }}>Check out</div>
<div style={{ fontSize: "var(--text-sm)", color: "var(--text)", marginTop: 2 }}>Jun 19, 2026</div>
</div>
</div>
<div style={{ padding: "10px 14px", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
<div>
<div style={{ fontSize: 10, fontWeight: 700, color: "var(--text)", letterSpacing: "0.05em", textTransform: "uppercase" }}>Guests</div>
<div style={{ fontSize: "var(--text-sm)", color: "var(--text)", marginTop: 2 }}>2 adults · 1 dog</div>
</div>
<Icon name="chevDown" size={14} style={{ color: "var(--text-3)" }}/>
</div>
</div>
<Button full size="lg" leadingIcon={<Icon name="bolt" size={15}/>}>Reserve</Button>
<div style={{ textAlign: "center", fontSize: "var(--text-xs)", color: "var(--text-3)", margin: "10px 0 18px" }}>
You won't be charged yet
</div>
<PriceBreakdown items={[
{ label: "$318 × 5 nights", amount: 1590 },
{ label: "Atlas service fee", amount: 184 },
{ label: "Cleaning fee", amount: 95 },
{ label: "Local taxes (8%)", amount: 127 },
{ label: "First-time guest discount", amount: 150, note: "discount" },
]} total={1846}/>
<div style={{
marginTop: 18, padding: 14, borderRadius: 10,
background: "var(--accent-soft)", display: "flex", alignItems: "center", gap: 10,
}}>
<Icon name="info" size={14} style={{ color: "var(--accent)" }}/>
<span style={{ fontSize: "var(--text-sm)", color: "var(--text)" }}>
<b>Rare find</b> · this place is usually booked
</span>
</div>
</Card>
<div style={{
marginTop: 14, fontSize: "var(--text-xs)", color: "var(--text-3)",
textAlign: "center",
}}>Report this listing</div>
</aside>
</div>
</article>
</MarketplaceTopShell>
);
};
// ============================================================
// 4 · CHECKOUT
// ============================================================
const AtlasCheckout = () => (
<MarketplaceTopShell user={userMira} compact footer={false}>
<div style={{ padding: "32px 40px 60px", maxWidth: 1100, margin: "0 auto" }}>
<div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 18 }}>
<IconButton name="chevLeft" variant="secondary" label="Back"/>
<h1 style={{
fontFamily: "var(--font-display)", fontSize: 30, margin: 0,
fontWeight: 500, letterSpacing: "-0.02em",
}}>Confirm and pay</h1>
</div>
<div style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr", gap: 48, alignItems: "start" }}>
{/* Form */}
<div>
{/* Trip details */}
<section style={{ paddingBottom: 22, borderBottom: "1px solid var(--border)" }}>
<h2 style={{ fontFamily: "var(--font-display)", fontSize: 22, margin: "0 0 16px",
fontWeight: 500, letterSpacing: "-0.01em" }}>Your trip</h2>
{[
["Dates", "Jun 14 19, 2026"],
["Guests", "2 adults, 1 dog"],
].map(([k, v]) => (
<div key={k} style={{
display: "flex", justifyContent: "space-between", alignItems: "baseline",
padding: "10px 0",
}}>
<div>
<div style={{ fontSize: "var(--text-md)", fontWeight: 500 }}>{k}</div>
<div style={{ fontSize: "var(--text-sm)", color: "var(--text-2)" }}>{v}</div>
</div>
<Button variant="ghost" size="sm">Edit</Button>
</div>
))}
</section>
{/* Payment */}
<section style={{ padding: "26px 0", borderBottom: "1px solid var(--border)" }}>
<h2 style={{ fontFamily: "var(--font-display)", fontSize: 22, margin: "0 0 16px",
fontWeight: 500, letterSpacing: "-0.01em" }}>Pay with</h2>
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 10, marginBottom: 18 }}>
{["Card","Apple Pay","Klarna"].map((p, i) => (
<div key={p} style={{
padding: "12px 16px", borderRadius: 10, cursor: "pointer", textAlign: "center",
background: i === 0 ? "var(--surface)" : "var(--surface)",
border: i === 0 ? "1.5px solid var(--text)" : "1px solid var(--border)",
fontSize: "var(--text-sm)", fontWeight: i === 0 ? 600 : 500,
color: "var(--text)",
}}>{p}</div>
))}
</div>
<Field label="Card number">
<Input value="4242 4242 4242 4242"/>
</Field>
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
<Field label="Expiry"><Input value="08 / 28"/></Field>
<Field label="CVC"><Input value="123"/></Field>
</div>
<Field label="Country / region">
<Select value="United States"/>
</Field>
</section>
{/* Message host */}
<section style={{ padding: "26px 0", borderBottom: "1px solid var(--border)" }}>
<h2 style={{ fontFamily: "var(--font-display)", fontSize: 22, margin: "0 0 6px",
fontWeight: 500, letterSpacing: "-0.01em" }}>Message Mara</h2>
<p style={{ fontSize: "var(--text-sm)", color: "var(--text-2)", margin: "0 0 12px" }}>
Hosts often reply within an hour.
</p>
<Field>
<Textarea value="Hi Mara! We're looking forward to our trip. Any tips for the best spot to catch the sunset within walking distance?" rows={4}/>
</Field>
</section>
{/* Ground rules */}
<section style={{ padding: "26px 0" }}>
<h2 style={{ fontFamily: "var(--font-display)", fontSize: 22, margin: "0 0 12px",
fontWeight: 500, letterSpacing: "-0.01em" }}>Ground rules</h2>
<p style={{ fontSize: "var(--text-sm)", color: "var(--text-2)", lineHeight: 1.55 }}>
Atlas asks every guest to remember a few simple things. Treat
your host's home like your own. No parties or events. Follow the
house rules in your confirmation.
</p>
<Button size="lg" style={{ marginTop: 20 }}>Confirm and pay · $1,846</Button>
</section>
</div>
{/* Summary */}
<aside style={{ position: "sticky", top: 100 }}>
<Card padding={24} variant="raised">
<div style={{ display: "flex", gap: 14, marginBottom: 18 }}>
<div style={{ width: 100, borderRadius: 10, overflow: "hidden" }}>
<PhotoSlot label="Big Sur · A-frame" tone="sand" aspect="1/1"/>
</div>
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ fontSize: "var(--text-md)", fontWeight: 600, color: "var(--text)" }}>
Cliffside cabin in the pines
</div>
<div style={{ fontSize: "var(--text-xs)", color: "var(--text-3)", marginTop: 2 }}>
Entire cabin · 4 guests
</div>
<div style={{ marginTop: 6 }}>
<RatingStars value={4.94} size={11}/>
</div>
</div>
</div>
<Divider/>
<h3 style={{ fontFamily: "var(--font-display)", fontSize: 18, margin: "8px 0 12px",
fontWeight: 500 }}>Price details</h3>
<PriceBreakdown items={[
{ label: "$318 × 5 nights", amount: 1590 },
{ label: "Atlas service fee", amount: 184 },
{ label: "Cleaning fee", amount: 95 },
{ label: "Local taxes (8%)", amount: 127 },
{ label: "First-time guest discount", amount: 150, note: "discount" },
]} total={1846}/>
</Card>
</aside>
</div>
</div>
</MarketplaceTopShell>
);
// ============================================================
// 5 · GUEST DASHBOARD · MY TRIPS
// ============================================================
const AtlasGuestDash = () => (
<MarketplaceDashboardShell role="guest" active="trips" user={userMira}>
<div style={{ padding: "28px 36px 40px", overflow: "auto" }}>
<div style={{
display: "flex", justifyContent: "space-between", alignItems: "baseline",
marginBottom: 22,
}}>
<div>
<div style={{
fontSize: "var(--text-xs)", color: "var(--text-3)",
textTransform: "uppercase", letterSpacing: "0.06em",
fontWeight: 500, marginBottom: 4,
}}>Welcome back, Mira</div>
<h1 style={{
fontFamily: "var(--font-display)", fontSize: 32, margin: 0,
fontWeight: 500, letterSpacing: "-0.02em",
}}>Your trips</h1>
</div>
<Tabs items={[
{ label: "Upcoming", count: 1 }, { label: "Past", count: 12 },
{ label: "Cancelled" },
]} active="Upcoming"/>
</div>
{/* Upcoming hero */}
<Card padding={0} variant="raised" style={{
overflow: "hidden", marginBottom: 28,
}}>
<div style={{ display: "grid", gridTemplateColumns: "1.2fr 1fr" }}>
<div style={{ padding: 28 }}>
<Badge tone="accent" leadingIcon={<Icon name="bolt" size={11}/>} style={{ marginBottom: 14 }}>
Upcoming · in 19 days
</Badge>
<h2 style={{
fontFamily: "var(--font-display)", fontSize: 30, margin: "0 0 4px",
fontWeight: 500, letterSpacing: "-0.02em",
}}>Cliffside cabin in the pines</h2>
<div style={{ fontSize: "var(--text-md)", color: "var(--text-2)" }}>
Big Sur, California · Hosted by Mara
</div>
<div style={{
display: "grid", gridTemplateColumns: "repeat(3, auto)", gap: "8px 36px",
margin: "22px 0", fontSize: "var(--text-sm)",
}}>
<div>
<div style={{ color: "var(--text-3)", fontSize: 11, textTransform: "uppercase", letterSpacing: "0.06em" }}>Check in</div>
<div style={{ fontWeight: 600, marginTop: 2 }}>Jun 14, 4:00pm</div>
</div>
<div>
<div style={{ color: "var(--text-3)", fontSize: 11, textTransform: "uppercase", letterSpacing: "0.06em" }}>Check out</div>
<div style={{ fontWeight: 600, marginTop: 2 }}>Jun 19, 11:00am</div>
</div>
<div>
<div style={{ color: "var(--text-3)", fontSize: 11, textTransform: "uppercase", letterSpacing: "0.06em" }}>Guests</div>
<div style={{ fontWeight: 600, marginTop: 2 }}>2 adults · 1 dog</div>
</div>
</div>
<div style={{ display: "flex", gap: 8 }}>
<Button leadingIcon={<Icon name="inbox" size={13}/>}>Message Mara</Button>
<Button variant="secondary">View itinerary</Button>
<Button variant="ghost">Get directions</Button>
</div>
<div style={{
marginTop: 18, padding: 12, borderRadius: 10,
background: "var(--surface-2)", display: "flex", alignItems: "center", gap: 10,
}}>
<Icon name="info" size={14} style={{ color: "var(--text-2)" }}/>
<span style={{ fontSize: "var(--text-sm)", color: "var(--text-2)" }}>
Free cancellation until <b style={{ color: "var(--text)" }}>Jun 12, 4:00pm</b>.
</span>
</div>
</div>
<div style={{ position: "relative" }}>
<PhotoSlot label="Big Sur · A-frame" tone="sand" aspect="auto"
style={{ height: "100%", aspectRatio: "auto" }}/>
</div>
</div>
</Card>
{/* Saved + past */}
<div style={{ display: "grid", gridTemplateColumns: "2fr 1fr", gap: 28 }}>
<div>
<h3 style={{
fontFamily: "var(--font-display)", fontSize: 22, margin: "8px 0 14px",
fontWeight: 500, letterSpacing: "-0.01em",
}}>Past trips · 12</h3>
<div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
{[
{ i: "Mendocino, May 2025", l: "Off-grid farmstead", h: "Hosted by Jamal", rating: 5, tone: "sage" },
{ i: "Joshua Tree, Oct 2024", l: "Modernist villa", h: "Hosted by Sun", rating: 5, tone: "warm" },
{ i: "Sonoma, Aug 2024", l: "Hillside cottage", h: "Hosted by Lila", rating: 4.5, tone: "blush" },
].map(t => (
<Card key={t.i} padding={16} style={{ display: "grid", gridTemplateColumns: "100px 1fr auto", gap: 16, alignItems: "center" }}>
<div style={{ borderRadius: 10, overflow: "hidden", height: 80 }}>
<PhotoSlot label="" tone={t.tone} aspect="auto" style={{ height: "100%", aspectRatio: "auto" }}/>
</div>
<div>
<div style={{ fontSize: "var(--text-md)", fontWeight: 600 }}>{t.l}</div>
<div style={{ fontSize: "var(--text-sm)", color: "var(--text-2)" }}>{t.i} · {t.h}</div>
<div style={{ marginTop: 4 }}>
<RatingStars value={t.rating} size={11} showValue={false}/>
<span style={{ fontSize: "var(--text-xs)", color: "var(--text-3)", marginLeft: 6 }}>You left a review</span>
</div>
</div>
<Button variant="secondary" size="sm">Book again</Button>
</Card>
))}
</div>
</div>
<div>
<h3 style={{
fontFamily: "var(--font-display)", fontSize: 22, margin: "8px 0 14px",
fontWeight: 500, letterSpacing: "-0.01em",
}}>Wishlist · 8 saved</h3>
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
{[
{ l: "Tahoe bungalow", tone: "night" },
{ l: "Painted barn", tone: "blush" },
{ l: "Carmel ranch", tone: "sand" },
{ l: "Harbor loft", tone: "ocean" },
].map(w => (
<div key={w.l} style={{ borderRadius: 10, overflow: "hidden", position: "relative" }}>
<PhotoSlot label={w.l} tone={w.tone} aspect="1/1"/>
</div>
))}
</div>
<Button variant="ghost" full style={{ marginTop: 10 }}>See all saved →</Button>
</div>
</div>
</div>
</MarketplaceDashboardShell>
);
// ============================================================
// 6 · MESSAGES (Inbox + thread)
// ============================================================
const AtlasMessages = () => {
const threads = [
{ i: "Mara H", c: "#e8a87c", t: "Big Sur · A-frame", last: "We can leave the gate code in your message", time: "10:42am", unread: 1, active: true },
{ i: "Theo Bly", c: "#c8e8a8", t: "Joshua Tree · Villa", last: "Glad you enjoyed! Hope to host you again.", time: "Tuesday", unread: 0 },
{ i: "Lila Munro", c: "#a8c8e8", t: "Sonoma · Cottage", last: "Yes, both dogs are welcome! Just send their", time: "May 28", unread: 0 },
{ i: "Jamal Frost", c: "#c8a8e8", t: "Mendocino · Farmstead", last: "Thanks for the kind review, Mira.", time: "May 12", unread: 0 },
{ i: "Atlas Concierge", c: "#e8c8a8", t: "Trip planner", last: "Your trip details for Big Sur are ready ", time: "May 6", unread: 0 },
{ i: "Sun Ortiz", c: "#e8a8c8", t: "Tahoe · Bungalow", last: "We typically don't allow events but…", time: "April 22", unread: 0 },
];
return (
<MarketplaceDashboardShell role="guest" active="inbox" user={userMira}>
<div style={{ display: "grid", gridTemplateColumns: "360px 1fr", height: "100%", overflow: "hidden" }}>
{/* Inbox */}
<div style={{ borderRight: "1px solid var(--border)", display: "flex", flexDirection: "column" }}>
<div style={{ padding: "20px 20px 12px" }}>
<h2 style={{
fontFamily: "var(--font-display)", fontSize: 24, margin: "0 0 10px",
fontWeight: 500, letterSpacing: "-0.01em",
}}>Messages</h2>
<Input placeholder="Search messages" leadingIcon={<Icon name="search" size={14}/>}/>
</div>
<div style={{ padding: "0 12px 4px", display: "flex", gap: 6 }}>
{["All", "Hosts", "Travelling", "Support"].map((t, i) => (
<span key={t} style={{
padding: "5px 10px", borderRadius: 999,
background: i === 0 ? "var(--text)" : "transparent",
color: i === 0 ? "var(--bg)" : "var(--text-2)",
fontSize: 12, fontWeight: 500, cursor: "pointer",
}}>{t}</span>
))}
</div>
<div style={{ flex: 1, overflowY: "auto", padding: "10px 8px" }}>
{threads.map(th => (
<div key={th.i + th.t} style={{
display: "flex", gap: 12, padding: 12, borderRadius: 10,
background: th.active ? "var(--surface)" : "transparent",
boxShadow: th.active ? "var(--shadow-sm)" : "none",
cursor: "pointer", marginBottom: 2,
}}>
<Avatar name={th.i} color={th.c} size={40}/>
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{
display: "flex", justifyContent: "space-between", gap: 6,
}}>
<span style={{
fontSize: "var(--text-md)", fontWeight: th.unread ? 600 : 500,
color: "var(--text)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
}}>{th.i}</span>
<span style={{ fontSize: "var(--text-xs)", color: "var(--text-3)", whiteSpace: "nowrap" }}>{th.time}</span>
</div>
<div style={{ fontSize: "var(--text-xs)", color: "var(--accent)", marginTop: 1, fontWeight: 500 }}>
{th.t}
</div>
<div style={{
fontSize: "var(--text-sm)", color: th.unread ? "var(--text)" : "var(--text-2)",
marginTop: 2,
display: "-webkit-box", WebkitLineClamp: 1, WebkitBoxOrient: "vertical",
overflow: "hidden",
}}>{th.last}</div>
</div>
{th.unread > 0 && <span style={{
width: 8, height: 8, borderRadius: "50%", background: "var(--accent)",
alignSelf: "center", flexShrink: 0,
}}/>}
</div>
))}
</div>
</div>
{/* Thread */}
<div style={{ display: "flex", flexDirection: "column", overflow: "hidden" }}>
{/* Thread header */}
<div style={{
padding: "18px 28px", borderBottom: "1px solid var(--border)",
display: "flex", justifyContent: "space-between", alignItems: "center", gap: 16,
}}>
<div style={{ display: "flex", alignItems: "center", gap: 14, minWidth: 0 }}>
<Avatar name="Mara H" color="#e8a87c" size={44}/>
<div style={{ minWidth: 0 }}>
<div style={{
fontFamily: "var(--font-display)", fontSize: 20,
fontWeight: 500, letterSpacing: "-0.01em",
}}>Mara H</div>
<div style={{ fontSize: "var(--text-xs)", color: "var(--text-3)" }}>
Host · responds in ~30 min · joined 2019
</div>
</div>
</div>
<div style={{ display: "flex", gap: 8 }}>
<Button variant="secondary" size="sm">View listing</Button>
<IconButton name="more" variant="secondary" label="More"/>
</div>
</div>
{/* Trip card */}
<div style={{ padding: "16px 28px 0" }}>
<div style={{
display: "flex", gap: 14, padding: 14,
borderRadius: 12, background: "var(--surface-2)",
border: "1px solid var(--border)",
}}>
<div style={{ width: 60, height: 60, borderRadius: 8, overflow: "hidden", flexShrink: 0 }}>
<PhotoSlot label="" tone="sand" aspect="1/1"/>
</div>
<div style={{ flex: 1 }}>
<div style={{ fontSize: "var(--text-sm)", fontWeight: 600 }}>Cliffside cabin in the pines</div>
<div style={{ fontSize: "var(--text-xs)", color: "var(--text-3)" }}>Big Sur · Jun 14 → 19 · 2 guests</div>
<div style={{ marginTop: 6, display: "flex", gap: 6 }}>
<Badge tone="success" dot>Confirmed</Badge>
<Badge>$1,846 total</Badge>
</div>
</div>
<Button variant="ghost" size="sm">Trip details →</Button>
</div>
</div>
{/* Messages */}
<div style={{ flex: 1, overflowY: "auto", padding: "20px 28px" }}>
<div style={{ textAlign: "center", fontSize: "var(--text-xs)", color: "var(--text-3)", margin: "8px 0 18px" }}>
May 22 · Booking confirmed
</div>
<MessageBubble name="Mara H" color="#e8a87c" mine={false} time="10:14am"
body="Hi Mira! So happy to host you and the pup in June. The roads are spectacular this time of year. Will let you know about the gate code closer to."/>
<MessageBubble mine time="10:21am"
body="Thank you Mara! Quick question — is there a good local bakery you'd recommend for sourdough?"/>
<MessageBubble name="Mara H" color="#e8a87c" mine={false} time="10:38am" attachment="Mara's local map.pdf · 2 pages"
body="Of course. Bigotti's is the obvious answer but I'll send you my whole list. The man who runs it remembers everyone's order."/>
<MessageBubble name="Mara H" color="#e8a87c" mine={false} time="10:42am"
body="We can leave the gate code in your message thread the morning of check-in. The cabin will be unlocked when you arrive fire laid, coffee ground."/>
<div style={{ textAlign: "center", marginTop: 10 }}>
<span style={{
display: "inline-block", padding: "4px 10px", borderRadius: 999,
background: "var(--surface-2)", border: "1px solid var(--border)",
fontSize: "var(--text-xs)", color: "var(--text-3)",
}}>Mara is typing…</span>
</div>
</div>
{/* Composer */}
<div style={{ padding: 16, borderTop: "1px solid var(--border)" }}>
<div style={{
display: "flex", alignItems: "flex-end", gap: 10,
padding: 8, borderRadius: 14,
background: "var(--surface)", border: "1px solid var(--border)",
}}>
<IconButton name="plus" size="sm" variant="ghost" label="Attach"/>
<textarea placeholder="Write a message" rows="1" style={{
flex: 1, border: "none", outline: "none", background: "transparent",
fontFamily: "var(--font-sans)", fontSize: "var(--text-md)",
color: "var(--text)", resize: "none", padding: "6px 0",
}}/>
<Button size="sm">Send</Button>
</div>
</div>
</div>
</div>
</MarketplaceDashboardShell>
);
};
// ============================================================
// 7 · HOST DASHBOARD · TODAY
// ============================================================
const AtlasHostDash = () => {
// Build 4 weeks of availability for the heatmap
const weeks = [
["booked","booked","booked","open","open","open","open"],
["booked","booked","booked","booked","booked","booked","booked"],
["open","open","open","blocked","blocked","blocked","blocked"],
["open","open","booked","booked","open","open","open"],
];
// SVG bar chart for monthly earnings
const earnings = [3200, 4100, 3850, 4900, 5400, 6200, 7100, 6800, 5900, 6400, 5200, 4800, 6900, 8200];
const maxE = Math.max(...earnings);
return (
<MarketplaceDashboardShell role="host" active="today" user={{ name: "Mara H", color: "#e8a87c" }}>
<div style={{ padding: "28px 36px 40px", overflow: "auto" }}>
<div style={{
display: "flex", justifyContent: "space-between", alignItems: "baseline",
marginBottom: 22, flexWrap: "wrap", gap: 16,
}}>
<div>
<div style={{
fontSize: "var(--text-xs)", color: "var(--text-3)",
textTransform: "uppercase", letterSpacing: "0.06em",
fontWeight: 500, marginBottom: 4,
}}>Hosting · Monday, May 25</div>
<h1 style={{
fontFamily: "var(--font-display)", fontSize: 32, margin: 0,
fontWeight: 500, letterSpacing: "-0.02em",
}}>Good morning, Mara</h1>
<div style={{ fontSize: "var(--text-sm)", color: "var(--text-2)", marginTop: 4 }}>
You have 1 check-in this week and 2 messages waiting.
</div>
</div>
<div style={{ display: "flex", gap: 8 }}>
<Button variant="secondary">View as guest</Button>
<Button leadingIcon={<Icon name="plus" size={13}/>}>Create listing</Button>
</div>
</div>
{/* KPI strip */}
<div style={{
display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 14, marginBottom: 24,
}}>
<StatTile label="Earnings · MTD" value="$8,240" sub="vs last month" trend={18} icon="bar"/>
<StatTile label="Upcoming bookings" value="6" sub="next 30 days" icon="briefcase"/>
<StatTile label="Rating · 90d" value="4.96" sub="218 reviews" icon="star"/>
<StatTile label="Response rate" value="98%" sub="avg. 30 min" icon="bolt"/>
</div>
<div style={{ display: "grid", gridTemplateColumns: "1.5fr 1fr", gap: 24 }}>
{/* Earnings chart */}
<Card padding={24}>
<div style={{
display: "flex", justifyContent: "space-between", alignItems: "baseline",
marginBottom: 18,
}}>
<div>
<h3 style={{
fontFamily: "var(--font-display)", fontSize: 22, margin: 0,
fontWeight: 500, letterSpacing: "-0.01em",
}}>Earnings</h3>
<div style={{ fontSize: "var(--text-xs)", color: "var(--text-3)", marginTop: 2 }}>Last 14 days</div>
</div>
<Tabs variant="pill" items={[{ label: "Day" }, { label: "Week" }, { label: "Month" }]} active="Day"/>
</div>
<div style={{ position: "relative", height: 180 }}>
{[0, 0.25, 0.5, 0.75, 1].map(p => (
<div key={p} style={{
position: "absolute", left: 0, right: 0,
bottom: `${p * 100}%`, height: 1,
background: "var(--divider)",
}}/>
))}
<div style={{
position: "absolute", inset: 0,
display: "flex", alignItems: "flex-end", gap: 8, paddingRight: 4,
}}>
{earnings.map((v, i) => (
<div key={i} style={{ flex: 1, display: "flex", flexDirection: "column", justifyContent: "flex-end", height: "100%" }}>
<div style={{
width: "100%", height: `${(v / maxE) * 100}%`,
background: i === earnings.length - 1
? `linear-gradient(180deg, var(--accent), var(--accent-2))`
: "var(--surface-alt)",
borderRadius: 4,
}}/>
</div>
))}
</div>
<div style={{
position: "absolute", right: 0, top: -6,
background: "var(--text)", color: "var(--bg)",
padding: "3px 8px", borderRadius: 4,
fontSize: 11, fontWeight: 500,
}}>$820 · today</div>
</div>
<div style={{
display: "flex", justifyContent: "space-between", marginTop: 10,
fontSize: 10, color: "var(--text-3)", fontFamily: "var(--font-mono)",
}}>
{["May 12","M 13","T 14","W 15","T 16","F 17","S 18","S 19","M 20","T 21","W 22","T 23","F 24","Today"].map(d => (
<span key={d}>{d}</span>
))}
</div>
</Card>
{/* Upcoming bookings */}
<Card padding={24}>
<h3 style={{
fontFamily: "var(--font-display)", fontSize: 22, margin: "0 0 16px",
fontWeight: 500, letterSpacing: "-0.01em",
}}>Upcoming check-ins</h3>
{[
{ g: "Mira Reyes", c: "#d4b8a8", date: "Jun 14 · 5 nights", note: "Welcome!" },
{ g: "Sun Ortiz", c: "#a8c8e8", date: "Jul 02 · 3 nights", note: "Repeat guest" },
{ g: "Henri Lamarck", c: "#c8e8a8", date: "Jul 15 · 7 nights", note: "Honeymoon" },
].map(g => (
<div key={g.g} style={{
display: "flex", alignItems: "center", gap: 12, padding: "10px 0",
borderTop: "1px solid var(--divider)",
}}>
<Avatar name={g.g} color={g.c} size={36}/>
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ fontSize: "var(--text-md)", fontWeight: 500 }}>{g.g}</div>
<div style={{ fontSize: "var(--text-xs)", color: "var(--text-3)" }}>
{g.date} · {g.note}
</div>
</div>
<Button size="sm" variant="ghost">Message</Button>
</div>
))}
</Card>
{/* Calendar heatmap */}
<Card padding={24}>
<div style={{
display: "flex", justifyContent: "space-between", alignItems: "baseline",
marginBottom: 16,
}}>
<h3 style={{
fontFamily: "var(--font-display)", fontSize: 22, margin: 0,
fontWeight: 500, letterSpacing: "-0.01em",
}}>Calendar · June 2026</h3>
<Button size="sm" variant="ghost">Manage →</Button>
</div>
<AvailabilityHeatmap weeks={weeks}/>
<div style={{
display: "flex", gap: 16, marginTop: 14, fontSize: "var(--text-xs)", color: "var(--text-2)",
}}>
<span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
<span style={{ width: 10, height: 10, background: "var(--accent-soft)", border: "1px solid var(--accent)", borderRadius: 2 }}/>
Booked
</span>
<span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
<span style={{ width: 10, height: 10, background: "var(--success-soft)", border: "1px solid var(--success)", borderRadius: 2 }}/>
Open
</span>
<span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
<span style={{ width: 10, height: 10, background: "var(--surface-alt)", border: "1px solid var(--text-3)", borderRadius: 2 }}/>
Blocked
</span>
</div>
</Card>
{/* Recent reviews */}
<Card padding={24}>
<h3 style={{
fontFamily: "var(--font-display)", fontSize: 22, margin: "0 0 16px",
fontWeight: 500, letterSpacing: "-0.01em",
}}>Recent reviews</h3>
<ReviewCard author="Naila Choudhury" avatarColor="#e8a87c" rating={5} date="April 2026"
body="Photos don't do it justice. The light at golden hour is something to plan for."/>
<Divider/>
<ReviewCard author="Henri Lamarck" avatarColor="#a8c8e8" rating={4.5} date="March 2026"
body="Beautiful design, very thoughtful. Wifi was patchy for video calls — probably a feature."/>
<Button variant="ghost" full style={{ marginTop: 4 }}>View all 218 →</Button>
</Card>
</div>
</div>
</MarketplaceDashboardShell>
);
};
// ============================================================
// 8 · NEW LISTING — step 3 of 6 ("Make it pop")
// ============================================================
const AtlasNewListing = () => {
return (
<MarketplaceDashboardShell role="host" active="listings" user={{ name: "Mara H", color: "#e8a87c" }}>
<div style={{ display: "flex", flexDirection: "column", height: "100%", overflow: "hidden" }}>
{/* Wizard header */}
<div style={{
padding: "18px 36px", borderBottom: "1px solid var(--border)",
display: "flex", justifyContent: "space-between", alignItems: "center",
}}>
<div>
<div style={{
fontSize: "var(--text-xs)", color: "var(--text-3)",
textTransform: "uppercase", letterSpacing: "0.06em",
fontWeight: 500, marginBottom: 2,
}}>Step 3 of 6 · Make it pop</div>
<h1 style={{
fontFamily: "var(--font-display)", fontSize: 22, margin: 0,
fontWeight: 500, letterSpacing: "-0.01em",
}}>Add photos, title and description</h1>
</div>
<div style={{ display: "flex", gap: 8 }}>
<Button variant="ghost">Save & exit</Button>
<Button variant="secondary">Questions?</Button>
</div>
</div>
{/* Progress */}
<div style={{ padding: "12px 36px", borderBottom: "1px solid var(--border)" }}>
<div style={{ display: "grid", gridTemplateColumns: "repeat(6, 1fr)", gap: 8 }}>
{["About your place","Make it stand out","Make it pop","Set price","Publish","Welcome guests"].map((s, i) => (
<div key={s}>
<div style={{
height: 4, borderRadius: 2,
background: i < 2 ? "var(--text)" : i === 2 ? "var(--accent)" : "var(--surface-alt)",
}}/>
<div style={{
fontSize: 11, marginTop: 6,
color: i === 2 ? "var(--accent)" : i < 2 ? "var(--text)" : "var(--text-3)",
fontWeight: i === 2 ? 600 : 500,
}}>{s}</div>
</div>
))}
</div>
</div>
{/* Body */}
<div style={{ flex: 1, overflowY: "auto", padding: "28px 36px" }}>
<div style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr", gap: 48, maxWidth: 1180, margin: "0 auto" }}>
<div>
{/* Photos */}
<section style={{ marginBottom: 32 }}>
<h2 style={{
fontFamily: "var(--font-display)", fontSize: 26, margin: "0 0 6px",
fontWeight: 500, letterSpacing: "-0.02em",
}}>Photos · 12 of 5 required</h2>
<p style={{ fontSize: "var(--text-sm)", color: "var(--text-2)", margin: "0 0 18px" }}>
Drag to reorder. The first photo is your cover.
</p>
<div style={{
display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 12,
}}>
{[
{ l: "Cover · exterior", tone: "sand", primary: true },
{ l: "Living room", tone: "warm"},
{ l: "Kitchen", tone: "blush"},
{ l: "Bedroom", tone: "ocean"},
{ l: "Deck & view", tone: "sage"},
{ l: "Soaking tub", tone: "warm"},
].map(p => (
<div key={p.l} style={{
position: "relative", borderRadius: "var(--listing-radius)",
overflow: "hidden", border: p.primary ? "2px solid var(--accent)" : "1px solid var(--border)",
}}>
<PhotoSlot label={p.l} tone={p.tone} aspect="4/3"/>
{p.primary && <Badge tone="accent" leadingIcon={<Icon name="star" size={10}/>}
style={{ position: "absolute", top: 10, left: 10 }}>Cover</Badge>}
<IconButton name="more" size="sm" variant="secondary"
style={{ position: "absolute", top: 8, right: 8 }} label="Photo options"/>
</div>
))}
<div style={{
border: "1.5px dashed var(--border-strong)", borderRadius: "var(--listing-radius)",
aspectRatio: "4/3", display: "flex", flexDirection: "column",
alignItems: "center", justifyContent: "center", cursor: "pointer",
color: "var(--text-2)", background: "var(--surface-2)",
}}>
<div style={{
width: 44, height: 44, borderRadius: "50%", background: "var(--surface)",
border: "1px solid var(--border-strong)",
display: "flex", alignItems: "center", justifyContent: "center",
marginBottom: 10,
}}><Icon name="plus" size={20}/></div>
<span style={{ fontSize: "var(--text-sm)", fontWeight: 500 }}>Add more photos</span>
<span style={{ fontSize: "var(--text-xs)", color: "var(--text-3)" }}>or drop them here</span>
</div>
</div>
</section>
{/* Title */}
<section style={{ marginBottom: 28 }}>
<h2 style={{
fontFamily: "var(--font-display)", fontSize: 26, margin: "0 0 6px",
fontWeight: 500, letterSpacing: "-0.02em",
}}>Now, let's give it a title</h2>
<p style={{ fontSize: "var(--text-sm)", color: "var(--text-2)", margin: "0 0 14px" }}>
Short titles work best. Have fun with it you can always change it later.
</p>
<Input value="Cliffside cabin in the pines"
style={{ fontSize: 22, fontFamily: "var(--font-display)", fontWeight: 500, padding: "16px 18px" }}/>
<div style={{ fontSize: "var(--text-xs)", color: "var(--text-3)", marginTop: 8 }}>
32 / 50 characters
</div>
</section>
{/* Description */}
<section>
<h2 style={{
fontFamily: "var(--font-display)", fontSize: 26, margin: "0 0 6px",
fontWeight: 500, letterSpacing: "-0.02em",
}}>Create your description</h2>
<p style={{ fontSize: "var(--text-sm)", color: "var(--text-2)", margin: "0 0 14px" }}>
Share what makes your place special. We'll suggest improvements as you write.
</p>
<Textarea rows={5}
value="Set 80 feet above the Pacific, this A-frame is a quiet, light-soaked retreat. Architecturally restored in 2024 with radiant floors, a wood-burning stove, and a Furlong soaking tub on the deck. Stargazing is the only TV."/>
<div style={{
marginTop: 10, padding: 14, borderRadius: 10,
background: "var(--accent-soft)", display: "flex", gap: 12, alignItems: "flex-start",
}}>
<Icon name="spark" size={16} style={{ color: "var(--accent)", marginTop: 2 }}/>
<div style={{ flex: 1 }}>
<div style={{ fontSize: "var(--text-sm)", fontWeight: 600, color: "var(--text)" }}>
Atlas suggests: lead with sensory details
</div>
<div style={{ fontSize: "var(--text-sm)", color: "var(--text-2)", marginTop: 2, lineHeight: 1.5 }}>
"Wake to ocean light through the redwoods…" tends to perform better than a list of features.
</div>
</div>
<Button size="sm" variant="ghost">Rewrite</Button>
</div>
</section>
</div>
{/* Live preview */}
<aside style={{ position: "sticky", top: 0 }}>
<div style={{
fontSize: "var(--text-xs)", color: "var(--text-3)",
textTransform: "uppercase", letterSpacing: "0.08em",
fontWeight: 500, marginBottom: 12,
}}>Live preview</div>
<ListingCard listing={{
photo: { label: "Big Sur · A-frame", tone: "sand" },
title: "Cliffside cabin in the pines",
subtitle: "Big Sur, California",
price: { amount: 318, period: "/ night" },
rating: 4.94, reviews: 218,
badges: ["superhost"], tags: ["New"],
}}/>
<div style={{
marginTop: 16, padding: 14, borderRadius: 10,
background: "var(--surface)", border: "1px solid var(--border)",
fontSize: "var(--text-xs)", color: "var(--text-2)", lineHeight: 1.5,
}}>
This is how guests will see your listing in search results.
Don't worry you'll be able to fine-tune everything after publishing.
</div>
</aside>
</div>
</div>
{/* Bottom nav */}
<div style={{
padding: "16px 36px", borderTop: "1px solid var(--border)",
display: "flex", justifyContent: "space-between", alignItems: "center",
background: "var(--surface)",
}}>
<Button variant="ghost" leadingIcon={<Icon name="chevLeft" size={13}/>}>Back</Button>
<div style={{ display: "flex", gap: 12, fontSize: "var(--text-xs)", color: "var(--text-3)" }}>
<span>Auto-saved · just now</span>
</div>
<Button trailingIcon={<Icon name="arrow" size={13}/>}>Next · set your price</Button>
</div>
</div>
</MarketplaceDashboardShell>
);
};
// Export to window
Object.assign(window, {
AtlasHome, AtlasSearch, AtlasListing, AtlasCheckout,
AtlasMessages, AtlasGuestDash, AtlasHostDash, AtlasNewListing,
});