// LÜP Locations — interactive Leaflet map (CARTO Positron tiles, terracotta pins).
//
// Two data sources, switched by USE_LIVE_VENUES below:
//   false → EXAMPLE_VENUES, the illustrative end-state Sydney network (~90
//           pins). Keeps the marketing map looking dense while the real
//           network is still small / contains test rows.
//   true  → live `active` venues fetched from Supabase — the same list the
//           app's Find-a-venue page shows. Flip this to go live once the
//           real network is presentable (and test venues are cleaned up).
//
// The live fetch hits Supabase's public REST endpoint with the publishable
// (anon) key — the same public credentials the app ships to browsers. The
// "Active venues readable by all" RLS policy allows this unauthenticated.
const USE_LIVE_VENUES = false;
const LUP_SUPABASE_URL = 'https://tjkuyslxbzeselfanhgb.supabase.co';
const LUP_SUPABASE_PUBLISHABLE_KEY = 'sb_publishable_k8pVTr7a3792vjqAP2bc4w_z7NmcMjA';
const LUP_VENUES_APP_URL = 'https://app.lupit.com.au/venues';

// Pre-pilot the live network is too sparse to put on a map, so we hide it and
// show a "borrow here, return anywhere" explainer + a venue-suggestion form
// instead. Flip SHOW_MAP to true at pilot kickoff to reveal the Leaflet map +
// "Find LÜP venues" CTA (all the map code below stays intact either way).
const SHOW_MAP = false;

window.LocationsSection = function LocationsSection() {
  const { audience } = React.useContext(window.AudienceContext);
  const mapRef = React.useRef(null);
  const mapInstanceRef = React.useRef(null);
  const markersRef = React.useRef(null);

  // Audience-aware header copy. Venues see the density/flywheel framing
  // (why coverage matters to them); customers see the everyday borrow/return promise.
  const header = audience === 'venue'
    ? {
        leadText: 'A dense and growing network that ',
        accentText: 'makes reuse convenient and effortless.',
        subText: 'Customers borrow and return at any venue across the network, so every venue that joins means more drop-offs, faster cycles, and more repeat visits — for every venue in the LÜP network.',
      }
    : {
        leadText: 'Borrow and return your bowl. ',
        accentText: 'Anywhere.',
        subText: 'Borrow a bowl at any LÜP venue and return it at any other — and the more venues that join, the more convenient reuse becomes.',
      };

  // Example end-state network — densely populated venues across Sydney CBD and the
  // Eastern Suburbs. Multiple venues per suburb to convey real network coverage.
  const EXAMPLE_VENUES = [
    // ── CBD ──
    { name: 'Stable Coffee', suburb: 'The Rocks', type: 'Café', lat: -33.8587, lng: 151.2087 },
    { name: 'Argyle Lane Bowls', suburb: 'The Rocks', type: 'Restaurant', lat: -33.8595, lng: 151.2089 },
    { name: 'Quay Street Eats', suburb: 'Circular Quay', type: 'Restaurant', lat: -33.8615, lng: 151.2113 },
    { name: 'Wharf Provisions', suburb: 'Circular Quay', type: 'Café', lat: -33.8617, lng: 151.2106 },
    { name: 'Crown Coffee Co.', suburb: 'Barangaroo', type: 'Café', lat: -33.8619, lng: 151.2008 },
    { name: 'Hickson Rd Café', suburb: 'Barangaroo', type: 'Café', lat: -33.8590, lng: 151.2007 },
    { name: 'Reserve Bowls', suburb: 'Barangaroo', type: 'Restaurant', lat: -33.8623, lng: 151.2026 },
    { name: 'Wynyard Provisions', suburb: 'Wynyard', type: 'Café', lat: -33.8654, lng: 151.2065 },
    { name: 'Carrington Coffee', suburb: 'Wynyard', type: 'Café', lat: -33.8649, lng: 151.2076 },
    { name: 'Martin Place Bowls', suburb: 'Sydney CBD', type: 'Restaurant', lat: -33.8676, lng: 151.2098 },
    { name: 'MLC Café', suburb: 'Sydney CBD', type: 'Café', lat: -33.8682, lng: 151.2095 },
    { name: 'Pitt St Roasters', suburb: 'Sydney CBD', type: 'Café', lat: -33.8730, lng: 151.2065 },
    { name: 'George St Greens', suburb: 'Sydney CBD', type: 'Restaurant', lat: -33.8722, lng: 151.2059 },
    { name: 'Park Lane Café', suburb: 'Hyde Park', type: 'Café', lat: -33.8736, lng: 151.2120 },
    { name: 'St James Bowls', suburb: 'Hyde Park', type: 'Restaurant', lat: -33.8703, lng: 151.2113 },
    { name: 'Liverpool St Kitchen', suburb: 'Sydney CBD', type: 'Restaurant', lat: -33.8770, lng: 151.2080 },
    { name: 'World Square Eats', suburb: 'Sydney CBD', type: 'Restaurant', lat: -33.8780, lng: 151.2070 },
    { name: 'Goulburn Provisions', suburb: 'Haymarket', type: 'Café', lat: -33.8800, lng: 151.2050 },
    { name: 'Chinatown Bowls', suburb: 'Haymarket', type: 'Restaurant', lat: -33.8795, lng: 151.2042 },
    { name: 'Darling Harbour Greens', suburb: 'Darling Harbour', type: 'Café', lat: -33.8742, lng: 151.1999 },
    { name: 'Tumbalong Café', suburb: 'Darling Harbour', type: 'Café', lat: -33.8780, lng: 151.1997 },
    { name: 'Harris St Coffee', suburb: 'Pyrmont', type: 'Café', lat: -33.8703, lng: 151.1956 },
    { name: 'Pyrmont Point Café', suburb: 'Pyrmont', type: 'Café', lat: -33.8675, lng: 151.1932 },
    { name: 'Star Bakery', suburb: 'Pyrmont', type: 'Bakery', lat: -33.8696, lng: 151.1944 },
    { name: 'Broadway Bowls', suburb: 'Ultimo', type: 'Restaurant', lat: -33.8800, lng: 151.1955 },
    { name: 'Quay St Greens', suburb: 'Ultimo', type: 'Café', lat: -33.8825, lng: 151.1990 },

    // ── Surry Hills / Darlinghurst / Potts Point / Kings Cross ──
    { name: 'Crown St Kitchen', suburb: 'Surry Hills', type: 'Restaurant', lat: -33.8853, lng: 151.2126 },
    { name: 'Bourke St Bakery', suburb: 'Surry Hills', type: 'Bakery', lat: -33.8880, lng: 151.2127 },
    { name: 'Riley St Coffee', suburb: 'Surry Hills', type: 'Café', lat: -33.8836, lng: 151.2113 },
    { name: 'Cleveland Greens', suburb: 'Surry Hills', type: 'Café', lat: -33.8895, lng: 151.2102 },
    { name: 'Devonshire Eats', suburb: 'Surry Hills', type: 'Restaurant', lat: -33.8865, lng: 151.2089 },
    { name: 'Foveaux St Roasters', suburb: 'Surry Hills', type: 'Café', lat: -33.8842, lng: 151.2075 },
    { name: 'Oxford Street Bowl Bar', suburb: 'Darlinghurst', type: 'Restaurant', lat: -33.8779, lng: 151.2191 },
    { name: 'Crown Lane Café', suburb: 'Darlinghurst', type: 'Café', lat: -33.8804, lng: 151.2186 },
    { name: 'Victoria St Provisions', suburb: 'Darlinghurst', type: 'Café', lat: -33.8769, lng: 151.2168 },
    { name: 'Macleay Greens', suburb: 'Potts Point', type: 'Café', lat: -33.8682, lng: 151.2237 },
    { name: 'Challis Ave Coffee', suburb: 'Potts Point', type: 'Café', lat: -33.8693, lng: 151.2247 },
    { name: 'Kings Cross Café', suburb: 'Kings Cross', type: 'Café', lat: -33.8744, lng: 151.2226 },
    { name: 'Bayswater Bowls', suburb: 'Kings Cross', type: 'Restaurant', lat: -33.8740, lng: 151.2243 },
    { name: 'Elizabeth Bay Greens', suburb: 'Elizabeth Bay', type: 'Café', lat: -33.8707, lng: 151.2278 },
    { name: 'Rushcutters Café', suburb: 'Rushcutters Bay', type: 'Café', lat: -33.8770, lng: 151.2294 },

    // ── Paddington / Woollahra / Centennial Park / Moore Park ──
    { name: 'Five Ways Café', suburb: 'Paddington', type: 'Café', lat: -33.8842, lng: 151.2298 },
    { name: 'Paddington Bowl Co.', suburb: 'Paddington', type: 'Restaurant', lat: -33.8864, lng: 151.2278 },
    { name: 'Glenmore Rd Roasters', suburb: 'Paddington', type: 'Café', lat: -33.8827, lng: 151.2317 },
    { name: 'Oxford Square Eats', suburb: 'Paddington', type: 'Restaurant', lat: -33.8848, lng: 151.2333 },
    { name: 'William St Bakery', suburb: 'Paddington', type: 'Bakery', lat: -33.8852, lng: 151.2349 },
    { name: 'Queen St Provisions', suburb: 'Woollahra', type: 'Bakery', lat: -33.8866, lng: 151.2387 },
    { name: 'Moncur Greens', suburb: 'Woollahra', type: 'Café', lat: -33.8902, lng: 151.2412 },
    { name: 'Centennial Park Café', suburb: 'Centennial Park', type: 'Café', lat: -33.8946, lng: 151.2336 },
    { name: 'Moore Park Bowls', suburb: 'Moore Park', type: 'Restaurant', lat: -33.8910, lng: 151.2235 },

    // ── Edgecliff / Double Bay / Bellevue Hill ──
    { name: 'Edgecliff Eats', suburb: 'Edgecliff', type: 'Restaurant', lat: -33.8786, lng: 151.2407 },
    { name: 'Edgecliff Station Coffee', suburb: 'Edgecliff', type: 'Café', lat: -33.8802, lng: 151.2410 },
    { name: 'Bay Street Roasters', suburb: 'Double Bay', type: 'Café', lat: -33.8780, lng: 151.2424 },
    { name: 'Cross St Café', suburb: 'Double Bay', type: 'Café', lat: -33.8772, lng: 151.2444 },
    { name: 'Knox St Bowls', suburb: 'Double Bay', type: 'Restaurant', lat: -33.8777, lng: 151.2417 },
    { name: 'Bellevue Hill Provisions', suburb: 'Bellevue Hill', type: 'Café', lat: -33.8835, lng: 151.2587 },
    { name: 'Birriga Bakery', suburb: 'Bellevue Hill', type: 'Bakery', lat: -33.8853, lng: 151.2615 },

    // ── Rose Bay / Vaucluse ──
    { name: 'Rose Bay Greens', suburb: 'Rose Bay', type: 'Café', lat: -33.8716, lng: 151.2683 },
    { name: 'New South Head Café', suburb: 'Rose Bay', type: 'Café', lat: -33.8734, lng: 151.2657 },
    { name: 'Lyne Park Eats', suburb: 'Rose Bay', type: 'Restaurant', lat: -33.8714, lng: 151.2706 },
    { name: 'Vaucluse Village Café', suburb: 'Vaucluse', type: 'Café', lat: -33.8589, lng: 151.2746 },
    { name: 'Hopetoun Bowls', suburb: 'Vaucluse', type: 'Restaurant', lat: -33.8600, lng: 151.2772 },

    // ── Bondi Junction / Bondi / Tamarama / Bronte ──
    { name: 'Junction Bowl Co.', suburb: 'Bondi Junction', type: 'Restaurant', lat: -33.8915, lng: 151.2484 },
    { name: 'Westfield Provisions', suburb: 'Bondi Junction', type: 'Café', lat: -33.8919, lng: 151.2517 },
    { name: 'Spring St Coffee', suburb: 'Bondi Junction', type: 'Café', lat: -33.8932, lng: 151.2497 },
    { name: 'Oxford St Bowls', suburb: 'Bondi Junction', type: 'Restaurant', lat: -33.8909, lng: 151.2532 },
    { name: 'Beachside Bowls', suburb: 'Bondi', type: 'Restaurant', lat: -33.8915, lng: 151.2767 },
    { name: 'Campbell Pde Café', suburb: 'Bondi', type: 'Café', lat: -33.8928, lng: 151.2769 },
    { name: 'Hall St Roasters', suburb: 'Bondi', type: 'Café', lat: -33.8909, lng: 151.2754 },
    { name: 'North Bondi Greens', suburb: 'North Bondi', type: 'Café', lat: -33.8889, lng: 151.2784 },
    { name: 'Notts Ave Bakery', suburb: 'Bondi', type: 'Bakery', lat: -33.8927, lng: 151.2755 },
    { name: 'Curlewis St Eats', suburb: 'Bondi', type: 'Restaurant', lat: -33.8922, lng: 151.2741 },
    { name: 'Tama Greens', suburb: 'Tamarama', type: 'Café', lat: -33.8997, lng: 151.2700 },
    { name: 'Tama Beach Café', suburb: 'Tamarama', type: 'Café', lat: -33.9006, lng: 151.2710 },
    { name: 'Bronte Beach House', suburb: 'Bronte', type: 'Café', lat: -33.9036, lng: 151.2654 },
    { name: 'Macpherson St Café', suburb: 'Bronte', type: 'Café', lat: -33.9054, lng: 151.2615 },

    // ── Clovelly / Coogee / Randwick / Kensington ──
    { name: 'Clovelly Kitchen', suburb: 'Clovelly', type: 'Restaurant', lat: -33.9148, lng: 151.2657 },
    { name: 'Clovelly Beach Café', suburb: 'Clovelly', type: 'Café', lat: -33.9155, lng: 151.2670 },
    { name: 'Coogee Coastal Café', suburb: 'Coogee', type: 'Café', lat: -33.9197, lng: 151.2589 },
    { name: 'Arden St Bowls', suburb: 'Coogee', type: 'Restaurant', lat: -33.9201, lng: 151.2575 },
    { name: 'Beach St Roasters', suburb: 'Coogee', type: 'Café', lat: -33.9207, lng: 151.2596 },
    { name: 'Brook St Bakery', suburb: 'Coogee', type: 'Bakery', lat: -33.9180, lng: 151.2598 },
    { name: 'High St Coffee', suburb: 'Randwick', type: 'Café', lat: -33.9173, lng: 151.2440 },
    { name: 'The Spot Café', suburb: 'Randwick', type: 'Café', lat: -33.9162, lng: 151.2460 },
    { name: 'Belmore Rd Bowls', suburb: 'Randwick', type: 'Restaurant', lat: -33.9148, lng: 151.2426 },
    { name: 'Coogee Bay Rd Eats', suburb: 'Randwick', type: 'Restaurant', lat: -33.9203, lng: 151.2470 },
    { name: 'Anzac Pde Eats', suburb: 'Kensington', type: 'Bakery', lat: -33.9089, lng: 151.2250 },
    { name: 'Day Ave Café', suburb: 'Kensington', type: 'Café', lat: -33.9103, lng: 151.2237 },
    { name: 'UNSW Bowls', suburb: 'Kensington', type: 'Restaurant', lat: -33.9170, lng: 151.2280 },
  ];

  // Venue data shown on the map. Defaults to the illustrative set; when
  // USE_LIVE_VENUES is on we fetch the real active venues on mount and swap
  // them in. Normalised to {name, suburb, type, lat, lng} so the marker /
  // popup code below stays source-agnostic.
  const [venues, setVenues] = React.useState(USE_LIVE_VENUES ? [] : EXAMPLE_VENUES);

  React.useEffect(() => {
    if (!USE_LIVE_VENUES) return;
    let cancelled = false;
    const url = LUP_SUPABASE_URL +
      '/rest/v1/venues?select=name,address,latitude,longitude&active=eq.true&order=name.asc';
    fetch(url, {
      headers: {
        apikey: LUP_SUPABASE_PUBLISHABLE_KEY,
        Authorization: 'Bearer ' + LUP_SUPABASE_PUBLISHABLE_KEY,
      },
    })
      .then(r => (r.ok ? r.json() : Promise.reject(new Error('venues fetch ' + r.status))))
      .then(rows => {
        if (cancelled) return;
        const mapped = (rows || [])
          // Hide venues without coordinates — they can't be placed on the map
          // (mirrors the app's Find-a-venue behaviour).
          .filter(v => v.latitude != null && v.longitude != null)
          .map(v => ({
            name: v.name,
            suburb: v.address || '',
            type: '',
            lat: Number(v.latitude),
            lng: Number(v.longitude),
          }));
        setVenues(mapped);
      })
      .catch(err => { console.error('[locations] live venue fetch failed', err); });
    return () => { cancelled = true; };
  }, []);

  // Build the map once, then (re)draw markers whenever the venue set changes.
  // Markers live in a dedicated layer group so a data swap (example → live)
  // re-renders pins without tearing down and recreating the whole map.
  React.useEffect(() => {
    if (!mapRef.current || typeof L === 'undefined' || !venues.length) return;

    let map = mapInstanceRef.current;
    if (!map) {
      map = L.map(mapRef.current, { scrollWheelZoom: false, zoomControl: true });
      L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> &copy; <a href="https://carto.com/attributions">CARTO</a>',
        subdomains: 'abcd',
        maxZoom: 19,
      }).addTo(map);
      markersRef.current = L.layerGroup().addTo(map);
      mapInstanceRef.current = map;
    }

    const markerIcon = L.divIcon({
      className: 'lup-marker',
      html: '<span></span>',
      iconSize: [16, 16],
      iconAnchor: [8, 8],
      popupAnchor: [0, -8],
    });

    markersRef.current.clearLayers();
    venues.forEach(v => {
      const popup = '<strong>' + v.name + '</strong>' +
        (v.suburb ? '<br/><span class="lup-popup-suburb">' + v.suburb + '</span>' : '') +
        (v.type ? ' · <span class="lup-popup-type">' + v.type + '</span>' : '');
      L.marker([v.lat, v.lng], { icon: markerIcon }).addTo(markersRef.current).bindPopup(popup);
    });

    // Fit the view tightly around the current venue cluster — avoids hand-tuned
    // zoom that drifts as venues are added/removed, and adapts to screen size.
    const bounds = L.latLngBounds(venues.map(v => [v.lat, v.lng]));
    const fitOpts = { padding: [20, 20], maxZoom: 14 };
    map.fitBounds(bounds, fitOpts);

    // Reveal animations / responsive layout can change container size after
    // mount — re-measure and re-fit once the page has settled.
    setTimeout(() => {
      if (!mapInstanceRef.current) return;
      map.invalidateSize();
      map.fitBounds(bounds, fitOpts);
    }, 100);
  }, [venues]);

  // Tear down the map only on unmount.
  React.useEffect(() => {
    return () => {
      if (mapInstanceRef.current) {
        mapInstanceRef.current.remove();
        mapInstanceRef.current = null;
        markersRef.current = null;
      }
    };
  }, []);

  // ── Pre-pilot venue-suggestion form ──────────────────────────────────────
  // Reuses the customer waitlist endpoint (/api/join-customer → Airtable). The
  // nominated venues ride along in `comments`; a distinct `source` keeps these
  // "suggest a venue" rows separate from the JoinCustomer waitlist ones, so no
  // backend / Airtable change is needed to start capturing interest.
  const [sugForm, setSugForm] = React.useState({ email: '', postcode: '', venues: '' });
  const [sugSubmitted, setSugSubmitted] = React.useState(false);
  const [sugSubmitting, setSugSubmitting] = React.useState(false);
  const [sugError, setSugError] = React.useState(null);
  const [sugErrors, setSugErrors] = React.useState({});

  const updateSug = (k) => (e) => {
    setSugForm(prev => ({ ...prev, [k]: e.target.value }));
    if (sugErrors[k]) setSugErrors(prev => ({ ...prev, [k]: null }));
  };

  const submitSug = async (e) => {
    e.preventDefault();
    const errs = {};
    if (!sugForm.venues.trim()) errs.venues = 'Tell us at least one spot';
    // Email is optional; only validate the format if something was entered.
    if (sugForm.email.trim() && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(sugForm.email)) errs.email = 'Enter a valid email';
    if (Object.keys(errs).length) { setSugErrors(errs); return; }

    setSugError(null);
    setSugSubmitting(true);
    try {
      const res = await fetch('/api/join-customer', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          email: sugForm.email.trim(),
          postcode: sugForm.postcode.trim(),
          comments: 'Suggested venues: ' + sugForm.venues.trim(),
          source: 'Website /locations (venue suggestion)',
        }),
      });
      if (!res.ok) throw new Error(`Server returned ${res.status}`);
      setSugSubmitted(true);
    } catch (err) {
      console.error('Venue suggestion submission failed:', err);
      setSugError('Sorry — something went wrong sending your suggestion. Please try again, or email contact@lupit.com.au.');
      setSugSubmitting(false);
    }
  };

  // Shared input/label styles (mirror the JoinCustomer waitlist form).
  const inputStyle = (hasErr) => ({
    width: '100%', padding: '14px 16px', fontFamily: 'var(--font-sans)', fontSize: 15,
    color: 'var(--charcoal)', background: 'var(--ivory)',
    border: `1px solid ${hasErr ? '#b53333' : 'var(--border-warm)'}`,
    borderRadius: 12, outline: 'none', transition: 'border-color 0.15s, box-shadow 0.15s',
  });
  const labelStyle = {
    display: 'block', fontSize: 12, fontWeight: 500, letterSpacing: '0.4px',
    textTransform: 'uppercase', color: 'var(--stone)', marginBottom: 8,
  };
  const focusOn = (hasErr) => ({
    onFocus: e => e.target.style.borderColor = 'var(--terracotta)',
    onBlur: e => e.target.style.borderColor = hasErr ? '#b53333' : 'var(--border-warm)',
  });

  // ── Pre-pilot block: venue-finder pill, then a two-column interest block
  // (left pitch + right form/CTA) matching the JoinCustomer / Join layout used
  // elsewhere on the site, so the section isn't centered/narrow. ──────────────
  const interestLeft = React.createElement(Reveal, { as: 'div' },
    React.createElement('div', { className: 'eyebrow', style: { marginBottom: 18 } },
      React.createElement('span', { className: 'dot' }),
      audience === 'venue' ? 'Build the network' : 'Help us grow'
    ),
    React.createElement('h3', {
      style: { fontFamily: 'var(--font-serif)', fontSize: 'clamp(28px, 3vw, 40px)', fontWeight: 500, color: 'var(--charcoal)', lineHeight: 1.15, letterSpacing: '-0.01em', marginBottom: 18 }
    }, audience === 'venue' ? 'Want to bring LÜP to your venue?' : 'Want LÜP at your favourite takeaway spots?'),
    React.createElement('p', {
      style: { fontSize: 17, color: 'var(--stone)', lineHeight: 1.65, marginBottom: 28, maxWidth: 460 }
    },
      audience === 'venue'
        ? 'We\'re signing up bowl-format venues precinct by precinct across Sydney. Join the network and we\'ll be in touch within 24 hours.'
        : 'Tell us where you\'d love to see LÜP — your local poke bar, ramen joint, salad place — and we\'ll invite them to the network.'
    ),
    React.createElement('div', {
      style: {
        background: 'var(--parchment)', borderRadius: 16, padding: '20px 22px',
        display: 'flex', alignItems: 'center', gap: 14, border: '1px solid var(--border-cream)',
      }
    },
      React.createElement(IconMail, { size: 22, color: 'var(--terracotta)' }),
      React.createElement('div', {},
        React.createElement('div', { style: { fontSize: 12, color: 'var(--silver)', letterSpacing: '0.3px' } }, 'Got questions?'),
        React.createElement('a', { href: 'mailto:contact@lupit.com.au', style: { fontSize: 15, color: 'var(--charcoal)', textDecoration: 'none', fontWeight: 500 } }, 'contact@lupit.com.au'),
      ),
    ),
  );

  // RIGHT column — venues: "what to expect" + join CTA; customers: suggest form.
  const interestRight = audience === 'venue'
    ? React.createElement(Reveal, { as: 'div', delay: 1,
        style: {
          background: 'var(--parchment)', borderRadius: 28, padding: '40px 40px',
          border: '1px solid var(--border-cream)', boxShadow: '0 4px 40px rgba(0,0,0,0.04)',
        }
      },
        React.createElement('div', {
          style: { fontFamily: 'var(--font-serif)', fontSize: 22, fontWeight: 500, color: 'var(--charcoal)', lineHeight: 1.3, marginBottom: 22 }
        }, 'Quick to get started'),
        React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 14, marginBottom: 30 } },
          [
            'Up and running in under an hour',
            'No terminal or special equipment',
            '20–60% cheaper than disposable packaging',
          ].map(t => React.createElement('div', {
            key: t,
            style: { display: 'flex', gap: 12, alignItems: 'flex-start', fontSize: 15, color: 'var(--charcoal)', lineHeight: 1.45 }
          },
            React.createElement(IconCheck, { size: 18, color: 'var(--sage-dark)' }),
            React.createElement('span', {}, t),
          )),
        ),
        React.createElement('a', {
          href: '#join',
          className: 'btn btn-terracotta',
          style: { width: '100%', padding: '16px 28px', fontSize: 16, fontWeight: 500, borderRadius: 14, justifyContent: 'center' }
        }, 'Join the network', React.createElement(IconArrowRight, { size: 16 })),
      )
    : React.createElement(Reveal, { as: 'div', delay: 1,
        id: 'suggest-venue-card',
        style: {
          background: 'var(--parchment)', borderRadius: 28, padding: '40px 40px',
          border: '1px solid var(--border-cream)', boxShadow: '0 4px 40px rgba(0,0,0,0.04)',
          scrollMarginTop: 120,
        }
      },
        sugSubmitted
          ? React.createElement('div', { style: { padding: '30px 10px', textAlign: 'center' } },
              React.createElement('div', {
                style: {
                  width: 72, height: 72, borderRadius: '50%', background: 'rgba(122,140,110,0.2)',
                  display: 'inline-flex', alignItems: 'center', justifyContent: 'center', marginBottom: 22,
                }
              }, React.createElement(IconCheck, { size: 36, color: 'var(--sage-dark)' })),
              React.createElement('h3', {
                style: { fontFamily: 'var(--font-serif)', fontSize: 26, fontWeight: 500, color: 'var(--charcoal)', marginBottom: 10, lineHeight: 1.25 }
              }, 'Thanks — noted!'),
              React.createElement('p', { style: { fontSize: 16, color: 'var(--stone)', lineHeight: 1.6, maxWidth: 380, margin: '0 auto' } },
                'We\'ll reach out to the spots you suggested and let you know when LÜP lands near ',
                React.createElement('em', { className: 'hi' }, sugForm.postcode.trim() || 'you'), '.'
              ),
            )
          : React.createElement('form', { onSubmit: submitSug, style: { display: 'flex', flexDirection: 'column', gap: 20 } },
              React.createElement('div', {},
                  React.createElement('label', { htmlFor: 'sug-venues', style: labelStyle }, 'Favourite spots *'),
                  React.createElement('textarea', Object.assign({
                    id: 'sug-venues', rows: 3, value: sugForm.venues, onChange: updateSug('venues'),
                    placeholder: 'e.g. Fishbowl Bondi, Poke House Surry Hills, my local ramen bar',
                    style: { ...inputStyle(sugErrors.venues), resize: 'vertical', fontFamily: 'var(--font-sans)' },
                  }, focusOn(sugErrors.venues))),
                  sugErrors.venues && React.createElement('div', { style: { fontSize: 12, color: '#b53333', marginTop: 6 } }, sugErrors.venues),
                ),
                React.createElement('div', {},
                  React.createElement('label', { htmlFor: 'sug-email', style: labelStyle }, 'Email (optional if you\'d like to be notified when your venue joins)'),
                  React.createElement('input', Object.assign({
                    id: 'sug-email', type: 'email', value: sugForm.email, onChange: updateSug('email'),
                    placeholder: 'youremail@domain.com.au', style: inputStyle(sugErrors.email),
                  }, focusOn(sugErrors.email))),
                  sugErrors.email && React.createElement('div', { style: { fontSize: 12, color: '#b53333', marginTop: 6 } }, sugErrors.email),
                ),
                React.createElement('div', {},
                  React.createElement('label', { htmlFor: 'sug-postcode', style: labelStyle }, 'Postcode (optional)'),
                  React.createElement('input', Object.assign({
                    id: 'sug-postcode', type: 'text', inputMode: 'numeric', value: sugForm.postcode, onChange: updateSug('postcode'),
                    placeholder: '2010', style: inputStyle(false),
                  }, focusOn(false))),
                ),
                React.createElement('button', {
                  type: 'submit', disabled: sugSubmitting, className: 'btn btn-terracotta',
                  style: {
                    padding: '16px 28px', fontSize: 16, fontWeight: 500, borderRadius: 14, marginTop: 8,
                    justifyContent: 'center', opacity: sugSubmitting ? 0.7 : 1, cursor: sugSubmitting ? 'wait' : 'pointer',
                  }
                },
                  sugSubmitting ? 'Sending…' : 'Send suggestion',
                  !sugSubmitting && React.createElement(IconArrowRight, { size: 16 }),
                ),
                sugError && React.createElement('div', {
                  style: { fontSize: 13, color: '#b53333', textAlign: 'center', lineHeight: 1.5, marginTop: -4 }
                }, sugError),
                React.createElement('div', { style: { fontSize: 12, color: 'var(--silver)', textAlign: 'center', lineHeight: 1.5 } },
                  'We\'ll only email you about LÜP launches. No spam, unsubscribe anytime.'
                ),
              )
        );

  const prelaunchBlock = React.createElement(React.Fragment, null,
    // "Find LÜP venues" pill (left-aligned, matching the rest of the site)
    React.createElement(Reveal, { as: 'div', style: { display: 'flex', justifyContent: 'flex-start', marginBottom: 64 } },
      React.createElement('a', {
        href: LUP_VENUES_APP_URL,
        className: 'btn btn-terracotta',
        style: { padding: '14px 24px', fontSize: 15, borderRadius: 100 }
      }, 'Find LÜP venues', React.createElement(IconArrowRight, { size: 14 })),
    ),
    // Two-column interest block (pitch + form/CTA) — matches JoinCustomer / Join
    React.createElement('div', {
      className: 'stack-md',
      style: { display: 'grid', gridTemplateColumns: '1fr 1.1fr', gap: 56, alignItems: 'start' }
    }, interestLeft, interestRight),
  );

  return React.createElement('section', { id: 'locations', style: { background: 'var(--ivory)', borderTop: '1px solid var(--border-cream)' } },
    React.createElement('div', { className: 'container' },
      // Header
      React.createElement(Reveal, { as: 'div',
        style: { maxWidth: 760, marginBottom: 32 }
      },
        React.createElement('div', { className: 'eyebrow', style: { marginBottom: 18 } },
          React.createElement('span', { className: 'dot' }), 'LÜP locations'
        ),
        React.createElement('h2', {
          style: { fontSize: 'clamp(36px, 4vw, 56px)', lineHeight: 1.05, letterSpacing: '-0.02em', marginBottom: 16 }
        },
          header.leadText,
          React.createElement('span', { className: 'serif-accent' }, header.accentText)
        ),
        React.createElement('p', { style: { fontSize: 17, color: 'var(--stone)', lineHeight: 1.6 } },
          header.subText
        ),
      ),

      // Map container (SHOW_MAP only). Hidden pre-pilot; the Leaflet effects
      // above no-op while this div isn't mounted (mapRef stays null).
      SHOW_MAP && React.createElement('div', {
        ref: mapRef,
        className: 'lup-map',
        style: {
          height: 'clamp(420px, 60vh, 560px)',
          borderRadius: 24,
          overflow: 'hidden',
          border: '1px solid var(--border-cream)',
          boxShadow: '0 4px 30px rgba(0,0,0,0.04)',
          background: 'var(--parchment)',
        }
      }),

      // CTA pill (SHOW_MAP only) — takes the visitor into the app's live venue finder.
      SHOW_MAP && React.createElement('div', { style: { display: 'flex', justifyContent: 'center', marginTop: 24 } },
        React.createElement('a', {
          href: LUP_VENUES_APP_URL,
          className: 'btn btn-terracotta',
          style: { padding: '14px 24px', fontSize: 15, borderRadius: 100 }
        }, 'Find LÜP venues', React.createElement(IconArrowRight, { size: 14 })),
      ),

      // Pre-pilot explainer + venue-suggestion form (shown while the map is hidden).
      !SHOW_MAP && prelaunchBlock,
    ),
  );
};
