/* 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" }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill={fill} xmlns="http://www.w3.org/2000/svg">
    <path d="M12 2l2.39 7.36H22l-6.18 4.49L18.21 22 12 17.5 5.79 22l2.39-8.15L2 9.36h7.61L12 2z" />
  </svg>
);

const Sparkle = ({ size = 20 }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill="currentColor" xmlns="http://www.w3.org/2000/svg">
    <path d="M12 0l1.8 6.5L20 8l-6.2 1.5L12 16l-1.8-6.5L4 8l6.2-1.5L12 0z" />
    <path d="M19 14l.9 3.1L23 18l-3.1.9L19 22l-.9-3.1L15 18l3.1-.9L19 14z" opacity="0.7"/>
    <path d="M5 14l.6 2.4L8 17l-2.4.6L5 20l-.6-2.4L2 17l2.4-.6L5 14z" opacity="0.5"/>
  </svg>
);

const PlayIcon = () => (
  <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
    <path d="M8 5v14l11-7L8 5z" />
  </svg>
);

const ArrowRight = ({ size = 16 }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" xmlns="http://www.w3.org/2000/svg">
    <path d="M5 12h14M13 6l6 6-6 6" />
  </svg>
);

const Crown = ({ size = 24 }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill="currentColor" xmlns="http://www.w3.org/2000/svg">
    <path d="M3 8l3 9h12l3-9-5 3-4-6-4 6-5-3zm2 11h14v2H5v-2z"/>
  </svg>
);

const MutedIcon = () => (
  <svg viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
    <path d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"/>
  </svg>
);
const UnmutedIcon = () => (
  <svg viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
    <path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"/>
  </svg>
);

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 <svg {...props}><path d="M12 22c-4.97 0-9-4.03-9-9 0-3.85 2.42-7.13 5.83-8.4-1.05 1.85-1.67 4.05-1.67 6.4 0 2.5.93 4.78 2.46 6.51A8.957 8.957 0 0012 19c1.42 0 2.76-.33 3.95-.92A8.95 8.95 0 0018 13c0-2.35-.62-4.55-1.67-6.4C19.58 7.87 22 11.15 22 15c0 3.87-3.13 7-7 7H12z"/></svg>;
    case "mic": return <svg {...props}><path d="M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z"/></svg>;
    case "flower": return <svg {...props}><path d="M12 22c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm0-10c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm-8 4c0-1.1.9-2 2-2s2 .9 2 2-.9 2-2 2-2-.9-2-2zm16 0c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zM12 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3z"/></svg>;
    case "glove": return <svg {...props}><path d="M7 4c-1.1 0-2 .9-2 2v10c0 3.31 2.69 6 6 6h2c3.31 0 6-2.69 6-6V9c0-1.1-.9-2-2-2s-2 .9-2 2V6c0-1.1-.9-2-2-2s-2 .9-2 2v-.5C11 4.67 10.33 4 9.5 4S8 4.67 8 5.5V6c0-1.1-.45-2-1-2z"/></svg>;
    case "disco": return <svg {...props}><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3v18M5.6 5.6l12.8 12.8M18.4 5.6L5.6 18.4" stroke="white" strokeWidth="0.6" fill="none"/></svg>;
    case "boa": return <svg {...props}><path d="M6 4c-1.1 0-2 .9-2 2 0 .5.2 1 .5 1.4-.3.4-.5.9-.5 1.4 0 1.1.9 2 2 2 .5 0 1-.2 1.4-.5.4.3.9.5 1.4.5 1.1 0 2-.9 2-2 0-.5-.2-1-.5-1.4.3-.4.5-.9.5-1.4 0-1.1-.9-2-2-2-.5 0-1 .2-1.4.5C7 4.2 6.5 4 6 4zm12 8c-1.1 0-2 .9-2 2 0 .5.2 1 .5 1.4-.3.4-.5.9-.5 1.4 0 1.1.9 2 2 2 .5 0 1-.2 1.4-.5.4.3.9.5 1.4.5 1.1 0 2-.9 2-2 0-.5-.2-1-.5-1.4.3-.4.5-.9.5-1.4 0-1.1-.9-2-2-2-.5 0-1 .2-1.4.5-.4-.3-.9-.5-1.4-.5z"/></svg>;
    case "gem": return <svg {...props}><path d="M12 2l4 6-4 14-4-14 4-6zm-6 6l2 14-6-8 4-6zm12 0l4 6-6 8 2-14z"/></svg>;
    case "braid": return <svg {...props}><path d="M12 2c-1 0-2 .8-2 2 0 .5.2 1 .5 1.4-1 1-1.5 2.2-1.5 3.6 0 .8.2 1.5.5 2.1-1 .8-1.5 2-1.5 3.4 0 .8.2 1.5.5 2.1-1 .8-1.5 2-1.5 3.4 0 1.1.9 2 2 2h6c1.1 0 2-.9 2-2 0-1.4-.5-2.6-1.5-3.4.3-.6.5-1.3.5-2.1 0-1.4-.5-2.6-1.5-3.4.3-.6.5-1.3.5-2.1 0-1.4-.5-2.6-1.5-3.6.3-.4.5-.9.5-1.4 0-1.2-1-2-2-2z"/></svg>;
    case "heart": return <svg {...props}><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/></svg>;
    default: return null;
  }
};

/* ============================================================
   Nav
   ============================================================ */
function Nav() {
  return (
    <nav className="nav">
      <div className="nav-inner">
        <a className="brand" href="#top">
          <div className="brand-mark">
            <Crown size={20} />
          </div>
          <div>
            <div className="brand-name">Little Stars</div>
            <div className="brand-sub">party bus</div>
          </div>
        </a>
        <div className="nav-links">
          <a href="#experience">Experience</a>
          <a href="#packages">Packages</a>
          <a href="#gallery">Gallery</a>
          <a href="#travel">Travel</a>
          <a href="#reviews">Reviews</a>
          <a href="#faq">FAQ</a>
        </div>
        <div className="nav-cta">
          <div className="nav-phone">Call <span>{PHONE}</span></div>
          <a className="btn btn-primary btn-sm" href={BOOKING_URL} target="_blank" rel="noopener">
            Book Now <ArrowRight size={14} />
          </a>
        </div>
      </div>
    </nav>
  );
}

/* ============================================================
   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 (
    <header className="hero" id="top">
      <div className="sparkle s1"><Sparkle /></div>
      <div className="sparkle s2"><Sparkle size={14} /></div>
      <div className="sparkle s3"><Sparkle size={24} /></div>
      <div className="sparkle s4"><Sparkle size={12} /></div>

      <div className="hero-grid">
        <div className="hero-copy">
          <div className="eyebrow-row">
            <span className="dot"></span>
            <span className="eyebrow">Now booking spring & summer</span>
          </div>
          <h1>
            Birthdays<br />
            <span className="pink">become</span> <span className="script">core memories</span><br />
            on wheels.
          </h1>
          <p className="lede">
            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.
          </p>
          <div className="hero-cta-row">
            <a className="btn btn-primary btn-lg" href={BOOKING_URL} target="_blank" rel="noopener">
              Book her party <ArrowRight />
            </a>
            <a className="btn btn-ghost btn-lg" href="#packages">See packages</a>
          </div>
          <div className="hero-trust">
            <div className="hero-trust-item">
              <span className="stars-row">★★★★★</span>
              <span>200+ happy birthdays</span>
            </div>
            <div className="hero-trust-item">
              <Sparkle size={14} />
              <span>San Diego · OC · Temecula</span>
            </div>
          </div>
        </div>

        <div className="hero-visual">
          <video
            ref={videoRef}
            src="assets/video-hero.mp4"
            autoPlay
            muted
            loop
            playsInline
            poster="assets/tt-14.png"
          />
          <div className="live-label">
            <span className="pulse"></span>
            <span>inside the bus</span>
          </div>
          <button className="mute-btn" onClick={toggleMute} aria-label="Toggle sound">
            {muted ? <MutedIcon /> : <UnmutedIcon />}
          </button>

          <div className="badge-floater float-1">
            <span className="icon">🎤</span> Every girl gets a mic
          </div>
          <div className="badge-floater float-2">
            <span className="icon">💖</span> Pink carpet entrance
          </div>
          <div className="badge-floater float-3">
            <Sparkle size={14} /> Disco vibes
          </div>
        </div>
      </div>
    </header>
  );
}

/* ============================================================
   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 (
    <div className="trust-strip">
      <div className="trust-strip-inner">
        {items.map((it, i) => (
          <div className="trust-item" key={i}>
            <span className="ico">{it.icon}</span>
            <span>{it.text}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ============================================================
   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 (
    <section className="how" id="experience">
      <div className="container">
        <div className="section-head">
          <span className="eyebrow">The experience</span>
          <h2>Not just a party.<br /><span className="script">A core memory.</span></h2>
          <p>Three simple steps. Zero stress for you. All sparkle for her.</p>
        </div>
        <div className="how-grid">
          {steps.map((s, i) => (
            <div className="how-card" key={i}>
              <div className="num">{s.n}</div>
              <h3>{s.t}</h3>
              <p>{s.p}</p>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   Packages
   ============================================================ */
function Packages({ onSelect }) {
  return (
    <section className="packages" id="packages">
      <div className="container">
        <div className="section-head">
          <span className="eyebrow">Four ways to celebrate</span>
          <h2>Choose her <span className="script">package</span></h2>
          <p>Every package includes a hostess, the pink carpet entrance and all the magic. Pick the one that fits her crew.</p>
        </div>
        <div className="pkg-grid">
          {PACKAGES.map((p) => (
            <article
              key={p.id}
              className={`pkg-card${p.featured ? " is-featured" : ""}${p.isLimited ? " is-limited" : ""}`}
            >
              {p.featured ? <div className="pkg-flag">MOST POPULAR</div> : null}
              <div
                className="pkg-img"
                style={{ backgroundImage: `url(${p.bg})`, backgroundPosition: p.bgPos }}
              >
                <div className="pkg-name">
                  <span className="small">the</span>
                  {p.name}
                </div>
              </div>
              <div className="pkg-body">
                <div className="pkg-price">
                  <span className="cur">$</span>
                  <span className="num">{p.price}</span>
                </div>
                <div className="pkg-meta">
                  {p.duration} · {p.capacity}<br />
                  <span style={{ color: "var(--pink-600)", fontWeight: 700 }}>${p.deposit} deposit</span> to reserve your date
                </div>
                <ul className="pkg-features">
                  {p.short.slice(0, 5).map((f, i) => (
                    <li key={i}>{f}</li>
                  ))}
                </ul>
                <div className="pkg-actions">
                  <a className="btn btn-primary" href={BOOKING_URL} target="_blank" rel="noopener">
                    Book this
                  </a>
                  <button className="pkg-details-link" onClick={() => onSelect(p)}>
                    See full details
                  </button>
                </div>
              </div>
            </article>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   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 (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <button className="modal-close" onClick={onClose} aria-label="Close">×</button>
        <div className="modal-hero" style={{ backgroundImage: `url(${pkg.bg})`, backgroundPosition: pkg.bgPos }}></div>
        <div className="modal-body">
          <div className="tape">{pkg.tagline}</div>
          {pkg.isLimited ? (
            <div style={{
              display: "inline-flex", alignItems: "center", gap: 6,
              background: "linear-gradient(135deg, #e91e80, #b8186b)",
              color: "white", padding: "5px 12px", borderRadius: 999,
              fontSize: 11, fontWeight: 800, letterSpacing: "0.14em",
              marginLeft: 8, verticalAlign: "middle"
            }}>✨ LIMITED TIME</div>
          ) : null}
          <h3 style={{ marginTop: 12 }}>The {pkg.name} package</h3>
          <div className="modal-price">
            <span className="num">${pkg.price}</span>
            <span className="extras">{pkg.duration} · {pkg.capacity} · {pkg.extra}</span>
          </div>
          <div style={{ background: "var(--pink-50)", border: "1px solid var(--pink-200)", borderRadius: 12, padding: "12px 16px", marginBottom: 24, fontSize: 14, color: "var(--ink-2)" }}>
            <strong style={{ color: "var(--pink-700)" }}>${pkg.deposit} deposit</strong> reserves your date · remaining balance due the Monday before the event
          </div>
          <div className="modal-cols">
            <div className="modal-col">
              <h5>The experience</h5>
              <ul>
                {pkg.experience.map((it, i) => <li key={i}>{it}</li>)}
              </ul>
            </div>
            <div className="modal-col">
              <h5>Glam treatment</h5>
              <ul>
                {pkg.glam.map((it, i) => <li key={i}>{it}</li>)}
              </ul>
            </div>
          </div>
          <div className="modal-cols" style={{ marginBottom: pkg.footnote ? 18 : 0 }}>
            <div className="modal-col">
              <h5>For the birthday girl</h5>
              <ul>
                {pkg.birthdayGirl.map((it, i) => <li key={i}>{it}</li>)}
              </ul>
            </div>
            <div className="modal-col">
              <h5>Capacity</h5>
              <ul>
                <li>{pkg.capacity}</li>
                <li>{pkg.extra}</li>
                <li>{pkg.duration} total</li>
              </ul>
            </div>
          </div>
          {pkg.footnote ? (
            <p style={{ color: "var(--ink-3)", fontSize: 14, fontStyle: "italic", marginBottom: 18 }}>
              ✨ {pkg.footnote}
            </p>
          ) : null}
          <div className="modal-actions">
            <a className="btn btn-primary" href={BOOKING_URL} target="_blank" rel="noopener" style={{ flex: 1 }}>
              Book the {pkg.name} package <ArrowRight />
            </a>
            <a className="btn btn-ghost" href={`tel:${PHONE_TEL}`}>Call us</a>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ============================================================
   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 (
    <section className="reel" id="gallery">
      <div className="container">
        <div className="section-head">
          <span className="eyebrow">The energy</span>
          <h2>Real parties.<br /><span className="script">Real magic.</span></h2>
          <p>Scroll through actual moments from inside the bus.</p>
        </div>
      </div>
      <div className="container" style={{ overflow: "visible" }}>
        <div className="reel-track" ref={trackRef}>
          {cards.map((c, i) => (
            <div className="reel-card" key={i}>
              <video src={c.src} muted loop playsInline preload="metadata" />
              <div className="reel-overlay"></div>
              <div className="reel-play"><PlayIcon /></div>
              <div className="reel-label">{c.label}</div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   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 (
    <section className="travel" id="travel">
      <div className="container">
        <div className="section-head">
          <span className="eyebrow">Travel fees</span>
          <h2>We come to <span className="script">you.</span></h2>
          <p>
            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.
          </p>
        </div>

        <div className="travel-search">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" width="20" height="20">
            <circle cx="11" cy="11" r="8" />
            <line x1="21" y1="21" x2="16.65" y2="16.65" />
          </svg>
          <input
            type="text"
            placeholder="Type your city — e.g. Carlsbad, Newport, Temecula…"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
          />
          {isFiltering ? (
            <button className="travel-clear" onClick={() => setQuery("")} aria-label="Clear">×</button>
          ) : null}
        </div>

        {isFiltering && !anyMatch ? (
          <div className="travel-no-match">
            <p>We don't have <strong>"{query}"</strong> in our quick list — but that doesn't mean we can't come!</p>
            <a className="btn btn-primary btn-sm" href={`tel:${PHONE_TEL}`}>Call us for a quote</a>
          </div>
        ) : null}

        <div className="travel-grid">
          {matched.map((t) => (
            <div className="travel-tier" key={t.id}>
              <div className="travel-tier-head">
                <div className="travel-fee">
                  <span className="cur">$</span>
                  <span className="num">{t.fee}</span>
                </div>
                <div className="travel-meta">
                  <div className="travel-label">{t.label}</div>
                  <div className="travel-range">{t.range}</div>
                </div>
              </div>
              <div className="travel-cities">
                {t.cities.map((c, i) => (
                  <span className="travel-chip" key={i}>
                    {isFiltering ? (
                      <Highlight text={c} q={q} />
                    ) : c}
                  </span>
                ))}
              </div>
            </div>
          ))}
        </div>

        <div className="travel-note">
          <strong>Don't see your city?</strong> No worries — we travel beyond this list all the time. Give us a call at <a href={`tel:${PHONE_TEL}`}>{PHONE}</a> and we'll send you a custom quote.
        </div>
      </div>
    </section>
  );
}

function Highlight({ text, q }) {
  const idx = text.toLowerCase().indexOf(q);
  if (idx < 0) return text;
  return (
    <>
      {text.slice(0, idx)}
      <mark>{text.slice(idx, idx + q.length)}</mark>
      {text.slice(idx + q.length)}
    </>
  );
}

/* ============================================================
   Add-ons
   ============================================================ */
function Addons() {
  return (
    <section className="addons">
      <div className="container">
        <div className="section-head">
          <span className="eyebrow">Make it extra</span>
          <h2>Sparkly <span className="script">add-ons</span></h2>
          <p>Stack any of these onto any package to make her day even more "her."</p>
        </div>
        <div className="addons-grid">
          {ADDONS.map((a, i) => (
            <div className="addon-card" key={i}>
              <div className="addon-emoji"><AddonIcon kind={a.icon} /></div>
              <div>
                <h4>{a.name}</h4>
                <div className="addon-price">{a.price}</div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   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 (
    <section className="social">
      <div className="container">
        <div className="social-header">
          <div>
            <span className="eyebrow">From our feed</span>
            <h2><span className="at">@lilstarsparties</span></h2>
          </div>
          <div className="social-follow">
            <a className="social-pill" href="https://instagram.com/lilstarsparties" target="_blank" rel="noopener">
              <svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.2c3.2 0 3.6 0 4.8.1 1.2 0 1.8.2 2.2.4.6.2 1 .5 1.4 1 .5.4.8.8 1 1.4.2.4.4 1 .4 2.2.1 1.2.1 1.6.1 4.8s0 3.6-.1 4.8c0 1.2-.2 1.8-.4 2.2-.2.6-.5 1-1 1.4-.4.5-.8.8-1.4 1-.4.2-1 .4-2.2.4-1.2.1-1.6.1-4.8.1s-3.6 0-4.8-.1c-1.2 0-1.8-.2-2.2-.4-.6-.2-1-.5-1.4-1-.5-.4-.8-.8-1-1.4-.2-.4-.4-1-.4-2.2C2.2 15.6 2.2 15.2 2.2 12s0-3.6.1-4.8c0-1.2.2-1.8.4-2.2.2-.6.5-1 1-1.4.4-.5.8-.8 1.4-1 .4-.2 1-.4 2.2-.4C8.4 2.2 8.8 2.2 12 2.2zm0 1.8c-3.1 0-3.5 0-4.7.1-1.1 0-1.7.2-2.1.4-.5.2-.9.4-1.3.8-.4.4-.6.8-.8 1.3-.2.4-.3 1-.4 2.1C2.6 9.9 2.6 10.3 2.6 12s0 2.1.1 3.3c0 1.1.2 1.7.4 2.1.2.5.4.9.8 1.3.4.4.8.6 1.3.8.4.2 1 .3 2.1.4 1.2.1 1.6.1 4.7.1s3.5 0 4.7-.1c1.1 0 1.7-.2 2.1-.4.5-.2.9-.4 1.3-.8.4-.4.6-.8.8-1.3.2-.4.3-1 .4-2.1.1-1.2.1-1.6.1-3.3s0-2.1-.1-3.3c0-1.1-.2-1.7-.4-2.1-.2-.5-.4-.9-.8-1.3-.4-.4-.8-.6-1.3-.8-.4-.2-1-.3-2.1-.4C15.5 4 15.1 4 12 4zm0 3.1c2.7 0 4.9 2.2 4.9 4.9s-2.2 4.9-4.9 4.9-4.9-2.2-4.9-4.9 2.2-4.9 4.9-4.9zm0 8.1c1.8 0 3.2-1.4 3.2-3.2s-1.4-3.2-3.2-3.2-3.2 1.4-3.2 3.2 1.4 3.2 3.2 3.2zm6.2-8.3c0 .6-.5 1.1-1.1 1.1s-1.1-.5-1.1-1.1.5-1.1 1.1-1.1 1.1.5 1.1 1.1z"/></svg>
              Instagram
            </a>
            <a className="social-pill" href="https://tiktok.com/@littlestarparty" target="_blank" rel="noopener">
              <svg viewBox="0 0 24 24" fill="currentColor"><path d="M19.6 6.3c-1.4-.3-2.6-1-3.5-2-.9-1-1.4-2.3-1.4-3.7H11v14c0 1.5-1.2 2.7-2.7 2.7s-2.7-1.2-2.7-2.7 1.2-2.7 2.7-2.7c.3 0 .6.1.9.2v-3.7c-.3 0-.6-.1-.9-.1-3.5 0-6.3 2.8-6.3 6.3S5 21 8.5 21s6.3-2.8 6.3-6.3v-6c1.3 1 3 1.6 4.8 1.6V6.3z"/></svg>
              TikTok
            </a>
          </div>
        </div>
        <div className="social-grid">
          {tiles.map((t, i) => (
            <a className="social-tile" key={i} href="https://instagram.com/lilstarsparties" target="_blank" rel="noopener">
              <img src={`assets/${t}`} alt="" loading="lazy" />
            </a>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   Reviews
   ============================================================ */
function Reviews() {
  return (
    <section className="reviews" id="reviews">
      <div className="container">
        <div className="section-head">
          <span className="eyebrow">Parents are talking</span>
          <h2>The reviews are <span className="script">in.</span></h2>
          <p>Here's what moms and dads tell us after the bus pulls away.</p>
        </div>
        <div className="review-grid">
          {REVIEWS.map((r, i) => (
            <div className="review-card" key={i}>
              <div className="review-stars">★★★★★</div>
              <blockquote>"{r.quote}"</blockquote>
              <div className="review-author">
                <div className="review-avatar">{r.initial}</div>
                <div>
                  <div className="review-name">{r.name}</div>
                  <div className="review-meta">{r.meta}</div>
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   FAQ
   ============================================================ */
function FaqSection() {
  const [open, setOpen] = useState(0);
  return (
    <section className="faq" id="faq">
      <div className="container">
        <div className="section-head">
          <span className="eyebrow">The fine print</span>
          <h2>Common <span className="script">questions</span></h2>
        </div>
        <div className="faq-wrap">
          {FAQ.map((f, i) => (
            <div className="faq-item" key={i}>
              <button
                className={`faq-q${open === i ? " is-open" : ""}`}
                onClick={() => setOpen(open === i ? -1 : i)}
              >
                <span>{f.q}</span>
                <span className="faq-icon">+</span>
              </button>
              <div className="faq-a">
                <div className="faq-a-inner">{f.a}</div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   Booking CTA
   ============================================================ */
function BookingCta() {
  return (
    <section className="cta">
      <div className="container">
        <div className="cta-inner">
          <h2>
            Spring & summer dates<br />
            are filling <span className="script">fast.</span>
          </h2>
          <p>Lock in her date with a deposit starting at $249. Takes 90 seconds.</p>
          <a className="btn btn-primary btn-lg" href={BOOKING_URL} target="_blank" rel="noopener">
            Book on the calendar <ArrowRight />
          </a>
          <div className="cta-direct">
            <span>or talk to a real human →</span>
            <a href={`tel:${PHONE_TEL}`}>{PHONE}</a>
            <a href="https://instagram.com/lilstarsparties" target="_blank" rel="noopener">@lilstarsparties</a>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   Footer
   ============================================================ */
function Footer() {
  return (
    <footer className="footer">
      <div className="container">
        <div className="footer-grid">
          <div className="footer-col footer-brand">
            <a className="brand" href="#top">
              <div className="brand-mark">
                <Crown size={20} />
              </div>
              <div>
                <div className="brand-name">Little Stars</div>
                <div className="brand-sub" style={{ color: "var(--pink-400)" }}>party bus</div>
              </div>
            </a>
            <p>Birthdays become core memories on wheels. Private celebrations for kids, parked right in your driveway.</p>
            <div className="footer-socials">
              <a href="https://instagram.com/lilstarsparties" target="_blank" rel="noopener" aria-label="Instagram">
                <svg viewBox="0 0 24 24"><path d="M12 2.2c3.2 0 3.6 0 4.8.1 1.2 0 1.8.2 2.2.4.6.2 1 .5 1.4 1 .5.4.8.8 1 1.4.2.4.4 1 .4 2.2.1 1.2.1 1.6.1 4.8s0 3.6-.1 4.8c0 1.2-.2 1.8-.4 2.2-.2.6-.5 1-1 1.4-.4.5-.8.8-1.4 1-.4.2-1 .4-2.2.4-1.2.1-1.6.1-4.8.1s-3.6 0-4.8-.1c-1.2 0-1.8-.2-2.2-.4-.6-.2-1-.5-1.4-1-.5-.4-.8-.8-1-1.4-.2-.4-.4-1-.4-2.2C2.2 15.6 2.2 15.2 2.2 12s0-3.6.1-4.8c0-1.2.2-1.8.4-2.2.2-.6.5-1 1-1.4.4-.5.8-.8 1.4-1 .4-.2 1-.4 2.2-.4C8.4 2.2 8.8 2.2 12 2.2zm0 3.1c2.7 0 4.9 2.2 4.9 4.9s-2.2 4.9-4.9 4.9-4.9-2.2-4.9-4.9 2.2-4.9 4.9-4.9zm0 8.1c1.8 0 3.2-1.4 3.2-3.2s-1.4-3.2-3.2-3.2-3.2 1.4-3.2 3.2 1.4 3.2 3.2 3.2zm6.2-8.3c0 .6-.5 1.1-1.1 1.1s-1.1-.5-1.1-1.1.5-1.1 1.1-1.1 1.1.5 1.1 1.1z"/></svg>
              </a>
              <a href="https://tiktok.com/@littlestarparty" target="_blank" rel="noopener" aria-label="TikTok">
                <svg viewBox="0 0 24 24"><path d="M19.6 6.3c-1.4-.3-2.6-1-3.5-2-.9-1-1.4-2.3-1.4-3.7H11v14c0 1.5-1.2 2.7-2.7 2.7s-2.7-1.2-2.7-2.7 1.2-2.7 2.7-2.7c.3 0 .6.1.9.2v-3.7c-.3 0-.6-.1-.9-.1-3.5 0-6.3 2.8-6.3 6.3S5 21 8.5 21s6.3-2.8 6.3-6.3v-6c1.3 1 3 1.6 4.8 1.6V6.3z"/></svg>
              </a>
            </div>
          </div>
          <div className="footer-col">
            <h5>Packages</h5>
            {PACKAGES.map((p) => <a href="#packages" key={p.id}>The {p.name}</a>)}
          </div>
          <div className="footer-col">
            <h5>Visit</h5>
            <a href="#experience">How it works</a>
            <a href="#gallery">Gallery</a>
            <a href="#travel">Travel fees</a>
            <a href="#reviews">Reviews</a>
            <a href="#faq">FAQ</a>
          </div>
          <div className="footer-col">
            <h5>Get in touch</h5>
            <a href={`tel:${PHONE_TEL}`}>{PHONE}</a>
            <p>San Diego · Orange County<br />Temecula & surrounding areas</p>
            <a className="btn btn-primary btn-sm" href={BOOKING_URL} target="_blank" rel="noopener" style={{ marginTop: 12, display: "inline-flex" }}>
              Book now
            </a>
          </div>
        </div>
        <div className="footer-bottom">
          <div>© {new Date().getFullYear()} Little Stars Party Bus. All rights reserved.</div>
          <div>Made with 💖 for little stars in Southern California.</div>
        </div>
      </div>
    </footer>
  );
}

/* ============================================================
   App
   ============================================================ */
function App() {
  const [activePkg, setActivePkg] = useState(null);

  return (
    <>
      <Nav />
      <Hero />
      <TrustStrip />
      <HowItWorks />
      <Packages onSelect={setActivePkg} />
      <Reel />
      <Addons />
      <TravelFees />
      <Social />
      <Reviews />
      <FaqSection />
      <BookingCta />
      <Footer />
      {activePkg ? <PackageModal pkg={activePkg} onClose={() => setActivePkg(null)} /> : null}
    </>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
