// ROAMR — Explore + Route Detail + Saved + Profile screens
const { TOKENS: T, Chip, ConfBadge, Stat, SurfaceBar, MapMock, ElevationGraph, ActIcon, SectionHead, IconBtn } = window;

// ────────────────────────────────────────────────────────────
// Sample data
// ────────────────────────────────────────────────────────────
const ROUTES = [
  {
    id: 'r1',
    name: 'Roych Clough Byway',
    region: 'Peak District · Derbyshire',
    distance: '14.2', elev: '+428', time: '2h 10m',
    activity: 'moto', diff: 'INTERMEDIATE',
    conf: 'high', confDays: 8,
    surfaces: [
      { label: 'Tarmac', pct: 22, color: '#5a6253' },
      { label: 'Byway', pct: 48, color: T.signal },
      { label: 'Rough', pct: 23, color: T.amber },
      { label: 'Tech', pct: 7, color: T.rust },
    ],
    routePath: "M40 165 Q 70 140 100 130 Q 130 120 160 100 Q 200 80 230 90 Q 270 110 310 80 Q 340 60 370 75",
    reports: 3,
    tags: ['BOAT', 'Big-ADV friendly'],
  },
  {
    id: 'r2',
    name: 'Stanage North Loop',
    region: 'Peak District · S. Yorks',
    distance: '8.6', elev: '+312', time: '3h 20m',
    activity: 'hike', diff: 'EASY',
    conf: 'high', confDays: 14,
    surfaces: [
      { label: 'Path', pct: 68, color: T.signal },
      { label: 'Rocky', pct: 24, color: T.amber },
      { label: 'Road', pct: 8, color: '#5a6253' },
    ],
    routePath: "M50 160 Q 80 150 110 120 L 150 110 Q 200 100 240 130 Q 280 150 310 130 L 360 100",
    reports: 1,
    tags: ['Dog-friendly', 'Circular'],
  },
  {
    id: 'r3',
    name: 'Strines Reservoir Gravel',
    region: 'Bradfield · S. Yorks',
    distance: '32.8', elev: '+540', time: '2h 45m',
    activity: 'gravel', diff: 'INTERMEDIATE',
    conf: 'med', confDays: 38,
    surfaces: [
      { label: 'Tarmac', pct: 38, color: '#5a6253' },
      { label: 'Gravel', pct: 54, color: T.signal },
      { label: 'Rough', pct: 8, color: T.amber },
    ],
    routePath: "M40 170 Q 80 160 110 140 Q 140 120 180 130 Q 220 140 260 110 Q 300 80 340 95 L 370 80",
    reports: 0,
    tags: ['Cafe stop', 'Circular'],
  },
  {
    id: 'r4',
    name: 'Glossop UCR Network',
    region: 'High Peak · Derbyshire',
    distance: '21.4', elev: '+612', time: '3h 50m',
    activity: 'moto', diff: 'ADVANCED',
    conf: 'low', confDays: 94,
    surfaces: [
      { label: 'Tarmac', pct: 12, color: '#5a6253' },
      { label: 'Byway', pct: 38, color: T.signal },
      { label: 'Rough', pct: 32, color: T.amber },
      { label: 'Tech', pct: 18, color: T.rust },
    ],
    routePath: "M30 170 Q 60 140 90 130 L 130 150 Q 170 170 210 130 Q 250 90 290 110 Q 320 130 360 100",
    reports: 5,
    warn: true,
    tags: ['UCR', 'Recent TRO report'],
  },
];

// ────────────────────────────────────────────────────────────
// ROUTE CARD
// ────────────────────────────────────────────────────────────
function RouteCard({ route, onClick, compact }) {
  return (
    <div onClick={onClick} role="button" tabIndex={0} style={{
      display: 'flex', flexDirection: 'column', gap: 0,
      width: '100%', background: T.card, border: `1px solid ${T.border}`,
      borderRadius: 3, overflow: 'hidden', cursor: 'pointer', textAlign: 'left',
      padding: 0,
    }}>
      <div style={{ position: 'relative', height: compact ? 100 : 132 }}>
        <MapMock height={compact ? 100 : 132} routePath={route.routePath}
          pins={[{ x: 45, y: parseFloat(route.routePath.split(' ')[1]) || 165, label: 'R' }]} />
        <div style={{ position: 'absolute', top: 8, left: 8, display: 'flex', gap: 6 }}>
          <Chip sm active={false}>
            <ActIcon kind={route.activity} size={11} />
            <span style={{ marginLeft: 3 }}>{route.activity.toUpperCase()}</span>
          </Chip>
          {route.warn && <Chip sm danger>⚠ TRO</Chip>}
        </div>
        <div style={{ position: 'absolute', top: 8, right: 8 }}>
          <ConfBadge level={route.conf} days={route.confDays} compact />
        </div>
      </div>
      <div style={{ padding: '14px 14px 16px', display: 'flex', flexDirection: 'column', gap: 10 }}>
        <div>
          <div style={{ fontFamily: T.fontD, fontSize: 17, fontWeight: 600, color: T.textHi, letterSpacing: -0.2, marginBottom: 3 }}>{route.name}</div>
          <div style={{ fontFamily: T.fontM, fontSize: 10, color: T.textMute, letterSpacing: 0.8 }}>{route.region.toUpperCase()}</div>
        </div>
        <div style={{ display: 'flex', gap: 22, alignItems: 'flex-end' }}>
          <Stat value={route.distance} unit="KM" size="m" />
          <Stat value={route.elev} unit="M GAIN" size="m" />
          <Stat value={route.time} unit="EST" size="m" />
        </div>
        <SurfaceBar parts={route.surfaces} />
        {route.reports > 0 && (
          <div style={{ fontFamily: T.fontM, fontSize: 10, color: T.signalGlow, letterSpacing: 0.8, display: 'flex', alignItems: 'center', gap: 6 }}>
            <span style={{ width: 4, height: 4, background: T.signalGlow, borderRadius: 2 }} />
            {route.reports} RECENT REPORT{route.reports > 1 ? 'S' : ''} · {route.diff}
          </div>
        )}
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// EXPLORE SCREEN
// ────────────────────────────────────────────────────────────
function ExploreScreen({ onOpenRoute, onNavigate }) {
  const [activeAct, setActiveAct] = React.useState('all');
  const acts = [
    { k: 'all', label: 'All', icon: null },
    { k: 'moto', label: 'Moto' },
    { k: 'hike', label: 'Hike' },
    { k: 'gravel', label: 'Gravel' },
    { k: 'mtb', label: 'MTB' },
    { k: '4x4', label: '4×4' },
    { k: 'run', label: 'Trail run' },
    { k: 'dog', label: 'Dog' },
  ];
  const filtered = activeAct === 'all' ? ROUTES : ROUTES.filter(r => r.activity === activeAct);

  return (
    <div style={{ background: T.bg, paddingBottom: 100 }}>
      {/* Header */}
      <div style={{ padding: '18px 18px 14px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 18 }}>
          <div>
            <div style={{ fontFamily: T.fontM, fontSize: 10, color: T.textMute, letterSpacing: 1.6, marginBottom: 2 }}>SHEFFIELD · UK</div>
            <div style={{ fontFamily: T.fontD, fontSize: 22, fontWeight: 600, color: T.textHi, letterSpacing: -0.3 }}>Good morning.</div>
          </div>
          <IconBtn size={38} onClick={() => onNavigate('profile')} label="profile">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4">
              <circle cx="8" cy="6" r="2.5"/><path d="M3 14 Q 8 9 13 14"/>
            </svg>
          </IconBtn>
        </div>

        {/* Search w/ AI hint */}
        <div onClick={() => onNavigate('ai')} style={{
          display: 'flex', alignItems: 'center', gap: 10,
          background: T.card, border: `1px solid ${T.border}`,
          padding: '12px 14px', cursor: 'pointer',
        }}>
          <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke={T.textMute} strokeWidth="1.5">
            <circle cx="7" cy="7" r="4.5"/><path d="M10.5 10.5 L14 14"/>
          </svg>
          <span style={{ flex: 1, fontFamily: T.fontB, fontSize: 14, color: T.textLo }}>Find a route, or ask…</span>
          <span style={{
            fontFamily: T.fontM, fontSize: 9, color: T.signalGlow,
            background: 'rgba(226,94,31,0.12)', padding: '3px 6px',
            border: `1px solid ${T.signalDeep}`, letterSpacing: 1,
          }}>AI</span>
        </div>

        {/* Weather strip */}
        <div style={{ marginTop: 12, display: 'flex', gap: 8, fontFamily: T.fontM, fontSize: 10, color: T.textLo, letterSpacing: 0.5 }}>
          <span style={{ color: T.textHi }}>● 11°C OVERCAST</span>
          <span>·</span>
          <span>WIND 18 KM/H SW</span>
          <span>·</span>
          <span style={{ color: T.amber }}>RAIN 60% PM</span>
        </div>
      </div>

      {/* Activity chips */}
      <div style={{ padding: '4px 0 16px', overflowX: 'auto', whiteSpace: 'nowrap' }}>
        <div style={{ display: 'inline-flex', gap: 6, padding: '0 18px' }}>
          {acts.map(a => (
            <Chip key={a.k} active={activeAct === a.k} onClick={() => setActiveAct(a.k)}
              icon={a.k !== 'all' ? <ActIcon kind={a.k} size={12} /> : null}>
              {a.label}
            </Chip>
          ))}
        </div>
      </div>

      {/* Featured: AI route of the day */}
      <SectionHead kicker="§ AI PICK" title="For your big-ADV bike today" />
      <div style={{ padding: '0 18px', marginBottom: 24 }}>
        <button onClick={() => onOpenRoute(ROUTES[0])} style={{
          background: T.card, border: `1px solid ${T.border}`, borderLeft: `3px solid ${T.signal}`,
          padding: 0, width: '100%', textAlign: 'left', cursor: 'pointer', overflow: 'hidden',
        }}>
          <div style={{ position: 'relative', height: 160 }}>
            <MapMock height={160} dense routePath={ROUTES[0].routePath}
              pins={[
                { x: 45, y: 165, label: 'R' },
                { x: 200, y: 100, color: '#0E110D', size: 5 },
                { x: 370, y: 75, color: T.signal, size: 6 },
              ]}
              showLabels />
          </div>
          <div style={{ padding: '14px 16px 16px' }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 10 }}>
              <div>
                <div style={{ fontFamily: T.fontD, fontSize: 18, fontWeight: 600, color: T.textHi, letterSpacing: -0.3, marginBottom: 2 }}>{ROUTES[0].name}</div>
                <div style={{ fontFamily: T.fontM, fontSize: 10, color: T.textMute, letterSpacing: 1 }}>{ROUTES[0].region.toUpperCase()}</div>
              </div>
              <ConfBadge level="high" days={8} />
            </div>
            <div style={{
              fontFamily: T.fontB, fontSize: 13, color: T.textMid, lineHeight: 1.5,
              padding: '10px 12px', background: T.bg, border: `1px solid ${T.border}`,
            }}>
              <span style={{ fontFamily: T.fontM, fontSize: 9, color: T.signalGlow, letterSpacing: 1.5, marginRight: 6 }}>AI:</span>
              Mostly dry surface this week. Two manageable rocky sections suit a big ADV bike — soft tyres recommended. No known restriction in our data.
            </div>
          </div>
        </button>
      </div>

      {/* Nearby */}
      <SectionHead kicker="§ NEARBY · 12 KM" title="Routes near you" action="MAP" onAction={() => onNavigate('map')} />
      <div style={{ padding: '0 18px 24px', display: 'flex', flexDirection: 'column', gap: 14 }}>
        {filtered.map(r => <RouteCard key={r.id} route={r} onClick={() => onOpenRoute(r)} />)}
      </div>

      {/* Community feed */}
      <SectionHead kicker="§ COMMUNITY" title="Recent ground reports" action="ALL" />
      <div style={{ padding: '0 18px 24px', display: 'flex', flexDirection: 'column', gap: 8 }}>
        {[
          { who: 'Tom R.', when: '2h', type: 'GATE', color: T.amber, body: 'Locked gate at northern end of Stanage Causeway. Walk-around possible on the west side.', route: 'Stanage North Loop' },
          { who: 'Sarah K.', when: '14h', type: 'TRO', color: T.rust, body: 'New TRO sign posted on byway near Glossop. Council notice attached.', route: 'Glossop UCR Network' },
          { who: 'James M.', when: '1d', type: 'OK', color: T.lichen, body: 'Rode it yesterday in light rain — surface holding up well. Watch for the ford at km 7.', route: 'Roych Clough Byway' },
        ].map((r, i) => (
          <div key={i} style={{ background: T.card, border: `1px solid ${T.border}`, padding: 14, display: 'flex', gap: 12 }}>
            <div style={{
              fontFamily: T.fontM, fontSize: 9, color: r.color,
              border: `1px solid ${r.color}`, padding: '2px 6px', height: 'fit-content', letterSpacing: 1,
            }}>{r.type}</div>
            <div style={{ flex: 1 }}>
              <div style={{ fontFamily: T.fontB, fontSize: 13, color: T.text, lineHeight: 1.4, marginBottom: 6 }}>{r.body}</div>
              <div style={{ fontFamily: T.fontM, fontSize: 9, color: T.textMute, letterSpacing: 0.8 }}>{r.who.toUpperCase()} · {r.when.toUpperCase()} · {r.route.toUpperCase()}</div>
            </div>
          </div>
        ))}
      </div>

      {/* Premium teaser */}
      <div style={{ padding: '0 18px 24px' }}>
        <button onClick={() => onNavigate('upgrade')} style={{
          width: '100%', textAlign: 'left', padding: '18px 16px',
          background: T.cardElev, border: `1px solid ${T.border}`,
          borderLeft: `3px solid ${T.signal}`,
          cursor: 'pointer', display: 'flex', flexDirection: 'column', gap: 8,
        }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <span style={{
              fontFamily: T.fontM, fontSize: 9, color: T.signal, letterSpacing: 1.5,
              border: `1px solid ${T.signalDeep}`, padding: '2px 6px',
            }}>PREMIUM</span>
            <span style={{ fontFamily: T.fontM, fontSize: 10, color: T.textMute, letterSpacing: 0.8 }}>14-DAY TRIAL</span>
          </div>
          <div style={{ fontFamily: T.fontD, fontSize: 17, fontWeight: 600, color: T.textHi, letterSpacing: -0.2 }}>Offline packs, TRO alerts, AI route builder.</div>
          <div style={{ fontFamily: T.fontM, fontSize: 11, color: T.signalGlow, letterSpacing: 0.5 }}>£4.99/mo · UNLOCK →</div>
        </button>
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// MAP SCREEN
// ────────────────────────────────────────────────────────────
function MapScreen({ onOpenRoute }) {
  const [sel, setSel] = React.useState(ROUTES[0]);
  const [layers, setLayers] = React.useState(false);
  const [config, setConfig] = React.useState(window.ROAMR_CONFIG);
  const [query, setQuery] = React.useState('Peak District');
  const [routeStatus, setRouteStatus] = React.useState('');
  const [routeError, setRouteError] = React.useState('');
  const [liveRoute, setLiveRoute] = React.useState(null);
  const [saveStatus, setSaveStatus] = React.useState('');

  React.useEffect(() => {
    window.ROAMR_CONFIG_READY?.then(setConfig);
    const onConfig = (event) => setConfig(event.detail);
    window.addEventListener('roamr:config', onConfig);
    return () => window.removeEventListener('roamr:config', onConfig);
  }, []);

  const mapTilerReady = config?.maps?.provider === 'maptiler' && config?.maps?.mapTilerKey;
  const liveTiles = mapTilerReady ? window.ROAMR_MAP.peakDistrictTiles() : [];
  const profile = sel.activity === 'hike' ? 'foot-walking' : sel.activity === 'moto' ? 'driving-car' : 'cycling-regular';

  const minutesToLabel = (minutes) => {
    if (!minutes && minutes !== 0) return sel.time;
    const h = Math.floor(minutes / 60);
    const m = minutes % 60;
    return h ? `${h}h ${String(m).padStart(2, '0')}m` : `${m}m`;
  };

  const searchRoute = async () => {
    const text = query.trim();
    if (text.length < 2) {
      setRouteError('Enter a place or area first.');
      return;
    }
    setRouteError('');
    setRouteStatus('Searching OpenRouteService…');
    try {
      const geo = await window.ROAMR_API.geocode(text);
      const destination = geo.results?.[0];
      if (!destination?.coordinates) throw new Error('No matching place found.');
      setRouteStatus('Building route…');
      const data = await window.ROAMR_API.route([-1.817, 53.349], destination.coordinates, profile);
      const route = data.route || {};
      const nextRoute = {
        ...sel,
        id: `live-${Date.now()}`,
        name: `${text} route draft`,
        region: destination.label,
        distance: String(route.distanceKm || sel.distance),
        elev: route.ascentM ? `+${Math.round(route.ascentM)}` : sel.elev,
        time: minutesToLabel(route.durationMinutes),
        conf: 'med',
        confDays: 0,
        reports: 0,
        tags: ['OpenRouteService', 'Draft'],
      };
      setLiveRoute(route);
      setSel(nextRoute);
      setRouteStatus(`Live route from OpenRouteService · ${data.provider}`);
    } catch (err) {
      setRouteError(err.message || 'Route search failed.');
      setRouteStatus('');
    }
  };
  const saveSelectedRoute = async () => {
    setSaveStatus('Saving…');
    try {
      await window.ROAMR_API.saveRoute(sel);
      setSaveStatus('Saved to Supabase');
    } catch (err) {
      setSaveStatus(err.message || 'Sign in to save routes.');
    }
  };

  return (
    <div style={{ position: 'relative', height: '100%', background: T.bgDeep }}>
      {/* Big map */}
      <div style={{ position: 'absolute', inset: 0 }}>
        {mapTilerReady && (
          <div style={{ position: 'absolute', inset: 0, display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gridTemplateRows: 'repeat(3, 1fr)', opacity: 0.86, filter: 'saturate(0.86) contrast(0.95)' }}>
            {liveTiles.map(tile => (
              <img key={`${tile.z}-${tile.x}-${tile.y}`} src={tile.url} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
            ))}
          </div>
        )}
        <svg viewBox="0 0 400 800" preserveAspectRatio="xMidYMid slice"
          style={{ width: '100%', height: '100%', display: 'block', position: 'relative', opacity: mapTilerReady ? 0.72 : 1 }}>
          <defs>
            <pattern id="grid-map" width="40" height="40" patternUnits="userSpaceOnUse">
              <path d="M40 0 L0 0 L0 40" fill="none" stroke="#1c211a" strokeWidth="0.5"/>
            </pattern>
          </defs>
          <rect width="400" height="800" fill="url(#grid-map)" />
          <g stroke="#2a2f27" strokeWidth="0.7" fill="none">
            {[100,140,180,220,260,300,340,380,420,460,500,540,580,620].map(y => (
              <path key={y} d={`M0 ${y} Q 80 ${y-20} 160 ${y-10} T 320 ${y-5} T 400 ${y+10}`} />
            ))}
          </g>
          <path d="M0 480 Q 100 510 200 490 T 400 480" stroke="#6E92B0" strokeWidth="1.5" fill="none" opacity="0.6"/>
          {/* multiple routes */}
          <path d="M60 600 Q 110 540 160 510 Q 220 470 280 480 Q 340 490 380 460" stroke="#E25E1F" strokeWidth="3" fill="none" opacity="0.9"/>
          {liveRoute && <path d="M70 610 Q 125 560 165 505 Q 225 445 288 470 Q 340 492 370 430" stroke="#F2EDE2" strokeWidth="2.4" fill="none" strokeDasharray="8 6" opacity="0.95"/>}
          <path d="M100 200 Q 160 240 200 280 Q 240 320 280 290 L 340 270" stroke="#E25E1F" strokeWidth="2" fill="none" opacity="0.5"/>
          <path d="M40 350 Q 100 380 140 360 L 200 340" stroke="#E25E1F" strokeWidth="2" fill="none" opacity="0.5"/>
          {/* pins */}
          <g transform="translate(60,600)"><circle r="10" fill="#E25E1F" stroke="#F2EDE2" strokeWidth="2"/><text y="3" textAnchor="middle" fontFamily="JetBrains Mono" fontSize="10" fontWeight="700" fill="#fff">R</text></g>
          <g transform="translate(100,200)"><circle r="9" fill="#0E110D" stroke="#F2EDE2" strokeWidth="2"/></g>
          <g transform="translate(40,350)"><circle r="9" fill="#0E110D" stroke="#F2EDE2" strokeWidth="2"/></g>
          <g transform="translate(280,480)"><circle r="9" fill="#F2B33B" stroke="#F2EDE2" strokeWidth="2"/><text y="3" textAnchor="middle" fontFamily="JetBrains Mono" fontSize="10" fontWeight="700" fill="#0E110D">!</text></g>
          <g transform="translate(280,290)"><circle r="6" fill="#0E110D" stroke="#F2EDE2" strokeWidth="1.5"/></g>
          {/* user location */}
          <g transform="translate(200,420)">
            <circle r="14" fill="#E25E1F" opacity="0.18"/>
            <circle r="6" fill="#E25E1F" stroke="#F2EDE2" strokeWidth="2"/>
          </g>
          <text x="14" y="22" fontFamily="JetBrains Mono" fontSize="9" fill="#797F72" letterSpacing="1.2">53.1424°N · 1.9789°W · 1:25K</text>
        </svg>
        <div style={{
          position: 'absolute', left: 14, bottom: 180,
          background: 'rgba(14,17,13,0.82)', border: `1px solid ${T.border}`,
          color: mapTilerReady ? T.lichen : T.amber,
          fontFamily: T.fontM, fontSize: 9, letterSpacing: 1.2,
          padding: '6px 8px',
        }}>
          {mapTilerReady ? 'MAPTILER LIVE TILES' : 'PLACEHOLDER MAP · ADD MAPTILER KEY'}
        </div>
      </div>

      {/* Top controls */}
      <div style={{ position: 'absolute', top: 12, left: 12, right: 12, display: 'flex', gap: 8 }}>
        <div style={{
          flex: 1, display: 'flex', alignItems: 'center', gap: 8,
          background: 'rgba(14,17,13,0.92)', backdropFilter: 'blur(8px)',
          border: `1px solid ${T.border}`, padding: '10px 12px',
        }}>
          <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke={T.textMute} strokeWidth="1.5">
            <circle cx="7" cy="7" r="4.5"/><path d="M10.5 10.5 L14 14"/>
          </svg>
          <input value={query} onChange={e => setQuery(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') searchRoute(); }}
            aria-label="Search destination"
            placeholder="Search this area…"
            style={{
              flex: 1, minWidth: 0, background: 'transparent', border: 'none', outline: 'none',
              fontFamily: T.fontB, fontSize: 13, color: T.textHi,
            }} />
        </div>
        <IconBtn onClick={searchRoute} label="route search">
          <svg width="15" height="15" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4">
            <path d="M3 13 C 5 9 11 8 13 3"/><path d="M10 3 L13 3 L13 6"/>
          </svg>
        </IconBtn>
        <IconBtn onClick={() => setLayers(!layers)} active={layers} label="layers">
          <svg width="15" height="15" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4">
            <path d="M8 2 L14 6 L8 10 L2 6 Z"/><path d="M2 10 L8 14 L14 10"/>
          </svg>
        </IconBtn>
      </div>

      {/* Layers panel */}
      {layers && (
        <div style={{
          position: 'absolute', top: 60, right: 12,
          background: 'rgba(14,17,13,0.96)', backdropFilter: 'blur(8px)',
          border: `1px solid ${T.border}`, padding: 14, width: 220,
          display: 'flex', flexDirection: 'column', gap: 10,
        }}>
          <div style={{ fontFamily: T.fontM, fontSize: 10, color: T.textMute, letterSpacing: 1.5, marginBottom: 4 }}>MAP LAYERS</div>
          {[
            { k: 'BOAT byways', on: true, c: T.signal },
            { k: 'UCR network', on: true, c: T.signal },
            { k: 'ORPA candidate', on: false, c: T.amber },
            { k: 'TRO/closures', on: true, c: T.rust },
            { k: 'Recent reports', on: true, c: T.signalGlow },
            { k: 'Contour lines', on: true, c: T.textMute },
          ].map(l => (
            <div key={l.k} style={{ display: 'flex', alignItems: 'center', gap: 10, fontFamily: T.fontB, fontSize: 13, color: T.text }}>
              <span style={{ width: 10, height: 10, background: l.on ? l.c : 'transparent', border: `1px solid ${l.c}` }} />
              {l.k}
            </div>
          ))}
        </div>
      )}

      {/* Bottom sheet with selected route */}
      <div style={{
        position: 'absolute', left: 0, right: 0, bottom: 0,
        background: T.bg, borderTop: `1px solid ${T.border}`,
        padding: '14px 16px 20px',
      }}>
        <div style={{ width: 36, height: 3, background: T.borderSoft, margin: '0 auto 14px' }} />
        {(routeStatus || routeError || saveStatus) && (
          <div style={{
            marginBottom: 10, fontFamily: T.fontM, fontSize: 9, letterSpacing: 1.1,
            color: routeError || saveStatus?.includes('Sign in') || saveStatus?.includes('failed') ? T.amber : T.lichen,
          }}>
            {routeError || saveStatus || routeStatus}
          </div>
        )}
        <button onClick={() => onOpenRoute(sel)} style={{
          background: 'transparent', border: 'none', padding: 0, width: '100%', textAlign: 'left', cursor: 'pointer',
        }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 12 }}>
            <div>
              <div style={{ fontFamily: T.fontM, fontSize: 9, color: T.textMute, letterSpacing: 1.5, marginBottom: 4 }}>{sel.region.toUpperCase()}</div>
              <div style={{ fontFamily: T.fontD, fontSize: 18, fontWeight: 600, color: T.textHi, letterSpacing: -0.2 }}>{sel.name}</div>
            </div>
            <ConfBadge level={sel.conf} days={sel.confDays} />
          </div>
          <div style={{ display: 'flex', gap: 22, marginBottom: 12 }}>
            <Stat value={sel.distance} unit="KM" />
            <Stat value={sel.elev} unit="M GAIN" />
            <Stat value={sel.time} unit="EST" />
            <Stat value={sel.diff.slice(0,3)} unit="DIFF" />
          </div>
          <SurfaceBar parts={sel.surfaces} />
          {liveRoute?.geometry && (
            <div style={{ marginTop: 10, fontFamily: T.fontM, fontSize: 9, color: T.textMute, letterSpacing: 1 }}>
              LIVE GEOMETRY · {liveRoute.geometry.type?.toUpperCase()} · OPENROUTESERVICE
            </div>
          )}
        </button>
        <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
          <button onClick={() => onOpenRoute(sel)} style={{
            flex: 1, background: T.signal, color: '#fff', border: 'none',
            padding: '12px', fontFamily: T.fontB, fontWeight: 500, fontSize: 14, cursor: 'pointer',
          }}>View route</button>
          <button onClick={saveSelectedRoute} style={{
            background: T.card, color: T.textHi, border: `1px solid ${T.borderSoft}`,
            padding: '12px 18px', fontFamily: T.fontB, fontWeight: 500, fontSize: 14, cursor: 'pointer',
          }}>Save</button>
        </div>
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// ROUTE DETAIL SCREEN
// ────────────────────────────────────────────────────────────
function RouteDetailScreen({ route, onBack, onStartNav }) {
  const r = route || ROUTES[0];
  const [reportOpen, setReportOpen] = React.useState(false);
  const [reportNote, setReportNote] = React.useState('');
  const [reportStatus, setReportStatus] = React.useState('');
  const [saveStatus, setSaveStatus] = React.useState('');
  const gpxFilename = `${r.name.toLowerCase().replace(/[^a-z0-9]+/g, '-') || 'roamr-route'}.gpx`;
  const escapeXml = value => String(value || '').replace(/[<>&'"]/g, char => ({
    '<': '&lt;',
    '>': '&gt;',
    '&': '&amp;',
    "'": '&apos;',
    '"': '&quot;',
  }[char]));
  const downloadGpxBlob = (blob, filename = gpxFilename) => {
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = filename;
    a.click();
    URL.revokeObjectURL(url);
  };
  const fallbackGpx = () => {
    const routeName = escapeXml(r.name);
    return `<?xml version="1.0" encoding="UTF-8"?>
<gpx version="1.1" creator="ROAMR" xmlns="http://www.topografix.com/GPX/1/1">
  <metadata><name>${routeName}</name></metadata>
  <trk>
    <name>${routeName}</name>
    <trkseg>
      <trkpt lat="53.349" lon="-1.817"></trkpt>
      <trkpt lat="53.365" lon="-1.761"></trkpt>
      <trkpt lat="53.372" lon="-1.728"></trkpt>
      <trkpt lat="53.332" lon="-1.704"></trkpt>
    </trkseg>
  </trk>
</gpx>`;
  };
  const exportGpx = async () => {
    setSaveStatus('Preparing GPX…');
    try {
      const response = await fetch(`/api/routes/${encodeURIComponent(r.id)}/export-gpx`);
      if (!response.ok) throw new Error('Route GPX is not available from the API yet.');
      const header = response.headers.get('content-disposition') || '';
      const filename = header.match(/filename="([^"]+)"/)?.[1] || gpxFilename;
      downloadGpxBlob(await response.blob(), filename);
      setSaveStatus('GPX downloaded.');
    } catch (err) {
      downloadGpxBlob(new Blob([fallbackGpx()], { type: 'application/gpx+xml' }), gpxFilename);
      setSaveStatus('GPX downloaded from demo route geometry.');
    }
  };
  const saveRoute = async () => {
    setSaveStatus('Saving…');
    try {
      await window.ROAMR_API.saveRoute(r);
      setSaveStatus('Saved to Supabase');
    } catch (err) {
      setSaveStatus(err.message || 'Sign in to save routes.');
    }
  };
  const submitReport = async () => {
    if (reportNote.trim().length < 6) {
      setReportStatus('Add a short note before submitting.');
      return;
    }
    setReportStatus('Submitting…');
    try {
      await window.ROAMR_API.submitReport(r, reportNote.trim());
      setReportNote('');
      setReportOpen(false);
      setReportStatus('Report submitted for moderation');
    } catch (err) {
      setReportStatus(err.message || 'Report failed.');
    }
  };
  return (
    <div style={{ background: T.bg, paddingBottom: 100 }}>
      {/* Hero map */}
      <div style={{ position: 'relative', height: 280 }}>
        <MapMock height={280} dense showLabels routePath={r.routePath}
          pins={[
            { x: 45, y: 165, label: 'R', size: 9 },
            { x: 200, y: 100, color: '#0E110D', size: 6 },
            { x: 280, y: 90, color: T.amber, label: '!', size: 8 },
            { x: 370, y: 75, color: T.signal, size: 7 },
          ]} />
        <button onClick={onBack} style={{
          position: 'absolute', top: 12, left: 12,
          width: 40, height: 40, background: 'rgba(14,17,13,0.92)',
          backdropFilter: 'blur(8px)', border: `1px solid ${T.border}`,
          color: T.textHi, cursor: 'pointer',
        }}>←</button>
        <button aria-label="Save route" onClick={saveRoute} style={{
          position: 'absolute', top: 12, right: 12,
          width: 40, height: 40, background: 'rgba(14,17,13,0.92)',
          backdropFilter: 'blur(8px)', border: `1px solid ${T.border}`,
          color: T.textHi, cursor: 'pointer', fontSize: 16,
        }}>♡</button>
      </div>

      {/* Title block */}
      <div style={{ padding: '20px 18px 18px', borderBottom: `1px solid ${T.border}` }}>
        <div style={{ display: 'flex', gap: 6, marginBottom: 10 }}>
          <Chip sm icon={<ActIcon kind={r.activity} size={11} />}><span style={{ marginLeft: 3 }}>{r.activity.toUpperCase()}</span></Chip>
          {r.tags && r.tags.map(t => <Chip sm key={t}>{t}</Chip>)}
        </div>
        <div style={{ fontFamily: T.fontD, fontSize: 26, fontWeight: 600, color: T.textHi, letterSpacing: -0.4, lineHeight: 1.15, marginBottom: 6 }}>{r.name}</div>
        <div style={{ fontFamily: T.fontM, fontSize: 11, color: T.textMute, letterSpacing: 1.2 }}>{r.region.toUpperCase()}</div>
      </div>

      {/* Stats row */}
      <div style={{ padding: '20px 18px', borderBottom: `1px solid ${T.border}`, display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 12 }}>
        <Stat value={r.distance} unit="KM" size="l" />
        <Stat value={r.elev} unit="M GAIN" size="l" />
        <Stat value={r.time} unit="EST" size="l" />
        <Stat value={r.diff.slice(0,3)} unit="DIFF" size="l" color={T.signalGlow} />
      </div>

      {/* Actions */}
      <div style={{ padding: '14px 18px', borderBottom: `1px solid ${T.border}`, display: 'flex', gap: 8 }}>
        <button disabled title="Live navigation is disabled for this user-testing build." style={{
          flex: 1, background: T.card, color: T.textLo, border: `1px solid ${T.borderSoft}`,
          padding: '13px', fontFamily: T.fontB, fontWeight: 500, fontSize: 14, cursor: 'not-allowed',
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
        }}>
          Native navigation in beta
        </button>
        <button onClick={saveRoute} style={{ background: T.card, color: T.textHi, border: `1px solid ${T.borderSoft}`, padding: '13px 14px', fontFamily: T.fontM, fontSize: 11, cursor: 'pointer', letterSpacing: 1 }}>SAVE</button>
        <button onClick={exportGpx} style={{ background: T.card, color: T.textHi, border: `1px solid ${T.borderSoft}`, padding: '13px 14px', fontFamily: T.fontM, fontSize: 11, cursor: 'pointer', letterSpacing: 1 }}>GPX</button>
        <button disabled title="Offline downloads are hidden until real offline packs are ready." style={{ background: T.card, color: T.textMute, border: `1px solid ${T.borderSoft}`, padding: '13px 14px', fontFamily: T.fontM, fontSize: 11, cursor: 'not-allowed', letterSpacing: 1 }}>OFFLINE</button>
      </div>
      <div style={{ padding: '10px 18px 14px', fontFamily: T.fontB, fontSize: 12, color: T.textLo, lineHeight: 1.45 }}>
        Live turn-by-turn and offline packs are disabled for this user-testing build.
      </div>
      {saveStatus && <div style={{ padding: '0 18px 14px', fontFamily: T.fontM, fontSize: 10, color: saveStatus.includes('Saved') ? T.lichen : T.amber, letterSpacing: 0.8 }}>{saveStatus}</div>}

      {/* Access confidence panel */}
      <div style={{ padding: '20px 18px', borderBottom: `1px solid ${T.border}` }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 14 }}>
          <div style={{ fontFamily: T.fontM, fontSize: 10, color: T.signal, letterSpacing: 1.5 }}>§ ACCESS CONFIDENCE</div>
          <ConfBadge level={r.conf} days={r.confDays} />
        </div>
        <div style={{ background: T.card, border: `1px solid ${T.border}`, padding: 14, display: 'flex', flexDirection: 'column', gap: 10 }}>
          {[
            { label: 'Designated BOAT', src: 'Derbyshire CC · ROW Map · 2024', status: 'ok' },
            { label: 'No active TRO', src: 'DCC TRO database · checked 8d ago', status: 'ok' },
            { label: 'TRF route reference', src: 'TRF GreenRoad · 2024-Q2', status: 'ok' },
            { label: 'Seasonal advisory', src: '"Avoid Nov-Feb during wet" · TRF', status: 'warn' },
          ].map((s, i) => (
            <div key={i} style={{ display: 'flex', gap: 12, alignItems: 'flex-start' }}>
              <span style={{
                width: 14, height: 14, marginTop: 2,
                background: s.status === 'ok' ? T.lichen : T.amber,
                color: '#0E110D', display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontFamily: T.fontM, fontWeight: 700, fontSize: 10,
              }}>{s.status === 'ok' ? '✓' : '!'}</span>
              <div style={{ flex: 1 }}>
                <div style={{ fontFamily: T.fontB, fontSize: 13, color: T.textHi, fontWeight: 500 }}>{s.label}</div>
                <div style={{ fontFamily: T.fontM, fontSize: 10, color: T.textMute, letterSpacing: 0.6, marginTop: 2 }}>{s.src.toUpperCase()}</div>
              </div>
            </div>
          ))}
        </div>
        <div style={{ marginTop: 12, fontFamily: T.fontB, fontSize: 11, color: T.textLo, lineHeight: 1.5, fontStyle: 'italic' }}>
          ROAMR's access confidence is a planning aid, not legal advice. Always verify local signs and authority notices before riding.
        </div>
      </div>

      {/* Surface profile */}
      <div style={{ padding: '20px 18px', borderBottom: `1px solid ${T.border}` }}>
        <div style={{ fontFamily: T.fontM, fontSize: 10, color: T.signal, letterSpacing: 1.5, marginBottom: 12 }}>§ SURFACE PROFILE</div>
        <SurfaceBar parts={r.surfaces} showLegend />
      </div>

      {/* Elevation */}
      <div style={{ padding: '20px 18px', borderBottom: `1px solid ${T.border}` }}>
        <div style={{ fontFamily: T.fontM, fontSize: 10, color: T.signal, letterSpacing: 1.5, marginBottom: 12 }}>§ ELEVATION</div>
        <div style={{ background: T.card, border: `1px solid ${T.border}` }}>
          <ElevationGraph height={120} />
        </div>
      </div>

      {/* AI summary */}
      <div style={{ padding: '20px 18px', borderBottom: `1px solid ${T.border}` }}>
        <div style={{ fontFamily: T.fontM, fontSize: 10, color: T.signal, letterSpacing: 1.5, marginBottom: 12 }}>§ AI SUMMARY</div>
        <div style={{ background: T.card, border: `1px solid ${T.border}`, borderLeft: `3px solid ${T.signal}`, padding: 14,
          fontFamily: T.fontB, fontSize: 13, color: T.text, lineHeight: 1.55 }}>
          A classic Peak District byway with a manageable rocky descent at km 9. Surface is dry across recent reports — good for a big ADV bike on mixed tyres. The optional pub stop at the halfway point makes this a popular weekend loop. One seasonal advisory: TRF recommends avoiding Nov–Feb during prolonged wet.
          <div style={{ marginTop: 10, fontFamily: T.fontM, fontSize: 9, color: T.textMute, letterSpacing: 1 }}>GENERATED 14 MIN AGO · 12 SOURCES</div>
        </div>
      </div>

      {/* Recent reports */}
      <div style={{ padding: '20px 18px', borderBottom: `1px solid ${T.border}` }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
          <div style={{ fontFamily: T.fontM, fontSize: 10, color: T.signal, letterSpacing: 1.5 }}>§ RECENT REPORTS · 3</div>
          <button onClick={() => setReportOpen(!reportOpen)} style={{ background: 'transparent', border: 'none', fontFamily: T.fontM, fontSize: 10, color: T.signalGlow, letterSpacing: 1, cursor: 'pointer' }}>+ REPORT</button>
        </div>
        {reportOpen && (
          <div style={{ background: T.card, border: `1px solid ${T.border}`, padding: 12, marginBottom: 10 }}>
            <textarea value={reportNote} onChange={e => setReportNote(e.target.value)} rows={3}
              placeholder="What changed on the ground?"
              style={{ width: '100%', background: T.bg, border: `1px solid ${T.borderSoft}`, color: T.textHi, padding: 10, fontFamily: T.fontB, fontSize: 13, resize: 'vertical' }} />
            <button onClick={submitReport} style={{ marginTop: 8, background: T.signal, color: '#fff', border: 'none', padding: '10px 12px', fontFamily: T.fontB, fontWeight: 600, cursor: 'pointer' }}>Submit report</button>
          </div>
        )}
        {reportStatus && <div style={{ marginBottom: 10, fontFamily: T.fontM, fontSize: 10, color: reportStatus.includes('submitted') ? T.lichen : T.amber, letterSpacing: 0.8 }}>{reportStatus}</div>}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
          {[
            { type: 'OK', color: T.lichen, body: 'Rode in light rain, surface holding up.', by: 'James M.', when: '1d' },
            { type: 'WATER', color: T.slate, body: 'Ford at km 7 deeper than usual. Crossable with care.', by: 'Tom R.', when: '4d' },
            { type: 'TREE', color: T.amber, body: 'Small fallen branch around km 11 — easy to ride past.', by: 'Sarah K.', when: '8d' },
          ].map((rp, i) => (
            <div key={i} style={{ background: T.card, border: `1px solid ${T.border}`, padding: 12, display: 'flex', gap: 10 }}>
              <div style={{ fontFamily: T.fontM, fontSize: 9, color: rp.color, border: `1px solid ${rp.color}`, padding: '2px 5px', height: 'fit-content', letterSpacing: 1 }}>{rp.type}</div>
              <div style={{ flex: 1 }}>
                <div style={{ fontFamily: T.fontB, fontSize: 13, color: T.text, lineHeight: 1.4 }}>{rp.body}</div>
                <div style={{ fontFamily: T.fontM, fontSize: 9, color: T.textMute, letterSpacing: 0.8, marginTop: 4 }}>{rp.by.toUpperCase()} · {rp.when.toUpperCase()}</div>
              </div>
            </div>
          ))}
        </div>
      </div>

      {/* Trust timeline */}
      <div style={{ padding: '20px 18px' }}>
        <div style={{ fontFamily: T.fontM, fontSize: 10, color: T.signal, letterSpacing: 1.5, marginBottom: 14 }}>§ TRUST TIMELINE</div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12, fontFamily: T.fontM, fontSize: 11, color: T.textMid, letterSpacing: 0.3 }}>
          {[
            ['Created', '2021-04-14', 'TRF Derbyshire'],
            ['Last ridden', '2026-05-23', '12 contributors this month'],
            ['Last report', '2026-05-24', 'OK — surface dry'],
            ['Moderator check', '2026-05-17', 'Verified by ROAMR'],
            ['Legal source', '2026-05-17', 'DCC ROW database'],
          ].map(([k, d, v], i) => (
            <div key={i} style={{ display: 'flex', gap: 14, alignItems: 'baseline' }}>
              <span style={{ width: 130, color: T.textMute, letterSpacing: 1 }}>{k.toUpperCase()}</span>
              <span style={{ width: 90, color: T.textHi }}>{d}</span>
              <span style={{ flex: 1, color: T.textLo, fontFamily: T.fontB, fontSize: 12 }}>{v}</span>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// SAVED SCREEN
// ────────────────────────────────────────────────────────────
function SavedScreen({ onOpenRoute, onNavigate }) {
  const previewRoutes = React.useMemo(() => ([
    { ...ROUTES[0], id: 'preview-r1', tags: ['Saved preview', 'Big-ADV friendly'] },
    { ...ROUTES[2], id: 'preview-r3', tags: ['Saved preview', 'Cafe stop'] },
    { ...ROUTES[1], id: 'preview-r2', tags: ['Saved preview', 'Circular'] },
  ]), []);
  const [routes, setRoutes] = React.useState(previewRoutes);
  const [previewMode, setPreviewMode] = React.useState(true);
  const [status, setStatus] = React.useState('Showcase preview: your saved routes will live here once beta accounts open.');

  const loadSaved = React.useCallback(async () => {
    setStatus('Loading saved routes…');
    try {
      const data = await window.ROAMR_API.savedRoutes();
      setRoutes(data.length ? data : previewRoutes);
      setPreviewMode(!data.length);
      setStatus(data.length ? '' : 'Your real saved routes will appear here. These examples show the beta library.');
    } catch (err) {
      setRoutes(previewRoutes);
      setPreviewMode(true);
      setStatus('Showcase preview: accounts are coming soon. These sample routes show how your saved library will feel.');
    }
  }, [previewRoutes]);

  React.useEffect(() => {
    loadSaved();
    window.addEventListener('roamr:saves-changed', loadSaved);
    window.addEventListener('roamr:auth', loadSaved);
    return () => {
      window.removeEventListener('roamr:saves-changed', loadSaved);
      window.removeEventListener('roamr:auth', loadSaved);
    };
  }, [loadSaved]);

  return (
    <div style={{ background: T.bg, paddingBottom: 100 }}>
      <div style={{ padding: '18px' }}>
        <button onClick={() => onNavigate && onNavigate('explore')} style={{
          background: 'transparent', border: 'none', color: T.textLo, padding: '0 0 14px',
          fontFamily: T.fontM, fontSize: 10, letterSpacing: 1.2, cursor: 'pointer',
        }}>← EXPLORE</button>
        <div style={{ fontFamily: T.fontM, fontSize: 10, color: T.textMute, letterSpacing: 1.6, marginBottom: 4 }}>§ LIBRARY</div>
        <div style={{ fontFamily: T.fontD, fontSize: 28, fontWeight: 600, color: T.textHi, letterSpacing: -0.5 }}>Saved</div>
      </div>
      <div style={{ padding: '0 18px 14px', display: 'flex', gap: 6 }}>
        {[`All · ${routes.length}`, 'Offline packs · roadmap', 'Collections · beta', 'Drafts · AI'].map((t, i) => <Chip key={i} active={i === 0}>{t}</Chip>)}
      </div>

      <SectionHead kicker="§ SAVED ROUTES" title={previewMode ? 'Saved route preview' : 'Your library'} />
      <div style={{ padding: '0 18px', display: 'flex', flexDirection: 'column', gap: 14 }}>
        {status && <div style={{ background: T.card, border: `1px solid ${T.border}`, padding: 14, fontFamily: T.fontB, color: T.textLo, fontSize: 13 }}>{status}</div>}
        {routes.map(r => (
          <div key={r.id} style={{ position: 'relative' }}>
            <RouteCard route={r} onClick={() => onOpenRoute(r)} compact />
            {previewMode ? (
              <span style={{ position: 'absolute', top: 8, right: 8, background: T.bg, color: T.signalGlow, border: `1px solid ${T.signalDeep}`, padding: '6px 8px', fontFamily: T.fontM, fontSize: 9 }}>PREVIEW</span>
            ) : (
              <button onClick={async () => {
                setStatus('Removing saved route…');
                try {
                  await window.ROAMR_API.unsaveRoute(r.id);
                  await loadSaved();
                } catch (err) {
                  setStatus(err.message || 'Could not remove saved route.');
                }
              }} style={{ position: 'absolute', top: 8, right: 8, background: T.bg, color: T.textLo, border: `1px solid ${T.borderSoft}`, padding: '6px 8px', fontFamily: T.fontM, fontSize: 9, cursor: 'pointer' }}>REMOVE</button>
            )}
          </div>
        ))}
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// PROFILE SCREEN
// ────────────────────────────────────────────────────────────
function ProfileScreen({ onNavigate }) {
  const [user, setUser] = React.useState(window.ROAMR_STATE?.user || null);
  const [profile, setProfile] = React.useState(window.ROAMR_STATE?.profile || null);
  const [email, setEmail] = React.useState('');
  const [password, setPassword] = React.useState('');
  const [status, setStatus] = React.useState('Checking session…');
  const [authBusy, setAuthBusy] = React.useState(false);
  const [notifyEmail, setNotifyEmail] = React.useState('');

  const refreshProfile = React.useCallback(async () => {
    try {
      await window.ROAMR_AUTH_READY;
      if (window.ROAMR_AUTH_ERROR) {
        setStatus(`Sign-in was not completed: ${window.ROAMR_AUTH_ERROR}`);
        return;
      }
      setUser(window.ROAMR_STATE.user);
      if (window.ROAMR_STATE.user) {
        const nextProfile = await window.ROAMR_API.profile();
        setProfile(nextProfile);
        setStatus('');
      } else {
        setStatus('Sign in to save routes, submit reports and keep your ROAMR profile across devices.');
      }
    } catch (err) {
      setStatus(err.message || 'Auth unavailable.');
    }
  }, []);

  React.useEffect(() => {
    refreshProfile();
    const onAuth = () => refreshProfile();
    window.addEventListener('roamr:auth', onAuth);
    return () => window.removeEventListener('roamr:auth', onAuth);
  }, [refreshProfile]);

  const submitAuth = async (mode) => {
    if (authBusy) return;
    if (!email.includes('@') || password.length < 6) {
      setStatus('Use a valid email and at least 6 password characters.');
      return;
    }
    window.ROAMR_AUTH_ERROR = '';
    setStatus(mode === 'signup' ? 'Creating account…' : 'Signing in…');
    setAuthBusy(true);
    try {
      if (mode === 'signup') {
        const result = await window.ROAMR_API.signUp(email, password);
        if (result.session) {
          await refreshProfile();
          setStatus('Account created and signed in.');
        } else {
          setStatus('Account created. Check your email if confirmation is required, then sign in.');
        }
      } else {
        await window.ROAMR_API.signIn(email, password);
        await refreshProfile();
        setStatus('Signed in.');
      }
    } catch (err) {
      setStatus(err.message || 'Auth failed.');
    } finally {
      setAuthBusy(false);
    }
  };

  const providerSignIn = async (provider) => {
    if (authBusy) return;
    const label = provider === 'google' ? 'Google' : 'Apple';
    window.ROAMR_AUTH_ERROR = '';
    setStatus(`Redirecting to ${label}…`);
    setAuthBusy(true);
    try {
      await window.ROAMR_API.signInWithProvider(provider);
    } catch (err) {
      setStatus(err.message || `${label} sign-in is not available yet.`);
      setAuthBusy(false);
    }
  };

  const resetPassword = async () => {
    const nextEmail = email.trim().toLowerCase();
    if (authBusy) return;
    if (!nextEmail.includes('@') || nextEmail.length < 5) {
      setStatus('Enter your email first, then tap Reset password.');
      return;
    }
    setStatus('Sending password reset…');
    setAuthBusy(true);
    try {
      await window.ROAMR_API.resetPassword(nextEmail);
      setStatus('Password reset email sent. Check your inbox.');
    } catch (err) {
      setStatus(err.message || 'Password reset is not available yet.');
    } finally {
      setAuthBusy(false);
    }
  };

  const signOut = async () => {
    if (authBusy) return;
    setStatus('Signing out…');
    setAuthBusy(true);
    try {
      await window.ROAMR_API.signOut();
      setProfile(null);
      setUser(null);
      setStatus('Signed out.');
    } catch (err) {
      setStatus(err.message || 'Sign out failed.');
    } finally {
      setAuthBusy(false);
    }
  };

  const joinWaitlist = () => {
    const nextEmail = notifyEmail.trim().toLowerCase();
    if (!nextEmail.includes('@') || nextEmail.length < 5) {
      setStatus('Add a valid email to get notified.');
      return;
    }
    try {
      const existing = JSON.parse(localStorage.getItem('roamrAppBetaEmails') || '[]');
      const emails = Array.from(new Set([...existing, nextEmail]));
      localStorage.setItem('roamrAppBetaEmails', JSON.stringify(emails));
    } catch (err) {
      // Local beta capture is best-effort so the public showcase never blocks.
    }
    setNotifyEmail('');
    setStatus("You're on the beta list. We'll let you know when wider access opens.");
  };

  const displayEmail = profile?.email || user?.email || 'Showcase visitor';
  const initials = displayEmail?.[0]?.toUpperCase() || 'R';

  return (
    <div style={{ background: T.bg, paddingBottom: 100 }}>
      <div style={{ padding: '24px 18px 20px' }}>
        <button onClick={() => onNavigate && onNavigate('explore')} style={{
          background: 'transparent', border: 'none', color: T.textLo, padding: '0 0 16px',
          fontFamily: T.fontM, fontSize: 10, letterSpacing: 1.2, cursor: 'pointer',
        }}>← EXPLORE</button>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 18 }}>
          <div style={{
            width: 56, height: 56, background: T.signal,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontFamily: T.fontD, fontSize: 22, fontWeight: 600, color: '#fff',
          }}>{initials}</div>
          <div>
            <div style={{ fontFamily: T.fontD, fontSize: 20, fontWeight: 600, color: T.textHi, letterSpacing: -0.3 }}>{profile?.display_name || displayEmail}</div>
            <div style={{ fontFamily: T.fontM, fontSize: 10, color: T.textMute, letterSpacing: 1.2, marginTop: 4 }}>{user ? `SIGNED IN · ${profile?.role || 'USER'}` : 'PUBLIC SHOWCASE MODE'}</div>
          </div>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 14, padding: 16, background: T.card, border: `1px solid ${T.border}` }}>
          <Stat value="42" unit="ROUTES" />
          <Stat value="318" unit="KM YTD" />
          <Stat value="8" unit="REPORTS" />
        </div>
      </div>

      <div style={{ padding: '0 18px 16px' }}>
        <div style={{ background: T.card, border: `1px solid ${T.border}`, padding: 14, display: 'flex', flexDirection: 'column', gap: 10 }}>
          {!user && (
            <>
              <div>
                <div style={{ fontFamily: T.fontM, fontSize: 10, color: T.signal, letterSpacing: 1.5, marginBottom: 6 }}>BETA SIGN-IN</div>
                <div style={{ fontFamily: T.fontD, fontSize: 20, fontWeight: 600, color: T.textHi, letterSpacing: -0.2, marginBottom: 6 }}>Sign in or create an account</div>
                <div style={{ fontFamily: T.fontB, fontSize: 13, color: T.textLo, lineHeight: 1.5 }}>
                  Save routes, submit ground reports and keep your profile ready for the closed beta.
                </div>
              </div>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr', gap: 8 }}>
                <input value={email} onChange={e => setEmail(e.target.value)} placeholder="you@example.com" autoComplete="email" inputMode="email" style={{ background: T.bg, border: `1px solid ${T.borderSoft}`, color: T.textHi, padding: 12, fontFamily: T.fontB, fontSize: 14 }} />
                <input value={password} onChange={e => setPassword(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') submitAuth('signin'); }} placeholder="Password" type="password" autoComplete="current-password" style={{ background: T.bg, border: `1px solid ${T.borderSoft}`, color: T.textHi, padding: 12, fontFamily: T.fontB, fontSize: 14 }} />
                <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
                  <button disabled={authBusy} onClick={() => submitAuth('signin')} style={{ background: T.signal, color: '#fff', border: 'none', padding: 12, fontFamily: T.fontB, fontWeight: 600, cursor: authBusy ? 'wait' : 'pointer', opacity: authBusy ? 0.75 : 1 }}>Sign in</button>
                  <button disabled={authBusy} onClick={() => submitAuth('signup')} style={{ background: T.bg, color: T.textHi, border: `1px solid ${T.borderSoft}`, padding: 12, fontFamily: T.fontB, fontWeight: 600, cursor: authBusy ? 'wait' : 'pointer', opacity: authBusy ? 0.75 : 1 }}>Create account</button>
                </div>
                <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
                  <button disabled={authBusy} onClick={() => providerSignIn('google')} style={{ background: T.cardElev, color: T.textHi, border: `1px solid ${T.borderSoft}`, padding: 12, fontFamily: T.fontB, fontWeight: 600, cursor: authBusy ? 'wait' : 'pointer', opacity: authBusy ? 0.75 : 1 }}>Google</button>
                  <button disabled={authBusy} onClick={() => providerSignIn('apple')} style={{ background: T.cardElev, color: T.textHi, border: `1px solid ${T.borderSoft}`, padding: 12, fontFamily: T.fontB, fontWeight: 600, cursor: authBusy ? 'wait' : 'pointer', opacity: authBusy ? 0.75 : 1 }}>Apple</button>
                </div>
                <button disabled={authBusy} onClick={resetPassword} style={{ background: 'transparent', color: T.textLo, border: `1px dashed ${T.borderSoft}`, padding: 11, fontFamily: T.fontB, fontWeight: 600, cursor: authBusy ? 'wait' : 'pointer', opacity: authBusy ? 0.75 : 1 }}>Reset password</button>
              </div>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr', gap: 8, borderTop: `1px solid ${T.borderSoft}`, paddingTop: 10 }}>
                <div style={{ fontFamily: T.fontB, fontSize: 12, color: T.textMute, lineHeight: 1.45 }}>Not ready to create an account?</div>
                <input value={notifyEmail} onChange={e => setNotifyEmail(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') joinWaitlist(); }} placeholder="Get notified email" autoComplete="email" inputMode="email" style={{ background: T.bg, border: `1px solid ${T.borderSoft}`, color: T.textHi, padding: 12, fontFamily: T.fontB, fontSize: 14 }} />
                <button disabled={authBusy} onClick={joinWaitlist} style={{ background: T.bg, color: T.textHi, border: `1px solid ${T.borderSoft}`, padding: 12, fontFamily: T.fontB, fontWeight: 600, cursor: authBusy ? 'wait' : 'pointer', opacity: authBusy ? 0.75 : 1 }}>Get notified</button>
              </div>
              <button onClick={() => onNavigate('explore')} style={{ background: T.bg, color: T.textHi, border: `1px solid ${T.borderSoft}`, padding: 12, fontFamily: T.fontB, fontWeight: 600, cursor: 'pointer' }}>Browse the showcase</button>
            </>
          )}
          {user && (
            <>
              {['owner', 'admin', 'moderator'].includes(profile?.role) && (
                <button disabled={authBusy} onClick={() => { window.location.href = '/admin/roamr'; }} style={{ background: T.cardElev, color: T.textHi, border: `1px solid ${T.borderSoft}`, padding: 12, fontFamily: T.fontB, fontWeight: 600, cursor: authBusy ? 'wait' : 'pointer', opacity: authBusy ? 0.75 : 1 }}>Open admin moderation</button>
              )}
              <button disabled={authBusy} onClick={signOut} style={{ background: T.signal, color: '#fff', border: 'none', padding: 12, fontFamily: T.fontB, fontWeight: 600, cursor: authBusy ? 'wait' : 'pointer', opacity: authBusy ? 0.75 : 1 }}>Sign out</button>
            </>
          )}
          {status && <div style={{ fontFamily: T.fontM, fontSize: 10, color: status.includes('Signed') || status.includes('list') || status === '' ? T.lichen : T.textLo, letterSpacing: 0.8 }}>{status}</div>}
        </div>
      </div>

      <div style={{ padding: '0 18px 16px' }}>
        <button disabled title="Stripe checkout is disabled for user testing." onClick={() => onNavigate('upgrade')} style={{
          width: '100%', textAlign: 'left',
          background: T.cardElev, border: `1px solid ${T.signalDeep}`, borderLeft: `3px solid ${T.signal}`,
          padding: '16px', cursor: 'not-allowed', display: 'flex', alignItems: 'center', gap: 12, opacity: 0.78,
        }}>
          <div style={{ flex: 1 }}>
            <div style={{ fontFamily: T.fontM, fontSize: 9, color: T.signal, letterSpacing: 1.5, marginBottom: 4 }}>YOUR PLAN · FREE</div>
            <div style={{ fontFamily: T.fontD, fontSize: 15, fontWeight: 600, color: T.textHi }}>Premium plans coming soon</div>
          </div>
          <span style={{ fontFamily: T.fontM, color: T.signalGlow }}>locked</span>
        </button>
      </div>

      <div style={{ padding: '0 18px' }}>
        {[
          ['§ MY ACTIVITIES', ['Adv motorbike — Big-ADV', 'Hiking', 'Gravel cycling']],
          ['§ MY BIKE', ['Triumph Tiger 900 GT', '21" front · Dual sport tyres']],
          ['§ PREFERENCES', ['Avoid deep mud', 'Avoid private-risk routes', 'Voice guidance on']],
          ['§ DEVICES', ['Apple Watch Series 10', 'Garmin Tread 2 (export)']],
          ['§ ACCOUNT', [user ? `Email · ${displayEmail}` : 'Email · sign in above', 'Subscription · Free showcase', user ? 'Sign out above' : 'Create an account or get notified above']],
        ].map(([title, items]) => (
          <div key={title} style={{ marginBottom: 24 }}>
            <div style={{ fontFamily: T.fontM, fontSize: 10, color: T.signal, letterSpacing: 1.5, marginBottom: 10 }}>{title}</div>
            <div style={{ background: T.card, border: `1px solid ${T.border}` }}>
              {items.map((it, i) => (
                <div key={i} style={{
                  padding: '14px 14px', borderTop: i > 0 ? `1px solid ${T.border}` : 'none',
                  fontFamily: T.fontB, fontSize: 14, color: T.text, display: 'flex', justifyContent: 'space-between', alignItems: 'center',
                }}>
              {it}<span style={{ color: T.textMute }}>{title === '§ ACCOUNT' ? '' : 'locked'}</span>
                </div>
              ))}
            </div>
          </div>
        ))}
        <div style={{ marginBottom: 24 }}>
          <div style={{ fontFamily: T.fontM, fontSize: 10, color: T.signal, letterSpacing: 1.5, marginBottom: 10 }}>§ SUPPORT</div>
          <div style={{ background: T.card, border: `1px solid ${T.border}`, display: 'grid', gridTemplateColumns: '1fr', gap: 0 }}>
            {[
              ['Send beta feedback', 'mailto:samcharlesfowler@gmail.com?subject=ROAMR%20beta%20feedback'],
              ['Privacy policy', '/privacy.html'],
              ['Terms of service', '/terms.html'],
            ].map(([label, href], i) => (
              <a key={label} href={href} style={{
                padding: '14px', borderTop: i > 0 ? `1px solid ${T.border}` : 'none',
                fontFamily: T.fontB, fontSize: 14, color: T.text, textDecoration: 'none',
                display: 'flex', justifyContent: 'space-between', alignItems: 'center',
              }}>
                {label}<span style={{ color: T.textMute }}>›</span>
              </a>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { ROUTES, RouteCard, ExploreScreen, MapScreen, RouteDetailScreen, SavedScreen, ProfileScreen });
