/* global React, ReactDOM */ const { useState, useEffect, useRef, useCallback } = React; const BOOKING_URL = "https://calendly.com/littlestarparty1"; const PHONE = "619-617-4905"; const PHONE_TEL = "+16196174905"; /* ============================================================ Package data ============================================================ */ const PACKAGES = [ { id: "star", name: "STAR", tagline: "the essentials", price: 849, deposit: 249, duration: "1.5 hours", capacity: "Birthday girl + 7 friends", extra: "$55 / extra guest", color: "#ff6fb3", bg: "assets/photo-star.jpg", bgPos: "center 18%", short: [ "1.5 hrs of party bus fun", "Makeup + rhinestone face gems", "Hair extension clips + glitter spray", "Mini manicures", "Pink carpet runway show", "Freestyle dance party", "Birthday tiara, sash + goody bag", ], glam: [ "Makeup with rhinestone face gems", "Colorful hair extension clips", "Glitter hairspray", "Mini manicures", "Temporary tattoos for kids", ], experience: [ "1.5 hours of party bus fun", "Pink carpet runway show", "Freestyle dance party", "Music + LED party lights", ], birthdayGirl: [ "Birthday tiara + sash", "Deluxe goody bag", ], }, { id: "popstar", name: "POP STAR", tagline: "for the squad", price: 799, deposit: 249, duration: "1.5 hours", capacity: "Birthday girl + 14 friends (15 total)", extra: "$35 / extra guest · buses fit 20–25", color: "#e91e80", bg: "assets/photo-popstar.jpg", bgPos: "center 25%", isLimited: true, short: [ "Built for bigger groups (15+)", "Dance party + LED lights", "Sing-along mic (every girl)", "Pink carpet photo moments", "Hostess-led games", "Music video atmosphere", "VIP treatment for birthday girl", ], glam: [ "Mini manicure (birthday girl)", "Soft glam makeup + face gems", "Clip-in hair extensions", "Glitter hairspray", "Temporary tattoos", ], experience: [ "1.5 hours of party bus fun", "Dance party with music + LED lights", "Sing-along mic — every girl gets one", "Pink carpet photo moments", "Hostess-led games + interaction", "Music-video-style atmosphere", "✨ Superstar entrance for birthday girl", ], birthdayGirl: [ "Birthday tiara + sash", "Deluxe birthday-girl goodie bag", "Superstar pink-carpet entrance", ], footnote: "Perfect for dance teams, cheer squads, classmates & larger birthday groups.", }, { id: "vip", name: "VIP", tagline: "the full glam", price: 1299, deposit: 449, duration: "2 hours", capacity: "Birthday girl + 9 friends", extra: "$99 / extra guest", color: "#b8186b", bg: "assets/photo-vip.jpg", bgPos: "center 15%", featured: true, short: [ "2 full hours of party bus fun", "Spa robes for all girls", "Full makeup + face gems", "Hair extensions + glitter spray", "Mini manicures + tattoos", "Superstar entrance + sing-along mic", "Deluxe goody bags + tiara gift", ], glam: [ "Spa robes for all girls", "Makeup with rhinestone face gems", "Colorful hair extension clips", "Glitter hairspray", "Mini manicures", "Temporary tattoos for kids", ], experience: [ "2 hours of party bus fun", "Pink carpet runway show", "Freestyle dance party", "Superstar entrance for birthday girl", "Sing-along mic experience (1 mic)", ], birthdayGirl: [ "VIP wristbands + lanyards for all girls", "Tiara + sash", "Deluxe goody bags for all girls", "Flower headband, fancy gloves, feather boa + heart sunglasses gift", ], }, { id: "ultimate", name: "ULTIMATE VIP", tagline: "the full show", price: 1699, deposit: 599, duration: "2 hours", capacity: "Birthday girl + 11 friends", extra: "$125 / extra guest", color: "#5a0a39", bg: "assets/photo-ultimate.jpg", bgPos: "center 22%", short: [ "Choose a theme (K-pop, princess, etc.)", "Spa robes + mask + cucumber eyes", "Full glam + clip-in braids", "Themed decor + themed music", "Sing-along mic (every girl)", "Superstar entrance", "Themed deluxe goody bags", ], glam: [ "Spa robes for all girls", "Spa mask + cucumber eye patches", "Makeup with rhinestone face gems", "Colorful clip-in hair braids", "Glitter hairspray", "Mini manicures", "Temporary tattoos for kids", ], experience: [ "2 hours of party bus fun", "Theme of your choice (K-pop, princess, etc.)", "Themed decor + themed music experience", "Pink carpet runway show", "Freestyle dance party", "Superstar entrance for birthday girl", "Sing-along mic — every girl gets one", ], birthdayGirl: [ "VIP wristbands + lanyards for all girls", "Tiara + sash", "Themed deluxe goody bags for all girls", "Flower headband, fancy gloves, feather boa + heart sunglasses gift", ], }, ]; const ADDONS = [ { name: "Spa mask + cucumber eyes", price: "$10 / girl", icon: "spa" }, { name: "Sing-along mic experience", price: "$10 / girl", icon: "mic" }, { name: "Flower headbands", price: "$5 each", icon: "flower" }, { name: "Fancy gloves", price: "$5 each", icon: "glove" }, { name: "Themed party decor upgrade", price: "$300 extra", icon: "disco" }, { name: "Feather fringe boas", price: "$10 each", icon: "boa" }, { name: "Mermaid face gems", price: "$10 each", icon: "gem" }, { name: "Clip-in braids", price: "$10 each", icon: "braid" }, { name: "Heart-shaped sunglasses", price: "$3.50 each", icon: "heart" }, ]; const FAQ = [ { q: "Where do you serve and is there a travel fee?", a: "We're based at the Palomar Transit Center in Chula Vista and serve all of San Diego, Orange County, Temecula and surrounding areas. Travel fees start at $49 for 0–30 miles and tier up by distance — check the Travel section above to find your city. Outside our usual range? Give us a call and we'll quote it.", }, { q: "How does it work — do you drive the kids around?", a: "The party bus parks right in your driveway (or wherever you'd like) and the whole experience happens inside while it's parked. No driving required — it's a private studio on wheels with disco lights, pink leather seats, a sing-along mic, mirrors, and everything they need to feel like total stars.", }, { q: "What ages is this for?", a: "Our happiest little stars are usually 5–12, but we've hosted everyone from 4-year-old princess parties to tween dance-team celebrations. We tailor the energy to the age group.", }, { q: "How long is each experience?", a: "STAR + POP STAR = 1.5 hours of pure magic. VIP + ULTIMATE VIP = 2 full hours so there's time for the spa + the full glam treatment + the pink-carpet show.", }, { q: "Can boys come too?", a: "Yes — boys are welcome at no extra charge and don't count against your headcount. Since most boys come along for the dance-party energy, they typically don't take part in the glam services (makeup, mani, hair). Everyone has a blast either way.", }, { q: "What does the deposit cover and when is the rest due?", a: "The deposit locks in your date — $249 for the STAR and POP STAR packages, $449 for VIP, and $599 for Ultimate VIP. The remaining balance is due the Monday before the event. Dates fill up fast — especially spring + summer weekends — so book early!", }, { q: "Can I add my own theme or decor?", a: "Yes! The Ultimate VIP includes a custom theme of your choice. For the other packages, themed decor is a $300 add-on. K-pop, princess, mermaid, Taylor — bring us the vibe and we'll bring it to life.", }, ]; const REVIEWS = [ { quote: "My daughter literally cried when it was over because she didn't want it to end. The hostess made every single girl feel like the main character. Worth every penny.", name: "Maria L.", meta: "Carlsbad · 9th birthday", initial: "M", }, { quote: "The bus pulled up and 12 girls SCREAMED. The makeup, the spa robes, the pink carpet — they thought they were on a TV show. Best party we've ever thrown.", name: "Jessica T.", meta: "Newport Beach · 7th birthday", initial: "J", }, { quote: "I'm a party planner and Little Stars is now my go-to recommendation. The setup is gorgeous, the team is professional, and the kids leave glowing. Five stars.", name: "Andrea R.", meta: "Temecula · group party", initial: "A", }, ]; const TRAVEL_TIERS = [ { id: "z1", fee: 49, range: "0–30 miles", label: "In our backyard", cities: [ "Chula Vista", "National City", "Bonita", "Imperial Beach", "San Diego (Downtown)", "Hillcrest", "Mission Valley", "Mission Hills", "Coronado", "La Jolla", "Pacific Beach", "Ocean Beach", "Point Loma", "El Cajon", "La Mesa", "Lemon Grove", "Santee", "Spring Valley", ], }, { id: "z2", fee: 79, range: "31–50 miles", label: "Close to home", cities: [ "Poway", "Del Mar", "Solana Beach", "Encinitas", "Cardiff", "Rancho Santa Fe", "Rancho Bernardo", "Scripps Ranch", "Mira Mesa", "Carmel Valley", "Sorrento Valley", "San Marcos", "Escondido", "Carlsbad", "Ramona", ], }, { id: "z3", fee: 125, range: "51–70 miles", label: "A little further", cities: [ "Oceanside", "Vista", "Fallbrook", "Bonsall", "Valley Center", "San Clemente", "Dana Point", ], }, { id: "z4", fee: 175, range: "71–90 miles", label: "Worth the drive", cities: [ "Temecula", "Murrieta", "Laguna Niguel", "Laguna Beach", "Aliso Viejo", "Mission Viejo", "Lake Forest", "Irvine", "Costa Mesa", "Newport Beach", ], }, { id: "z5", fee: "239+", range: "91+ miles", label: "Special trip (custom quote)", cities: [ "Anaheim", "Santa Ana", "Orange", "Huntington Beach", "Fullerton", "Long Beach", "Corona", ], }, ]; /* ============================================================ Icons ============================================================ */ const Star = ({ size = 24, fill = "currentColor" }) => ( ); const Sparkle = ({ size = 20 }) => ( ); const PlayIcon = () => ( ); const ArrowRight = ({ size = 16 }) => ( ); const Crown = ({ size = 24 }) => ( ); const MutedIcon = () => ( ); const UnmutedIcon = () => ( ); const AddonIcon = ({ kind }) => { const props = { width: 28, height: 28, viewBox: "0 0 24 24", fill: "currentColor", xmlns: "http://www.w3.org/2000/svg" }; switch (kind) { case "spa": return ; case "mic": return ; case "flower": return ; case "glove": return ; case "disco": return ; case "boa": return ; case "gem": return ; case "braid": return ; case "heart": return ; default: return null; } }; /* ============================================================ Nav ============================================================ */ function Nav() { return ( ); } /* ============================================================ Hero ============================================================ */ function Hero() { const videoRef = useRef(null); const [muted, setMuted] = useState(true); const toggleMute = () => { if (videoRef.current) { videoRef.current.muted = !videoRef.current.muted; setMuted(videoRef.current.muted); } }; return (
Now booking spring & summer

Birthdays
become core memories
on wheels.

A private, neon-lit celebration where she sings, dances, glams up and feels like the star of the day. Pulls right up to your driveway in San Diego, Orange County, Temecula and beyond.

Book her party See packages
★★★★★ 200+ happy birthdays
San Diego · OC · Temecula
); } /* ============================================================ Trust strip ============================================================ */ function TrustStrip() { const items = [ { icon: "★", text: "Rated 5/5 by parents" }, { icon: "🚌", text: "Private studio on wheels" }, { icon: "✨", text: "Pulls into your driveway" }, { icon: "📍", text: "San Diego · OC · Temecula" }, { icon: "🎂", text: "Ages 5–12 (we flex it)" }, ]; return (
{items.map((it, i) => (
{it.icon} {it.text}
))}
); } /* ============================================================ How it works ============================================================ */ function HowItWorks() { const steps = [ { n: "01", t: "Pick her vibe", p: "Choose from four packages — from a sweet glam session to a themed pop-star show. Customize with add-ons to make it hers.", }, { n: "02", t: "We pull up", p: "Our pink party bus parks in your driveway. Pink carpet rolls out. Disco lights on. She makes her superstar entrance to cheers.", }, { n: "03", t: "She's the star", p: "Glam, spa, sing-along, dance — our hostess runs the entire experience while you actually get to enjoy the party.", }, ]; return (
The experience

Not just a party.
A core memory.

Three simple steps. Zero stress for you. All sparkle for her.

{steps.map((s, i) => (
{s.n}

{s.t}

{s.p}

))}
); } /* ============================================================ Packages ============================================================ */ function Packages({ onSelect }) { return (
Four ways to celebrate

Choose her package

Every package includes a hostess, the pink carpet entrance and all the magic. Pick the one that fits her crew.

{PACKAGES.map((p) => (
{p.featured ?
MOST POPULAR
: null}
the {p.name}
$ {p.price}
{p.duration} · {p.capacity}
${p.deposit} deposit to reserve your date
    {p.short.slice(0, 5).map((f, i) => (
  • {f}
  • ))}
Book this
))}
); } /* ============================================================ Package Modal ============================================================ */ function PackageModal({ pkg, onClose }) { useEffect(() => { const onEsc = (e) => { if (e.key === "Escape") onClose(); }; document.addEventListener("keydown", onEsc); document.body.style.overflow = "hidden"; return () => { document.removeEventListener("keydown", onEsc); document.body.style.overflow = ""; }; }, [onClose]); if (!pkg) return null; return (
e.stopPropagation()}>
{pkg.tagline}
{pkg.isLimited ? (
✨ LIMITED TIME
) : null}

The {pkg.name} package

${pkg.price} {pkg.duration} · {pkg.capacity} · {pkg.extra}
${pkg.deposit} deposit reserves your date · remaining balance due the Monday before the event
The experience
    {pkg.experience.map((it, i) =>
  • {it}
  • )}
Glam treatment
    {pkg.glam.map((it, i) =>
  • {it}
  • )}
For the birthday girl
    {pkg.birthdayGirl.map((it, i) =>
  • {it}
  • )}
Capacity
  • {pkg.capacity}
  • {pkg.extra}
  • {pkg.duration} total
{pkg.footnote ? (

✨ {pkg.footnote}

) : null}
Book the {pkg.name} package Call us
); } /* ============================================================ Video reel (gallery) ============================================================ */ function Reel() { const cards = [ { src: "assets/video-hero.mp4", label: "Inside the bus" }, { src: "assets/video-2.mp4", label: "Pink carpet entrance" }, { src: "assets/video-3.mp4", label: "Glam time" }, { src: "assets/video-4.mp4", label: "Sing-along mic" }, { src: "assets/video-5.mp4", label: "Dance party" }, { src: "assets/video-6.mp4", label: "Spa squad" }, ]; const trackRef = useRef(null); // Auto-play videos when in view useEffect(() => { const obs = new IntersectionObserver((entries) => { entries.forEach((e) => { const v = e.target; if (e.isIntersecting) v.play().catch(() => {}); else v.pause(); }); }, { threshold: 0.4 }); trackRef.current?.querySelectorAll("video").forEach((v) => obs.observe(v)); return () => obs.disconnect(); }, []); return ( ); } /* ============================================================ Travel Fees ============================================================ */ function TravelFees() { const [query, setQuery] = useState(""); const q = query.trim().toLowerCase(); const isFiltering = q.length > 0; // Find matched tier(s) const matched = isFiltering ? TRAVEL_TIERS .map((t) => ({ ...t, cities: t.cities.filter((c) => c.toLowerCase().includes(q)), })) .filter((t) => t.cities.length > 0) : TRAVEL_TIERS; const anyMatch = isFiltering && matched.length > 0; return (
Travel fees

We come to you.

We leave from the Palomar Transit Center in Chula Vista — travel fees are tiered by driving distance. Find your city below or just give us a call.

setQuery(e.target.value)} /> {isFiltering ? ( ) : null}
{isFiltering && !anyMatch ? (

We don't have "{query}" in our quick list — but that doesn't mean we can't come!

Call us for a quote
) : null}
{matched.map((t) => (
$ {t.fee}
{t.label}
{t.range}
{t.cities.map((c, i) => ( {isFiltering ? ( ) : c} ))}
))}
Don't see your city? No worries — we travel beyond this list all the time. Give us a call at {PHONE} and we'll send you a custom quote.
); } function Highlight({ text, q }) { const idx = text.toLowerCase().indexOf(q); if (idx < 0) return text; return ( <> {text.slice(0, idx)} {text.slice(idx, idx + q.length)} {text.slice(idx + q.length)} ); } /* ============================================================ Add-ons ============================================================ */ function Addons() { return (
Make it extra

Sparkly add-ons

Stack any of these onto any package to make her day even more "her."

{ADDONS.map((a, i) => (

{a.name}

{a.price}
))}
); } /* ============================================================ Social TikTok strip ============================================================ */ function Social() { const tiles = [ "tt-01.png","tt-02.png","tt-03.png","tt-04.png","tt-05.png","tt-06.png", "tt-07.png","tt-08.png","tt-09.png","tt-10.png","tt-11.png","tt-12.png", ]; return (
From our feed

@lilstarsparties

Instagram TikTok
{tiles.map((t, i) => ( ))}
); } /* ============================================================ Reviews ============================================================ */ function Reviews() { return (
Parents are talking

The reviews are in.

Here's what moms and dads tell us after the bus pulls away.

{REVIEWS.map((r, i) => (
★★★★★
"{r.quote}"
{r.initial}
{r.name}
{r.meta}
))}
); } /* ============================================================ FAQ ============================================================ */ function FaqSection() { const [open, setOpen] = useState(0); return (
The fine print

Common questions

{FAQ.map((f, i) => (
{f.a}
))}
); } /* ============================================================ Booking CTA ============================================================ */ function BookingCta() { return (

Spring & summer dates
are filling fast.

Lock in her date with a deposit starting at $249. Takes 90 seconds.

Book on the calendar
or talk to a real human → {PHONE} @lilstarsparties
); } /* ============================================================ Footer ============================================================ */ function Footer() { return ( ); } /* ============================================================ App ============================================================ */ function App() { const [activePkg, setActivePkg] = useState(null); return ( <>