/* shared.jsx — Reviews data + scroll-section + page chrome wrapper + Pro Luxury Nav */

const MORE_REVIEWS = [
  { name: 'Madavy', country: 'Bogotá', date: 'May 2026', stars: 5, source: 'Airbnb',
    text: 'This home was perfect for a group of girls. Close to all the great spots — the house was great, great rooms, beds, and bathrooms. Everyone felt right at home. Kitchen and outdoor grill were perfect.' },
  { name: 'Kaly', country: 'New York', date: 'Apr 2026', stars: 5, source: 'Airbnb',
    text: 'Slept 10 of us very comfortably. Great location between downtown and Miami Beach. We also saw an insane amount of dolphins swim right up to the backyard one of the nights. The host was responsive and flexible.' },
  { name: 'Robert', country: 'Toronto', date: 'Mar 2026', stars: 5, source: 'VRBO',
    text: 'An amazing huge space with so many spaces for people to sleep, lots of utensils and stuff for us to use in the kitchen, a great pool — just everything we needed with a really responsive host.' },
  { name: 'Kayla', country: 'Austin', date: 'Mar 2026', stars: 5, source: 'Airbnb',
    text: 'Very comfortable for 4 couples, private bedrooms with en-suite baths. Property was as described, didn’t leave us guessing at all. Host was accommodating, friendly, very responsive.' },
  { name: 'Emiliano', country: 'México DF', date: 'Feb 2026', stars: 5, source: 'Direct',
    text: 'Pasamos un fin de semana increíble en Española. La atención de Miguel fue impecable — pre-llenó la cocina con todo lo que pedimos y nos consiguió chef privado para el sábado.' },
  { name: 'Isabella', country: 'São Paulo', date: 'Feb 2026', stars: 5, source: 'Airbnb',
    text: 'A villa em Treasure Island é simplesmente espetacular. Vista para a baía, decoração elegante, e o concierge respondeu a todos os pedidos em minutos. Voltaremos com certeza.' },
  { name: 'Daniel', country: 'Madrid', date: 'Jan 2026', stars: 5, source: 'VRBO',
    text: 'El Aston Martin Residences es otra cosa. El servicio del lobby, el spa, el marina privado. Era como vivir en un hotel cinco estrellas pero con la libertad de un apartamento.' },
  { name: 'Sophie', country: 'Paris', date: 'Jan 2026', stars: 5, source: 'Airbnb',
    text: 'I booked Aria on the Bay for a 10-night work trip. The Bosch kitchen, the bay balcony at sunset, the spa downstairs — it was effortless from booking to check-out.' },
  { name: 'Marcus', country: 'London', date: 'Dec 2025', stars: 5, source: 'Direct',
    text: 'We chartered the Galeon 500 for an afternoon — captain Pedro was fantastic, the boat is immaculate, and the route around Biscayne Bay was unforgettable. Villa stay + yacht day = perfect Miami.' },
  { name: 'Carolina', country: 'Buenos Aires', date: 'Dec 2025', stars: 5, source: 'Airbnb',
    text: 'Casa Blanca: la vista al downtown de Miami al atardecer es de otro planeta. La piscina, las habitaciones, el espacio para trabajar. Recomendado al 100%.' },
  { name: 'Henrik', country: 'Stockholm', date: 'Nov 2025', stars: 5, source: 'VRBO',
    text: 'Communication was perfect — we had a late flight and Miguel still personally met us with the keys. The villa was spotless and the welcome bottle of rosé was a beautiful touch.' },
  { name: 'Priya', country: 'London', date: 'Nov 2025', stars: 5, source: 'Direct',
    text: 'I have stayed in luxury rentals across Europe and the Caribbean and Novus is among the best run. Booking direct gives you a real concierge, not a chatbot.' },
  { name: 'James', country: 'Chicago', date: 'Nov 2025', stars: 5, source: 'Airbnb',
    text: 'Booked Ocean Bella Estayer for a bachelor weekend. The Treasure Island location was unbeatable — steps from the bay and a quick ride to the best bars. The house photographed beautifully and looked even better in person.' },
  { name: 'Lucía', country: 'Monterrey', date: 'Oct 2025', stars: 5, source: 'Airbnb',
    text: 'Todo perfecto desde el primer mensaje. El check-in fue súper fácil, la casa impecable, y nos ayudaron a reservar el yate para el cumpleaños de mi esposo. Servicio de cinco estrellas.' },
  { name: 'Thomas', country: 'Berlin', date: 'Oct 2025', stars: 5, source: 'VRBO',
    text: 'Villa Sole exceeded every expectation. The bay views at sunrise were unreal and the private dock made our fishing trip so easy. Spotless, modern, and the team answered within minutes.' },
  { name: 'Ana Paula', country: 'Lisbon', date: 'Sep 2025', stars: 5, source: 'Airbnb',
    text: 'A experiência foi impecável do início ao fim. O concierge organizou chef privado e transfer do aeroporto. A villa estava perfeita — recomendo a qualquer pessoa que procura luxo real em Miami.' },
  { name: 'David', country: 'San Francisco', date: 'Sep 2025', stars: 5, source: 'Direct',
    text: 'Booking direct with Novus saved us money and gave us a far better experience than any OTA. Real human concierge, transparent pricing, and the deposit process felt completely secure.' },
  { name: 'Valentina', country: 'Santiago', date: 'Aug 2025', stars: 5, source: 'Airbnb',
    text: 'Bay Villa Island fue un sueño. La piscina climatizada, las camas comodísimas, y la ubicación en North Bay Village a pasos del agua. Miguel siempre disponible. Volveremos sin dudarlo.' },
  { name: 'Olivia', country: 'Sydney', date: 'Aug 2025', stars: 5, source: 'VRBO',
    text: 'We travelled 20 hours from Australia and Novus made arrival effortless — driver waiting, fridge stocked, welcome note. The home was even more stunning than the listing photos.' },
  { name: 'Mohammed', country: 'Dubai', date: 'Jul 2025', stars: 5, source: 'Direct',
    text: 'Impeccable standard of service. The in-villa spa and private chef turned an ordinary weekend into something memorable. This is how luxury hospitality should be done.' },
  { name: 'Camila', country: 'Medellín', date: 'Jul 2025', stars: 5, source: 'Airbnb',
    text: 'La mejor estadía que hemos tenido en Miami. La casa, la atención, el yate, todo coordinado por el mismo equipo. Se siente personal, no como una empresa fría. 100% recomendado.' },
  { name: 'Elena', country: 'Milan', date: 'Jun 2025', stars: 5, source: 'Airbnb',
    text: 'Soggiorno perfetto. La villa era splendida, pulitissima e il concierge ha risposto a ogni richiesta in pochi minuti. Abbiamo prenotato anche lo chef privato — esperienza indimenticabile.' },
  { name: 'William', country: 'Boston', date: 'Jun 2025', stars: 5, source: 'VRBO',
    text: 'Five families, one villa, zero stress. The space handled all of us comfortably and the concierge arranged daily transfers and a sunset yacht charter. Worth every penny.' },
  { name: 'Renata', country: 'Rio de Janeiro', date: 'May 2025', stars: 5, source: 'Airbnb',
    text: 'Que lugar maravilhoso! A vista, a piscina, o atendimento. Tudo organizado pelo WhatsApp em minutos. Foi nossa segunda vez com a Novus e já estamos planejando a terceira.' },
];

window.MORE_REVIEWS = MORE_REVIEWS;

/* ---------- Page chrome wrapper ---------- */
function PageChrome({ children, active }) {
  return (
    <>
      <SiteNav active={active} />
      <main style={{ background: 'var(--bg-page)' }}>{children}</main>
      <Footer />
    </>
  );
}

/* =====================================================================
   GlobalNav — Pro Luxury Header with proper responsive breakpoints

   Breakpoints:
   - Mobile  (<  900px): Logo + Hamburger menu
   - Tablet  (900-1180px): Logo + condensed nav + Book CTA + Account icon
   - Desktop (> 1180px): Full nav + all CTAs
   ===================================================================== */
function GlobalNav({ active }) {
  const [scrolled, setScrolled] = React.useState(false);
  const [menuOpen, setMenuOpen] = React.useState(false);
  const [user, setUser] = React.useState(null);

  React.useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 8);
    onScroll(); window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  React.useEffect(() => {
    if (typeof window.onAuthStateChanged === 'function') {
      let unsub;
      window.onAuthStateChanged(u => setUser(u)).then(fn => { unsub = fn; }).catch(() => {});
      return () => { if (unsub) unsub(); };
    }
  }, []);

  React.useEffect(() => {
    const close = () => setMenuOpen(false);
    window.addEventListener('hashchange', close);
    return () => window.removeEventListener('hashchange', close);
  }, []);

  React.useEffect(() => {
    document.body.style.overflow = menuOpen ? 'hidden' : '';
    return () => { document.body.style.overflow = ''; };
  }, [menuOpen]);

  // ESC closes menu
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') setMenuOpen(false); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);

  const links = [
    { id: 'home',         label: 'Home',           href: 'index.html' },
    { id: 'villas',       label: 'Villas',         href: 'villas.html' },
    { id: 'experiences',  label: 'Experiences',    href: 'experiences.html' },
    { id: 'luxury',       label: 'Luxury Rentals', href: 'luxury-rentals.html' },
    { id: 'bimini',       label: 'Luxury Island',  href: 'bimini.html' },
    { id: 'contact',      label: 'Contact',        href: 'contact.html' },
  ];

  const headerBg = (scrolled || menuOpen)
    ? 'rgba(251,248,243,0.92)'
    : 'rgba(251,248,243,0.72)';

  return (
    <>
      <style>{`
        /* ============ NAV RESPONSIVE STRATEGY ============ */
        .nav-shell {
          position: sticky; top: 0; z-index: 100;
          backdrop-filter: blur(20px) saturate(180%);
          -webkit-backdrop-filter: blur(20px) saturate(180%);
          transition: background 280ms var(--ease-novus),
                      border-color 280ms var(--ease-novus),
                      box-shadow 280ms var(--ease-novus);
        }
        .nav-row {
          display: flex; align-items: center; justify-content: space-between;
          padding: 12px 0; gap: 16px;
          min-height: 64px;
        }
        @media (min-width: 900px) {
          .nav-row { min-height: 72px; }
        }
        /* Logo */
        .nav-logo {
          display: flex; align-items: center; gap: 10px;
          flex-shrink: 0;
          text-decoration: none;
          transition: opacity 200ms var(--ease-novus);
        }
        .nav-logo:hover { opacity: 0.78; }
        .nav-logo img {
          height: 36px; width: 36px; border-radius: 6px;
          object-fit: cover;
          box-shadow: 0 2px 6px rgba(10,31,51,0.08);
        }
        .nav-logo .brand-block {
          display: flex; flex-direction: column; line-height: 1.05;
        }
        .nav-logo .brand-name {
          font-weight: 700; letter-spacing: 0.2em;
          font-size: 12px; color: var(--navy-900);
        }
        .nav-logo .brand-sub {
          font-weight: 500; letter-spacing: 0.14em;
          font-size: 8px; color: var(--ink-600); margin-top: 2px;
        }
        /* Center nav links */
        .nav-links {
          display: none;
          gap: 32px;
          align-items: center;
          flex: 1; justify-content: center;
        }
        @media (min-width: 900px) {
          .nav-links { display: flex; gap: 26px; }
        }
        @media (min-width: 1180px) {
          .nav-links { gap: 36px; }
        }
        .nav-link {
          font-size: 13px;
          color: var(--ink-700);
          font-weight: 400;
          padding: 8px 0;
          position: relative;
          text-decoration: none;
          white-space: nowrap;
          letter-spacing: 0.02em;
          transition: color 240ms var(--ease-novus);
        }
        .nav-link::after {
          content: '';
          position: absolute;
          bottom: 4px; left: 0;
          width: 100%; height: 1.5px;
          background: var(--sun-coral);
          transform-origin: left center;
          transform: scaleX(0);
          transition: transform 360ms cubic-bezier(0.2, 0.7, 0.2, 1);
        }
        .nav-link:hover { color: var(--navy-900); }
        .nav-link:hover::after { transform: scaleX(1); }
        .nav-link.is-active {
          color: var(--navy-900);
          font-weight: 500;
        }
        .nav-link.is-active::after { transform: scaleX(1); }
        /* CTA group */
        .nav-cta {
          display: none;
          align-items: center; gap: 8px;
          flex-shrink: 0;
        }
        @media (min-width: 900px) {
          .nav-cta { display: flex; }
        }
        /* Check-in pill */
        .nav-checkin-btn {
          display: none;
          align-items: center; justify-content: center; gap: 7px;
          padding: 9px 16px;
          border-radius: 999px;
          background: linear-gradient(135deg, var(--sun-coral) 0%, var(--sun-amber) 100%);
          color: #fff !important;
          font-size: 12px; font-weight: 500;
          letter-spacing: 0.02em;
          box-shadow: 0 3px 12px rgba(248,141,107,0.30);
          border: 0; cursor: pointer;
          text-decoration: none;
          white-space: nowrap;
          transition: transform 240ms var(--ease-novus), box-shadow 240ms var(--ease-novus);
          position: relative; overflow: hidden;
        }
        @media (min-width: 1180px) {
          .nav-checkin-btn { display: inline-flex; }
        }
        .nav-checkin-btn:hover {
          transform: translateY(-1px);
          box-shadow: 0 6px 18px rgba(248,141,107,0.42);
        }
        .nav-checkin-btn:active { transform: translateY(0); }
        /* Account / Login */
        .nav-account-btn {
          display: inline-flex; align-items: center; justify-content: center;
          gap: 7px;
          padding: 9px 14px;
          border-radius: 999px;
          background: transparent;
          color: var(--navy-900);
          font-size: 12px; font-weight: 500;
          border: 1px solid var(--sand-300);
          cursor: pointer;
          text-decoration: none;
          white-space: nowrap;
          transition: all 240ms var(--ease-novus);
        }
        .nav-account-btn:hover {
          background: var(--navy-900);
          color: #fff;
          border-color: var(--navy-900);
        }
        /* Book button (always visible on tablet+) */
        .nav-book-btn {
          display: inline-flex; align-items: center; justify-content: center;
          padding: 10px 18px;
          border-radius: 999px;
          background: var(--navy-900);
          color: #fff !important;
          font-size: 12px; font-weight: 500;
          letter-spacing: 0.02em;
          border: 0; cursor: pointer;
          text-decoration: none;
          white-space: nowrap;
          transition: all 240ms var(--ease-novus);
          box-shadow: 0 2px 6px rgba(10,31,51,0.10);
        }
        .nav-book-btn:hover {
          background: var(--navy-700);
          transform: translateY(-1px);
          box-shadow: 0 6px 16px rgba(10,31,51,0.16);
        }
        /* Mobile menu trigger */
        .nav-burger {
          display: inline-flex; align-items: center; justify-content: center;
          width: 44px; height: 44px;
          padding: 0;
          background: transparent;
          border: 0;
          cursor: pointer;
          color: var(--navy-900);
          border-radius: 999px;
          transition: background 200ms var(--ease-novus);
        }
        @media (min-width: 900px) {
          .nav-burger { display: none; }
        }
        .nav-burger:hover {
          background: var(--sand-100);
        }
        .nav-burger svg {
          transition: transform 280ms var(--ease-novus);
        }
        .nav-burger.is-open svg { transform: rotate(90deg); }
        /* Mobile menu overlay */
        .nav-mobile-overlay {
          position: fixed;
          inset: 0;
          z-index: 99;
          background: var(--sand-50);
          display: flex; flex-direction: column;
          padding: 88px 24px max(40px, env(safe-area-inset-bottom)) 24px;
          overflow-y: auto;
          animation: slideDown 320ms var(--ease-novus);
        }
        @keyframes slideDown {
          from { opacity: 0; transform: translateY(-8px); }
          to   { opacity: 1; transform: translateY(0); }
        }
        @media (min-width: 900px) {
          .nav-mobile-overlay { display: none; }
        }
        .mobile-link {
          display: flex; align-items: center; justify-content: space-between;
          padding: 18px 4px;
          font-size: 22px;
          font-family: var(--font-display);
          color: var(--navy-900);
          font-weight: 400;
          letter-spacing: -0.01em;
          border-bottom: 1px solid var(--line);
          text-decoration: none;
          transition: padding 200ms var(--ease-novus), color 200ms var(--ease-novus);
        }
        .mobile-link:hover, .mobile-link:active {
          color: var(--sun-coral);
          padding-left: 8px;
        }
        .mobile-link.is-active {
          color: var(--sun-coral);
        }
        .mobile-link svg {
          opacity: 0;
          transform: translateX(-4px);
          transition: opacity 200ms var(--ease-novus), transform 200ms var(--ease-novus);
        }
        .mobile-link:hover svg,
        .mobile-link.is-active svg {
          opacity: 0.5;
          transform: translateX(0);
        }
        .mobile-cta-group {
          margin-top: 32px;
          display: flex; flex-direction: column; gap: 10px;
        }
        .mobile-cta-group .btn {
          width: 100%;
          justify-content: center;
          padding: 16px 22px;
          font-size: 14px;
          min-height: 52px;
        }
        .mobile-secondary-links {
          margin-top: 28px; padding-top: 24px;
          border-top: 1px solid var(--line);
          display: flex; flex-direction: column; gap: 4px;
        }
        .mobile-secondary-links a {
          display: flex; align-items: center; gap: 10px;
          padding: 12px 4px;
          font-size: 13px; color: var(--ink-600);
          text-decoration: none;
          letter-spacing: 0.01em;
        }
        .mobile-secondary-links a:hover { color: var(--navy-700); }
      `}</style>

      <header className="nav-shell" style={{
        background: headerBg,
        borderBottom: scrolled ? '1px solid var(--line)' : '1px solid transparent',
        boxShadow: scrolled ? '0 1px 0 rgba(0,0,0,0.02), 0 2px 12px rgba(15,42,66,0.04)' : 'none',
      }}>
        <div className="container">
          <div className="nav-row">
            {/* Logo + brand */}
            <a href="index.html" className="nav-logo" aria-label="Novus Residentials home">
              <img src="../../assets/novus-logo-mark.jpg" alt="Novus" />
              <div className="brand-block">
                <span className="brand-name">NOVUS</span>
                <span className="brand-sub">RESIDENTIALS</span>
              </div>
            </a>

            {/* Center Nav links — visible at 900px+ */}
            <nav className="nav-links" aria-label="Main navigation">
              {links.map(l => (
                <a key={l.id} href={l.href}
                  className={`nav-link ${active === l.id ? 'is-active' : ''}`}
                  aria-current={active === l.id ? 'page' : undefined}>
                  {l.label}
                </a>
              ))}
            </nav>

            {/* CTA group — visible at 900px+ */}
            <div className="nav-cta">
              <a href="check-in-flow.html" className="nav-checkin-btn" aria-label="Start check-in">
                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round">
                  <path d="M9 12l2 2 4-4"/>
                  <circle cx="12" cy="12" r="9"/>
                </svg>
                <span>Check-In</span>
              </a>
              {user ? (
                <a href="../guest-portal/index.html" className="nav-account-btn" aria-label="My Stay portal">
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
                    <circle cx="12" cy="8" r="3.5"/>
                    <path d="M5 21c0-3.866 3.134-7 7-7s7 3.134 7 7"/>
                  </svg>
                  <span>My Stay</span>
                </a>
              ) : (
                <a href="login.html" className="nav-account-btn" aria-label="Log in or sign up">
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
                    <circle cx="12" cy="8" r="3.5"/>
                    <path d="M5 21c0-3.866 3.134-7 7-7s7 3.134 7 7"/>
                  </svg>
                  <span>Log in</span>
                </a>
              )}
              <a href="booking.html" className="nav-book-btn">
                Book a stay
              </a>
            </div>

            {/* Mobile burger */}
            <button
              className={`nav-burger ${menuOpen ? 'is-open' : ''}`}
              aria-label={menuOpen ? 'Close menu' : 'Open menu'}
              aria-expanded={menuOpen}
              onClick={() => setMenuOpen(!menuOpen)}
            >
              {menuOpen ? (
                <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
                  <line x1="18" y1="6" x2="6" y2="18"></line>
                  <line x1="6" y1="6" x2="18" y2="18"></line>
                </svg>
              ) : (
                <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
                  <line x1="4" y1="7" x2="20" y2="7"></line>
                  <line x1="4" y1="12" x2="20" y2="12"></line>
                  <line x1="4" y1="17" x2="20" y2="17"></line>
                </svg>
              )}
            </button>
          </div>
        </div>
      </header>

      {/* Mobile menu overlay */}
      {menuOpen && (
        <div className="nav-mobile-overlay" role="dialog" aria-label="Mobile navigation menu">
          {links.map(l => (
            <a key={l.id} href={l.href} onClick={() => setMenuOpen(false)}
              className={`mobile-link ${active === l.id ? 'is-active' : ''}`}>
              <span>{l.label}</span>
              <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
                <line x1="5" y1="12" x2="19" y2="12"></line>
                <polyline points="12 5 19 12 12 19"></polyline>
              </svg>
            </a>
          ))}

          <div className="mobile-cta-group">
            <a href="booking.html" className="btn btn-primary">
              Book a stay
            </a>
            <a href="check-in-flow.html" className="btn" style={{
              background: 'linear-gradient(135deg, var(--sun-coral), var(--sun-amber))',
              color: '#fff', border: 0,
              boxShadow: '0 4px 14px rgba(248,141,107,0.3)',
            }}>
              Check-In →
            </a>
            {user ? (
              <a href="../guest-portal/index.html" className="btn btn-secondary">
                My Stay
              </a>
            ) : (
              <a href="login.html" className="btn btn-secondary">
                Log in / Sign up
              </a>
            )}
          </div>

          <div className="mobile-secondary-links">
            <a href="../admin/host-portal.html">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
                <rect x="3" y="3" width="7" height="9" rx="1"/>
                <rect x="14" y="3" width="7" height="5" rx="1"/>
                <rect x="14" y="12" width="7" height="9" rx="1"/>
                <rect x="3" y="16" width="7" height="5" rx="1"/>
              </svg>
              Host Admin
            </a>
            <a href="cohost.html">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
                <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
              </svg>
              Become a co-host
            </a>
            <a href="vendor.html">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
                <circle cx="12" cy="12" r="9"/>
                <path d="M8 12l3 3 5-5"/>
              </svg>
              Service provider
            </a>
            <a href="legal.html">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
                <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
                <polyline points="14 2 14 8 20 8"/>
              </svg>
              Legal &amp; House Rules
            </a>
          </div>
        </div>
      )}
    </>
  );
}

/* Alias for backwards compatibility */
function SiteNav({ active }) {
  return <GlobalNav active={active} />;
}

/* ---------- Sticky scroll-image storytelling section ---------- */
function ScrollStory({ panels, eyebrow }) {
  return (
    <section style={{ padding: '64px 0 40px' }}>
      <div className="container">
        {eyebrow && (
          <div style={{ textAlign: 'center', marginBottom: 48, padding: '0 8px' }}>
            <span className="sun-bullet" />
            <div className="overline" style={{ marginTop: 12 }}>{eyebrow.overline}</div>
            <h2 style={{
              fontFamily: 'var(--font-display)', fontWeight: 400,
              fontSize: 'clamp(28px, 4vw, 56px)', color: 'var(--navy-900)',
              margin: '14px auto 0', letterSpacing: '-0.015em', lineHeight: 1.08,
              maxWidth: 760, textWrap: 'balance',
            }}>{eyebrow.title}</h2>
            {eyebrow.intro && (
              <p style={{
                color: 'var(--ink-500)', fontSize: 'clamp(14px, 1.6vw, 17px)',
                lineHeight: 1.6, maxWidth: 620, margin: '16px auto 0', textWrap: 'pretty',
              }}>
                {eyebrow.intro}
              </p>
            )}
          </div>
        )}

        {panels.map((p, i) => (
          <ScrollPanel key={i} idx={i} {...p} />
        ))}
      </div>
    </section>
  );
}

function ScrollPanel({ idx, photo, badge, title, body, facts, cta }) {
  const flip = idx % 2 === 1;
  return (
    <div className="scroll-panel" style={{
      display: 'grid',
      gridTemplateColumns: '1fr',
      gap: 24,
      alignItems: 'stretch',
      marginBottom: 56,
    }}>
      <style>{`
        @media (min-width: 768px) {
          .scroll-panel { grid-template-columns: 1fr 1fr !important; gap: 40px !important; margin-bottom: 80px !important; }
        }
        @media (min-width: 1024px) {
          .scroll-panel { gap: 64px !important; margin-bottom: 96px !important; }
        }
        .scroll-panel-img { height: 280px; }
        @media (min-width: 640px) { .scroll-panel-img { height: 360px; } }
        @media (min-width: 768px) { .scroll-panel-img { position: sticky; top: 96px; align-self: flex-start; height: 70vh; min-height: 480px; } }
      `}</style>

      <div className="scroll-panel-img" style={{
        order: flip ? 2 : 1,
        borderRadius: 18, overflow: 'hidden',
        background: 'var(--sand-100)',
        position: 'relative',
      }}>
        <img src={photo} alt={title}
          style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
        {badge && (
          <div style={{
            position: 'absolute', left: 14, bottom: 14,
            padding: '6px 12px', background: 'rgba(10,31,51,0.62)',
            color: '#FBF8F3', borderRadius: 999, fontSize: 10, fontWeight: 600,
            letterSpacing: '0.14em', textTransform: 'uppercase',
            backdropFilter: 'blur(8px)', WebkitBackdropFilter: 'blur(8px)',
          }}>{badge}</div>
        )}
      </div>

      <div style={{ order: flip ? 1 : 2, padding: '8px 0 24px' }}>
        <h3 style={{
          fontFamily: 'var(--font-display)', fontWeight: 400,
          fontSize: 'clamp(24px, 3vw, 40px)', color: 'var(--navy-900)',
          margin: '0 0 14px', letterSpacing: '-0.01em', lineHeight: 1.15,
        }}>{title}</h3>
        <p style={{
          color: 'var(--ink-700)', fontSize: 'clamp(15px, 1.5vw, 17px)', lineHeight: 1.65,
          margin: '0 0 22px',
        }}>{body}</p>

        {facts && (
          <ul style={{
            listStyle: 'none', padding: 0, margin: '0 0 22px 0',
            display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 10,
          }}>
            {facts.map(f => (
              <li key={f} style={{
                display: 'flex', alignItems: 'center', gap: 8,
                fontSize: 13, color: 'var(--ink-700)',
              }}>
                <span style={{ width: 6, height: 6, borderRadius: 999, background: 'var(--sun-coral)', flexShrink: 0 }} />
                {f}
              </li>
            ))}
          </ul>
        )}

        {cta && (
          <a href={cta.href} className="btn btn-primary">{cta.label} →</a>
        )}
      </div>
    </div>
  );
}

/* ---------- Verified-source badge (Airbnb / VRBO / Direct) ---------- */
const SOURCE_STYLES = {
  Airbnb:  { color: '#FF5A5F', label: 'Verified on Airbnb' },
  VRBO:    { color: '#1668E3', label: 'Verified on VRBO' },
  Google:  { color: '#34A853', label: 'Verified on Google' },
  Direct:  { color: 'var(--navy-700)', label: 'Verified guest' },
};

function VerifiedSourceBadge({ source = 'Direct', onDark = false }) {
  const s = SOURCE_STYLES[source] || SOURCE_STYLES.Direct;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 5,
      fontSize: 10.5, fontWeight: 600, letterSpacing: '0.02em',
      color: onDark ? 'rgba(255,255,255,0.78)' : 'var(--ink-500)',
      padding: '3px 9px 3px 7px', borderRadius: 999,
      background: onDark ? 'rgba(255,255,255,0.07)' : 'var(--sand-100)',
      border: `1px solid ${onDark ? 'rgba(255,255,255,0.14)' : 'var(--line)'}`,
      whiteSpace: 'nowrap',
    }}>
      {/* shield-check glyph */}
      <svg width="11" height="11" viewBox="0 0 24 24" fill="none" style={{ flexShrink: 0 }}>
        <path d="M12 2l7 3v6c0 4.5-3 8.5-7 10-4-1.5-7-5.5-7-10V5l7-3z" fill={s.color} opacity="0.18" />
        <path d="M12 2l7 3v6c0 4.5-3 8.5-7 10-4-1.5-7-5.5-7-10V5l7-3z" stroke={s.color} strokeWidth="1.6" strokeLinejoin="round" />
        <path d="M8.5 12l2.2 2.2L15.5 9.5" stroke={s.color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
      </svg>
      {s.label}
    </span>
  );
}
window.VerifiedSourceBadge = VerifiedSourceBadge;

/* ---------- Tiny review card used inline on pages ---------- */
function ReviewCard({ r }) {
  return (
    <div style={{
      background: '#fff', border: '1px solid var(--line)',
      borderRadius: 14, padding: 22, height: '100%',
      display: 'flex', flexDirection: 'column', gap: 10,
      transition: 'border-color 240ms var(--ease-novus), transform 240ms var(--ease-novus)',
    }}
      onMouseEnter={e => { e.currentTarget.style.borderColor = 'var(--sand-300)'; e.currentTarget.style.transform = 'translateY(-2px)'; }}
      onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--line)'; e.currentTarget.style.transform = 'translateY(0)'; }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 3, color: 'var(--sun-amber)' }}>
          {Array.from({ length: r.stars }).map((_,i) => <span key={i} style={{ fontSize: 14 }}>★</span>)}
        </div>
        {r.source && <VerifiedSourceBadge source={r.source} />}
      </div>
      <p style={{
        margin: 0, color: 'var(--ink-700)', fontSize: 15, lineHeight: 1.55,
        fontFamily: 'var(--font-display)', fontStyle: 'italic',
      }}>"{r.text}"</p>
      <div style={{ marginTop: 'auto', paddingTop: 10, borderTop: '1px solid var(--line)', display: 'flex', alignItems: 'center', gap: 10 }}>
        <div style={{
          width: 36, height: 36, borderRadius: 999, background: 'var(--sunset-gradient)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          color: '#fff', fontFamily: 'var(--font-display)', fontSize: 14, flexShrink: 0,
        }}>{(r.name && r.name[0]) || '★'}</div>
        <div style={{ minWidth: 0, flex: 1 }}>
          <div style={{ fontWeight: 500, fontSize: 13, color: 'var(--navy-900)' }}>{r.name || 'Verified guest'}</div>
          <div style={{ fontSize: 11, color: 'var(--ink-500)' }}>{[r.country, r.date].filter(Boolean).join(' · ') || (r.source ? `Verified · ${r.source}` : 'Verified guest')}</div>
        </div>
      </div>
    </div>
  );
}

function ReviewsGrid({ reviews, cols = 3 }) {
  return (
    <div style={{
      display: 'grid',
      gridTemplateColumns: `repeat(auto-fit, minmax(min(100%, 280px), 1fr))`,
      gap: 16,
    }}>
      {reviews.map((r, i) => <ReviewCard r={r} key={i} />)}
    </div>
  );
}

/* ---------- Scroll reveal helper (Intersection Observer) ---------- */
function setupScrollReveal() {
  if (typeof window === 'undefined' || !('IntersectionObserver' in window)) return;
  const els = document.querySelectorAll('.reveal');
  if (!els.length) return;
  const io = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        entry.target.classList.add('is-visible');
        io.unobserve(entry.target);
      }
    });
  }, { threshold: 0.15, rootMargin: '0px 0px -60px 0px' });
  els.forEach(el => io.observe(el));
}

if (typeof window !== 'undefined') {
  window.addEventListener('load', () => {
    setTimeout(setupScrollReveal, 200);
  });
  window.addEventListener('hashchange', () => setTimeout(setupScrollReveal, 100));
}

window.SiteNav = SiteNav;
window.GlobalNav = GlobalNav;
window.PageChrome = PageChrome;
window.ScrollStory = ScrollStory;
window.ScrollPanel = ScrollPanel;
window.ReviewsGrid = ReviewsGrid;
window.ReviewCard = ReviewCard;
window.setupScrollReveal = setupScrollReveal;
