// Clan Of VTC — Homepage. Fullscreen MapLibre map + centered search + layer toggles.

const MAP_STYLE = 'https://tiles.openfreemap.org/styles/liberty';
const GCC_VIEW  = { center: [50, 25], zoom: 4.4 };
const POINTS_URL = 'data/points.geojson';

const KIND_COLOR = {
  event:    '#bd24df',
  spot:     '#2d6ade',
  product:  '#d6c441',
  part:     '#34d399',
  workshop: '#f87171',
  city:     '#aabbd9',
};

const KIND_LABEL = {
  event:    'Events',
  spot:     'Spots',
  product:  'Listings',
  part:     'Parts',
  workshop: 'Workshops',
  city:     'Cities',
};

const KIND_ORDER = ['event', 'spot', 'product', 'part', 'workshop', 'city'];

// Rough GCC bounding box — center on user only if they're inside.
const GCC_BBOX = { minLng: 34, maxLng: 60, minLat: 16, maxLat: 32 };
const inGCC = (lng, lat) =>
  lng >= GCC_BBOX.minLng && lng <= GCC_BBOX.maxLng &&
  lat >= GCC_BBOX.minLat && lat <= GCC_BBOX.maxLat;

const HomePage = () => {
  const mapRef = React.useRef(null);
  const containerRef = React.useRef(null);
  const dataRef = React.useRef(null);
  const sourceLoaded = React.useRef(false);

  const [ready, setReady] = React.useState(false);
  const [query, setQuery] = React.useState('');
  const [searchOpen, setSearchOpen] = React.useState(false);
  const [searchCompact, setSearchCompact] = React.useState(false);
  const [enabledKinds, setEnabledKinds] = React.useState(() => new Set(KIND_ORDER));
  const [kindCounts, setKindCounts] = React.useState({});
  const [countries, setCountries] = React.useState([]);
  const [enabledCountries, setEnabledCountries] = React.useState(() => new Set());
  const [countryCounts, setCountryCounts] = React.useState({});
  const [locating, setLocating] = React.useState(false);
  const [selected, setSelected] = React.useState(null);
  const [heatmapOn, setHeatmapOn] = React.useState(false);
  const [extraOpen, setExtraOpen] = React.useState(false);

  // ─── Init map once ────────────────────────────────────────────
  React.useEffect(() => {
    if (!containerRef.current || mapRef.current) return;

    const map = new maplibregl.Map({
      container: containerRef.current,
      style: MAP_STYLE,
      center: GCC_VIEW.center,
      zoom: GCC_VIEW.zoom,
      attributionControl: { compact: true },
    });
    mapRef.current = map;

    map.addControl(new maplibregl.NavigationControl({ visualizePitch: false }), 'bottom-right');

    const geolocate = new maplibregl.GeolocateControl({
      positionOptions: { enableHighAccuracy: true, timeout: 8000 },
      trackUserLocation: false,
      showUserLocation: true,
      showAccuracyCircle: true,
      fitBoundsOptions: { maxZoom: 11 },
    });
    map.addControl(geolocate, 'bottom-right');

    map.on('load', async () => {
      // Load sample data
      let geojson;
      try {
        const res = await fetch(POINTS_URL);
        geojson = await res.json();
      } catch (e) {
        console.error('Failed to load points.geojson', e);
        geojson = { type: 'FeatureCollection', features: [] };
      }
      dataRef.current = geojson;

      // Pre-compute kind + country counts for the toggle chips
      const kCounts = {};
      const cCounts = {};
      geojson.features.forEach((f) => {
        const p = f.properties || {};
        if (p.kind)    kCounts[p.kind]    = (kCounts[p.kind]    || 0) + 1;
        if (p.country) cCounts[p.country] = (cCounts[p.country] || 0) + 1;
      });
      setKindCounts(kCounts);
      setCountryCounts(cCounts);
      const sortedCountries = Object.keys(cCounts).sort();
      setCountries(sortedCountries);
      setEnabledCountries(new Set(sortedCountries));

      map.addSource('vtc', {
        type: 'geojson',
        data: geojson,
        cluster: true,
        clusterMaxZoom: 11,
        clusterRadius: 50,
        clusterProperties: buildClusterProperties(),
      });
      sourceLoaded.current = true;

      addHeatmapLayer(map);
      addClusterLayers(map);
      addPointLayer(map);
      wireMapInteractions(map, setSelected);

      setReady(true);

      // ─── Geolocation-aware default view ────────────────────────
      // If permission is already granted, fly to the user automatically.
      // Otherwise leave them on the GCC overview; they can hit the locate button.
      tryAutoLocate(geolocate);
    });

    // ─── Compact-search triggers ──────────────────────────────────
    // Any user-driven zoom/pan/wheel/touch should snap the search to the top.
    const userGesture = () => setSearchCompact(true);
    map.on('wheel',       userGesture);
    map.on('dragstart',   userGesture);
    map.on('touchstart',  userGesture);
    map.on('dblclick',    userGesture);
    map.on('zoomstart',   (e) => { if (e.originalEvent) setSearchCompact(true); });

    return () => { map.remove(); mapRef.current = null; sourceLoaded.current = false; };
  }, []);

  // ─── Apply heatmap visibility ────────────────────────────────
  React.useEffect(() => {
    const map = mapRef.current;
    if (!map || !sourceLoaded.current || !map.getLayer('heatmap')) return;
    map.setLayoutProperty('heatmap', 'visibility', heatmapOn ? 'visible' : 'none');
  }, [heatmapOn, ready]);

  // ─── Re-filter the source when enabled kinds or countries change ─
  React.useEffect(() => {
    const map = mapRef.current;
    if (!map || !sourceLoaded.current || !dataRef.current) return;
    const filtered = {
      type: 'FeatureCollection',
      features: dataRef.current.features.filter((f) => {
        const p = f.properties || {};
        return enabledKinds.has(p.kind) && enabledCountries.has(p.country);
      }),
    };
    const src = map.getSource('vtc');
    if (src) src.setData(filtered);
  }, [enabledKinds, enabledCountries, ready]);

  // ─── Search filtering ─────────────────────────────────────────
  const results = React.useMemo(() => {
    if (!query.trim() || !dataRef.current) return [];
    const q = query.trim().toLowerCase();
    return dataRef.current.features
      .filter((f) => {
        const p = f.properties || {};
        if (!enabledKinds.has(p.kind)) return false;
        if (!enabledCountries.has(p.country)) return false;
        return (p.name || '').toLowerCase().includes(q)
          || (p.region || '').toLowerCase().includes(q)
          || (p.country || '').toLowerCase().includes(q)
          || (p.kind || '').toLowerCase().includes(q)
          || (p.description || '').toLowerCase().includes(q);
      })
      .slice(0, 8);
  }, [query, ready, enabledKinds, enabledCountries]);

  const flyTo = (feature) => {
    const map = mapRef.current;
    if (!map) return;
    map.easeTo({ center: feature.geometry.coordinates, zoom: 12, duration: 1200 });
    setSearchOpen(false);
    setQuery('');
    setSearchCompact(true);
    setSelected(feature);
  };

  const toggleKind = (k) => {
    setEnabledKinds((prev) => {
      const next = new Set(prev);
      if (next.has(k)) next.delete(k); else next.add(k);
      return next;
    });
  };

  const toggleCountry = (c) => {
    setEnabledCountries((prev) => {
      const next = new Set(prev);
      if (next.has(c)) next.delete(c); else next.add(c);
      return next;
    });
  };

  const tryAutoLocate = async (geolocate) => {
    if (!navigator.geolocation) return;
    try {
      // Check permission state without prompting.
      const perm = navigator.permissions && navigator.permissions.query
        ? await navigator.permissions.query({ name: 'geolocation' })
        : { state: 'prompt' };
      if (perm.state !== 'granted') return;
      setLocating(true);
      navigator.geolocation.getCurrentPosition(
        (pos) => {
          setLocating(false);
          const { longitude, latitude } = pos.coords;
          const map = mapRef.current;
          if (!map) return;
          if (inGCC(longitude, latitude)) {
            map.easeTo({ center: [longitude, latitude], zoom: 10, duration: 1400 });
            setSearchCompact(true);
            // Trigger the control so the user dot shows
            try { geolocate.trigger(); } catch (_) {}
          }
        },
        () => setLocating(false),
        { enableHighAccuracy: true, timeout: 7000, maximumAge: 60000 }
      );
    } catch (_) {
      setLocating(false);
    }
  };

  return (
    <div className="home">
      <div ref={containerRef} className="home__map" aria-label="GCC enthusiast map" />

      <header className="home__header">
        <div className="home__header-left">
          <AuthMenu />
          <div className="home__brand">
            <img src="assets/logo.svg" alt="" className="home__logo" />
            <span>{(window.DATA && window.DATA.brand && window.DATA.brand.name) || 'Clan Of VTC'}</span>
          </div>
        </div>

        <div className="home__filters">
          <LayerToggles
            kinds={KIND_ORDER}
            enabled={enabledKinds}
            counts={kindCounts}
            onToggle={toggleKind}
          />
          <button
            className={`home__filters-more${extraOpen ? ' is-open' : ''}`}
            onClick={() => setExtraOpen((v) => !v)}
            aria-expanded={extraOpen}
            aria-controls="home-filters-extra"
            title="More filters"
          >
            <FilterIcon />
            <span>More</span>
          </button>
          <div
            id="home-filters-extra"
            className={`home__filters-extra${extraOpen ? ' is-open' : ''}`}
          >
            {countries.length > 1 && (
              <CountryToggles
                countries={countries}
                enabled={enabledCountries}
                counts={countryCounts}
                onToggle={toggleCountry}
              />
            )}
            <div className="home__view-mode">
              <button
                className={`home__viewmode-btn${heatmapOn ? ' is-on' : ''}`}
                onClick={() => setHeatmapOn((v) => !v)}
                aria-pressed={heatmapOn}
                title="Toggle heatmap overlay (low zoom)"
              >
                <HeatIcon /> Heatmap
              </button>
            </div>
          </div>
        </div>
      </header>

      <div className={`home__search${searchCompact ? ' home__search--compact' : ''}`}>
        <div className="home__search-wrap">
          <SearchIcon />
          <input
            className="home__search-input"
            type="search"
            placeholder="Search events, spots, products, parts…"
            value={query}
            onChange={(e) => { setQuery(e.target.value); setSearchOpen(true); }}
            onFocus={() => { setSearchOpen(true); setSearchCompact(true); }}
            aria-label="Search the map"
          />
          {query && (
            <button className="home__search-clear"
                    onClick={() => { setQuery(''); setSearchOpen(false); }}
                    aria-label="Clear">×</button>
          )}
        </div>

        {searchOpen && query && (
          <div className="home__results">
            {results.length === 0 && (
              <div className="home__result home__result--empty">No matches for "{query}"</div>
            )}
            {results.map((f) => {
              const p = f.properties || {};
              return (
                <div key={p.id || p.name} className="home__result" onClick={() => flyTo(f)}>
                  <span className="home__result-dot" style={{ background: KIND_COLOR[p.kind] || '#74849f' }} />
                  <div className="home__result-body">
                    <div className="home__result-name">{p.name}</div>
                    <div className="home__result-meta">
                      <span className="home__result-kind">{KIND_LABEL[p.kind] || p.kind}</span>
                      {p.region && <span> · {p.region}</span>}
                      {p.country && <span> · {p.country}</span>}
                    </div>
                  </div>
                </div>
              );
            })}
          </div>
        )}

        {!searchCompact && <Legend />}
      </div>

      {locating && <div className="home__locating">Locating you…</div>}

      <DetailDrawer feature={selected} onClose={() => setSelected(null)} />

      <InstallPrompt />

      <Footer />
    </div>
  );
};

// ─── Map layer helpers ──────────────────────────────────────────

// One numeric counter per kind, summed across all features in a cluster.
function buildClusterProperties() {
  const props = {};
  for (const k of KIND_ORDER) {
    props[`k_${k}`] = ['+', ['case', ['==', ['get', 'kind'], k], 1, 0]];
  }
  return props;
}

// Pick the kind with the highest count in the cluster and map to its color.
// Ties resolve in KIND_ORDER order (first wins), which keeps brand-y kinds
// like events ahead of more numerous but visually quiet ones like cities.
function dominantKindColorExpr() {
  const expr = ['case'];
  for (const k of KIND_ORDER) {
    const conds = ['all'];
    for (const other of KIND_ORDER) {
      if (other === k) continue;
      conds.push(['>=', ['get', `k_${k}`], ['get', `k_${other}`]]);
    }
    expr.push(conds, KIND_COLOR[k]);
  }
  expr.push('#74849f');
  return expr;
}

// Heatmap of the same clustered source. Weight by point_count so clusters
// "spread" their density; individual (non-clustered) features count as 1.
// Fades out by zoom 9 — pure low-zoom overview tool.
function addHeatmapLayer(map) {
  map.addLayer({
    id: 'heatmap',
    type: 'heatmap',
    source: 'vtc',
    maxzoom: 10,
    layout: { visibility: 'none' },
    paint: {
      'heatmap-weight': ['case', ['has', 'point_count'], ['get', 'point_count'], 1],
      'heatmap-intensity': ['interpolate', ['linear'], ['zoom'], 0, 1, 9, 3],
      'heatmap-color': [
        'interpolate', ['linear'], ['heatmap-density'],
        0,    'rgba(45,106,222,0)',
        0.2,  'rgba(45,106,222,0.45)',
        0.45, 'rgba(189,36,223,0.65)',
        0.7,  'rgba(214,196,65,0.85)',
        1,    'rgba(248,113,113,0.95)',
      ],
      'heatmap-radius': ['interpolate', ['linear'], ['zoom'], 0, 18, 9, 38],
      'heatmap-opacity': ['interpolate', ['linear'], ['zoom'], 0, 0.85, 8, 0.7, 9, 0],
    },
  });
}

function addClusterLayers(map) {
  map.addLayer({
    id: 'clusters',
    type: 'circle',
    source: 'vtc',
    filter: ['has', 'point_count'],
    paint: {
      'circle-color': dominantKindColorExpr(),
      'circle-radius': [
        'step', ['get', 'point_count'],
        18, 5,
        24, 15,
        32,
      ],
      'circle-stroke-width': 2,
      'circle-stroke-color': 'rgba(255,255,255,0.85)',
      'circle-opacity': 0.9,
    },
  });

  map.addLayer({
    id: 'cluster-count',
    type: 'symbol',
    source: 'vtc',
    filter: ['has', 'point_count'],
    layout: {
      'text-field': '{point_count_abbreviated}',
      'text-font': ['Noto Sans Regular'],
      'text-size': 13,
    },
    paint: { 'text-color': '#ffffff' },
  });
}

function addPointLayer(map) {
  const colorMatch = ['match', ['get', 'kind']];
  Object.entries(KIND_COLOR).forEach(([k, c]) => { colorMatch.push(k, c); });
  colorMatch.push('#74849f');

  map.addLayer({
    id: 'point',
    type: 'circle',
    source: 'vtc',
    filter: ['!', ['has', 'point_count']],
    paint: {
      'circle-color': colorMatch,
      'circle-radius': [
        'interpolate', ['linear'], ['zoom'],
        4, 4,
        8, 6,
        12, 9,
      ],
      'circle-stroke-width': 2,
      'circle-stroke-color': 'rgba(255,255,255,0.9)',
    },
  });

  // Larger halo layer for events (extra emphasis)
  map.addLayer({
    id: 'point-halo',
    type: 'circle',
    source: 'vtc',
    filter: ['all', ['!', ['has', 'point_count']], ['==', ['get', 'kind'], 'event']],
    paint: {
      'circle-color': KIND_COLOR.event,
      'circle-radius': [
        'interpolate', ['linear'], ['zoom'],
        4, 10,
        12, 22,
      ],
      'circle-opacity': 0.18,
      'circle-blur': 0.4,
    },
  }, 'point');
}

function wireMapInteractions(map, onSelect) {
  ['clusters', 'point'].forEach((id) => {
    map.on('mouseenter', id, () => { map.getCanvas().style.cursor = 'pointer'; });
    map.on('mouseleave', id, () => { map.getCanvas().style.cursor = ''; });
  });

  map.on('click', 'clusters', (e) => {
    const f = map.queryRenderedFeatures(e.point, { layers: ['clusters'] })[0];
    if (!f) return;
    const clusterId = f.properties.cluster_id;
    map.getSource('vtc').getClusterExpansionZoom(clusterId).then((zoom) => {
      map.easeTo({ center: f.geometry.coordinates, zoom });
    });
  });

  map.on('click', 'point', (e) => {
    const f = e.features[0];
    onSelect({
      type: 'Feature',
      geometry: { type: 'Point', coordinates: f.geometry.coordinates.slice() },
      properties: f.properties || {},
    });
  });
}

// ─── Subcomponents ──────────────────────────────────────────────

const LayerToggles = ({ kinds, enabled, counts, onToggle }) => (
  <div className="home__layers" role="group" aria-label="Map layers">
    {kinds.map((k) => {
      const on = enabled.has(k);
      const count = counts[k] || 0;
      return (
        <button
          key={k}
          className={`home__layer${on ? '' : ' home__layer--off'}`}
          onClick={() => onToggle(k)}
          aria-pressed={on}
          title={`${KIND_LABEL[k]} (${count})`}
        >
          <span className="home__layer-dot" style={{ background: KIND_COLOR[k] }} />
          <span className="home__layer-label">{KIND_LABEL[k]}</span>
          <span className="home__layer-count">{count}</span>
        </button>
      );
    })}
  </div>
);

const CountryToggles = ({ countries, enabled, counts, onToggle }) => (
  <div className="home__countries" role="group" aria-label="Filter by country">
    {countries.map((c) => {
      const on = enabled.has(c);
      const count = counts[c] || 0;
      return (
        <button
          key={c}
          className={`home__country${on ? '' : ' home__country--off'}`}
          onClick={() => onToggle(c)}
          aria-pressed={on}
          title={`${c} (${count})`}
        >
          <span className="home__country-label">{c}</span>
          <span className="home__country-count">{count}</span>
        </button>
      );
    })}
  </div>
);

const FilterIcon = () => (
  <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor"
       strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3" />
  </svg>
);

const HeatIcon = () => (
  <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor"
       strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <path d="M12 2s5 4.5 5 10a5 5 0 1 1-10 0c0-2 1-3 2-4 0 2 1 3 2 3 0-3-1-5 1-9z"/>
  </svg>
);

const SearchIcon = () => (
  <svg className="home__search-icon" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <circle cx="11" cy="11" r="7" />
    <line x1="21" y1="21" x2="16.65" y2="16.65" />
  </svg>
);

const Legend = () => (
  <div className="home__legend">
    {KIND_ORDER.filter((k) => k !== 'city').map((k) => (
      <span key={k} className="home__legend-item">
        <span className="home__legend-dot" style={{ background: KIND_COLOR[k] }} />
        {KIND_LABEL[k]}
      </span>
    ))}
  </div>
);

const Footer = () => {
  const brand = (window.DATA && window.DATA.brand) || { tagline: 'Built On Sand. Sworn To The 4800.' };
  const connect = (window.DATA && window.DATA.connect) || [];
  return (
    <footer className="home__footer">
      <div className="home__footer-left">
        <div className="home__tagline">{brand.tagline}</div>
        <div className="home__copy">© {new Date().getFullYear()} Clan Of VTC · vtcclan.com</div>
      </div>
      <div className="home__connect">
        {connect.map((c) => (
          <a key={c.ttl} className="home__connect-item" href={connectHref(c)}
             target={c.ico === 'whatsapp' || c.ico === 'insta' || c.ico === 'pin' ? '_blank' : undefined}
             rel="noopener noreferrer">
            <ConnectIcon name={c.ico} />
            <span className="home__connect-text">
              <span className="home__connect-label">{c.ttl}</span>
              <span className="home__connect-value">{c.v}</span>
            </span>
          </a>
        ))}
      </div>
    </footer>
  );
};

const connectHref = (c) => {
  if (c.ico === 'whatsapp') return `https://wa.me/${c.v.replace(/[^0-9]/g, '')}`;
  if (c.ico === 'insta')    return `https://instagram.com/${c.v.replace(/^@/, '')}`;
  if (c.ico === 'mail')     return `mailto:${c.v}`;
  if (c.ico === 'pin')      return `https://www.google.com/maps/search/${encodeURIComponent(c.v)}`;
  return '#';
};

const ConnectIcon = ({ name }) => {
  const common = { width: 18, height: 18, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round' };
  if (name === 'whatsapp') return <svg {...common}><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>;
  if (name === 'insta')    return <svg {...common}><rect x="2" y="2" width="20" height="20" rx="5" ry="5"/><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"/><line x1="17.5" y1="6.5" x2="17.51" y2="6.5"/></svg>;
  if (name === 'mail')     return <svg {...common}><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>;
  if (name === 'pin')      return <svg {...common}><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>;
  return null;
};

// ─── Auth menu ──────────────────────────────────────────────────

const AuthMenu = () => {
  const [user, setUser] = React.useState(null);
  const [loaded, setLoaded] = React.useState(false);
  const [open, setOpen] = React.useState(false);

  React.useEffect(() => {
    fetch('/api/auth/me', { credentials: 'same-origin' })
      .then((r) => r.json())
      .then((d) => setUser(d.user || null))
      .catch(() => setUser(null))
      .finally(() => setLoaded(true));
  }, []);

  React.useEffect(() => {
    if (!open) return;
    const close = (e) => {
      if (!e.target.closest || !e.target.closest('.home__auth')) setOpen(false);
    };
    window.addEventListener('click', close);
    return () => window.removeEventListener('click', close);
  }, [open]);

  if (!loaded) return <div className="home__auth home__auth--placeholder" aria-hidden="true" />;

  if (!user) {
    return (
      <a className="home__auth-signin" href="/api/auth/google/start">
        <GoogleIcon />
        <span>Sign in</span>
      </a>
    );
  }

  const initial = (user.name || user.email || '?').trim().charAt(0).toUpperCase();
  return (
    <div className="home__auth">
      <button
        className="home__auth-btn"
        onClick={() => setOpen((v) => !v)}
        aria-haspopup="menu"
        aria-expanded={open}
      >
        {user.picture
          ? <img src={user.picture} alt="" className="home__auth-avatar" referrerPolicy="no-referrer" />
          : <span className="home__auth-initial">{initial}</span>}
      </button>
      {open && (
        <div className="home__auth-menu" role="menu">
          <div className="home__auth-menu-head">
            <div className="home__auth-menu-name">{user.name || 'Signed in'}</div>
            <div className="home__auth-menu-email">{user.email}</div>
          </div>
          <a className="home__auth-menu-item" href="/api/auth/logout">Sign out</a>
        </div>
      )}
    </div>
  );
};

const GoogleIcon = () => (
  <svg width="14" height="14" viewBox="0 0 18 18" aria-hidden="true">
    <path fill="#4285F4" d="M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.91c1.7-1.57 2.69-3.88 2.69-6.62z"/>
    <path fill="#34A853" d="M9 18c2.43 0 4.47-.81 5.96-2.18l-2.91-2.26c-.81.54-1.84.86-3.05.86-2.34 0-4.33-1.58-5.04-3.7H.96v2.33A9 9 0 0 0 9 18z"/>
    <path fill="#FBBC05" d="M3.96 10.72A5.41 5.41 0 0 1 3.68 9c0-.6.1-1.18.28-1.72V4.95H.96A9 9 0 0 0 0 9c0 1.45.35 2.83.96 4.05l3-2.33z"/>
    <path fill="#EA4335" d="M9 3.58c1.32 0 2.5.45 3.44 1.35l2.58-2.58A9 9 0 0 0 9 0a9 9 0 0 0-8.04 4.95l3 2.33C4.67 5.16 6.66 3.58 9 3.58z"/>
  </svg>
);

// ─── Install prompt ─────────────────────────────────────────────

const IOS_HINT_KEY = 'vtc-ios-install-dismissed';

const InstallPrompt = () => {
  const [evt, setEvt] = React.useState(null);
  const [showIos, setShowIos] = React.useState(false);
  const [hiddenAfterInstall, setHiddenAfterInstall] = React.useState(false);

  React.useEffect(() => {
    const ua = navigator.userAgent || '';
    const isIOS = /iPad|iPhone|iPod/.test(ua) && !window.MSStream;
    const standalone =
      (navigator.standalone === true) ||
      (window.matchMedia && window.matchMedia('(display-mode: standalone)').matches);

    if (standalone) return; // already installed — nothing to show

    const onPrompt = (e) => { e.preventDefault(); setEvt(e); };
    const onInstalled = () => { setEvt(null); setHiddenAfterInstall(true); };
    window.addEventListener('beforeinstallprompt', onPrompt);
    window.addEventListener('appinstalled', onInstalled);

    let id;
    if (isIOS) {
      let dismissed = false;
      try { dismissed = localStorage.getItem(IOS_HINT_KEY) === '1'; } catch (_) {}
      if (!dismissed) {
        // Delay so it doesn't fight the first paint
        id = setTimeout(() => setShowIos(true), 3000);
      }
    }

    return () => {
      window.removeEventListener('beforeinstallprompt', onPrompt);
      window.removeEventListener('appinstalled', onInstalled);
      if (id) clearTimeout(id);
    };
  }, []);

  const install = async () => {
    if (!evt) return;
    evt.prompt();
    await evt.userChoice;
    setEvt(null);
  };

  const dismissIos = () => {
    setShowIos(false);
    try { localStorage.setItem(IOS_HINT_KEY, '1'); } catch (_) {}
  };

  if (hiddenAfterInstall) return null;

  if (evt) {
    return (
      <button className="home__install" onClick={install} aria-label="Install Clan Of VTC">
        <InstallIcon />
        <span>Install app</span>
      </button>
    );
  }

  if (showIos) {
    return (
      <div className="home__ios-hint" role="status" aria-live="polite">
        <div className="home__ios-hint-body">
          <strong>Add to Home Screen</strong>
          <span>Tap <ShareIosIcon /> then "Add to Home Screen"</span>
        </div>
        <button className="home__ios-hint-close" onClick={dismissIos} aria-label="Dismiss">×</button>
      </div>
    );
  }

  return null;
};

const InstallIcon = () => (
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
       strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
    <polyline points="7 10 12 15 17 10" />
    <line x1="12" y1="15" x2="12" y2="3" />
  </svg>
);

const ShareIosIcon = () => (
  <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor"
       strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"
       style={{ verticalAlign: '-2px', margin: '0 2px' }}>
    <path d="M12 3v13" />
    <polyline points="7 8 12 3 17 8" />
    <path d="M5 12v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-7" />
  </svg>
);

// ─── Detail drawer ──────────────────────────────────────────────

const DetailDrawer = ({ feature, onClose }) => {
  // Keep markup mounted across close so the slide-out animates.
  // Wait one frame after mount so the un-open state commits first, then add .is-open.
  const [mounted, setMounted] = React.useState(false);
  const [last, setLast] = React.useState(null);
  React.useEffect(() => {
    if (feature) {
      setLast(feature);
      const id = requestAnimationFrame(() => setMounted(true));
      return () => cancelAnimationFrame(id);
    }
    setMounted(false);
  }, [feature]);

  // Esc closes
  React.useEffect(() => {
    if (!mounted) return;
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [mounted, onClose]);

  const data = feature || last;
  if (!data) return null;
  const p = data.properties || {};
  const [lng, lat] = data.geometry.coordinates;
  const color = KIND_COLOR[p.kind] || '#74849f';
  const kindLabel = KIND_LABEL[p.kind] || p.kind || '';
  const meta = [p.region, p.country].filter(Boolean).join(' · ');

  const directionsHref = buildDirectionsUrl(lat, lng, p.name);
  const shareThis = () => sharePoint(p, lat, lng);

  return (
    <>
      <div
        className={`home__drawer-backdrop${mounted ? ' is-open' : ''}`}
        onClick={onClose}
        aria-hidden="true"
      />
      <aside
        className={`home__drawer${mounted ? ' is-open' : ''}`}
        role="dialog"
        aria-label={p.name || 'Detail'}
      >
        <div className="home__drawer-hero" style={{ background: `linear-gradient(135deg, ${color} 0%, rgba(14,20,36,0.95) 100%)` }}>
          <button className="home__drawer-close" onClick={onClose} aria-label="Close">×</button>
          <div className="home__drawer-kind">
            <span className="home__drawer-kind-dot" style={{ background: color }} />
            {kindLabel.toUpperCase()}
          </div>
        </div>

        <div className="home__drawer-body">
          <h2 className="home__drawer-name">{p.name || 'Unnamed'}</h2>
          {meta && <div className="home__drawer-meta">{meta}</div>}

          {(p.date || p.price) && (
            <div className="home__drawer-facts">
              {p.date  && <div className="home__drawer-fact"><span>When</span>{p.date}</div>}
              {p.price && <div className="home__drawer-fact"><span>Price</span>{p.price}</div>}
            </div>
          )}

          {p.description && <p className="home__drawer-desc">{p.description}</p>}

          <div className="home__drawer-actions">
            <a className="home__drawer-btn home__drawer-btn--primary" href={directionsHref} target="_blank" rel="noopener noreferrer">
              Get directions
            </a>
            <button className="home__drawer-btn" onClick={shareThis}>Share</button>
          </div>

          <div className="home__drawer-coords">
            {lat.toFixed(4)}, {lng.toFixed(4)}
          </div>
        </div>
      </aside>
    </>
  );
};

function buildDirectionsUrl(lat, lng, name) {
  const isApple = /(iPhone|iPad|iPod|Macintosh)/.test(navigator.userAgent);
  const q = name ? encodeURIComponent(name) : '';
  if (isApple) {
    return `https://maps.apple.com/?ll=${lat},${lng}${q ? `&q=${q}` : ''}`;
  }
  return `https://www.google.com/maps/search/?api=1&query=${lat},${lng}${q ? `&query_place_id=${q}` : ''}`;
}

async function sharePoint(p, lat, lng) {
  const title = p.name || 'Clan Of VTC';
  const text = [KIND_LABEL[p.kind] || p.kind, p.region, p.country].filter(Boolean).join(' · ');
  const url = window.location.href;
  const payload = { title, text: text ? `${text} — ${title}` : title, url };
  try {
    if (navigator.share) {
      await navigator.share(payload);
      return;
    }
  } catch (_) { /* user dismissed */ }
  try {
    await navigator.clipboard.writeText(`${title} — ${url}`);
  } catch (_) {}
}
