/* ============================================================
   Wayfare — Full webapp shell (post-login)
   Sidebar nav · Plan · Trips · Saved · Camera · Profile
   ============================================================ */

const { useState: shUseState, useEffect: shUseEffect, useMemo: shUseMemo } = React;

/* ----------- Sidebar icons ----------- */
const SidebarIcons = {
  plan: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" width="18" height="18"><circle cx="12" cy="12" r="9"/><path d="m9 12 2 2 4-5"/></svg>,
  trips: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" width="18" height="18"><path d="M3 7h18v12H3z"/><path d="M8 7V5a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>,
  saved: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" width="18" height="18"><path d="M5 3h14v18l-7-4-7 4z"/></svg>,
  camera: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" width="18" height="18"><path d="M3 8a2 2 0 0 1 2-2h2.5L9 4h6l1.5 2H19a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z"/><circle cx="12" cy="13" r="4"/></svg>,
  scouts: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" width="18" height="18"><path d="M12 2 4 6v6c0 5 3.5 9 8 10 4.5-1 8-5 8-10V6Z"/><path d="m9 12 2 2 4-4"/></svg>,
  requests: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" width="18" height="18"><path d="M4 6h16v10H7l-3 3z"/><path d="M9 11h6M9 8h4"/></svg>,
  profile: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" width="18" height="18"><circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0 1 16 0"/></svg>,
};

/* ----------- Sidebar ----------- */
function Sidebar({ active, onNav, session, onSignOut, open, onClose }) {
  const isScout = session.role === 'scout';
  const items = isScout
    ? [
        { k: 'requests', label: 'Requests' },
        { k: 'trips', label: 'My trips' },
      ]
    : [
        { k: 'plan', label: 'Plan a trip' },
        { k: 'trips', label: 'My trips' },
        { k: 'camera', label: 'Camera AI' },
        { k: 'scouts', label: 'Browse scouts' },
        { k: 'profile', label: 'Profile' },
      ];
  const pick = (k) => { onNav(k); onClose?.(); };
  return (
    <aside className={'app-sidebar' + (open ? ' is-open' : '')} aria-label="Main" aria-hidden={!open}>
      <button className="app-sidebar__close" onClick={onClose} aria-label="Close menu">×</button>
      <a href="Wayfare.html" className="app-sidebar__brand">
        <span className="nav__brand-mark" aria-hidden="true">W</span>
        <span>Wayfare</span>
      </a>
      <nav style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
        {items.map(i => (
          <button
            key={i.k}
            className={'sidebar-link' + (active === i.k ? ' is-active' : '')}
            onClick={() => pick(i.k)}
            aria-current={active === i.k ? 'page' : undefined}
          >
            {SidebarIcons[i.k]}
            {i.label}
          </button>
        ))}
      </nav>

      <div style={{ flex: 1 }} />

      <div style={{ padding: 12, background: 'var(--bg-alt)', borderRadius: 12, fontSize: 12, marginTop: 8 }}>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--primary)', fontWeight: 700 }}>● Wayfare AI</div>
        <p style={{ margin: '4px 0 0', color: 'var(--muted)', fontSize: 12 }}>You've used 12 of 50 monthly plan generations.</p>
        <div style={{ marginTop: 8, height: 4, borderRadius: 999, background: 'var(--line)', overflow: 'hidden' }}>
          <div style={{ width: '24%', height: '100%', background: 'var(--primary)' }} />
        </div>
      </div>

      <button onClick={() => { onSignOut(); onClose?.(); }} className="sidebar-link" style={{ marginTop: 8, color: 'var(--muted)' }}>
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" width="16" height="16"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" x2="9" y1="12" y2="12"/></svg>
        Sign out
      </button>
    </aside>
  );
}

/* ----------- Bottom nav (mobile) ----------- */
function BottomNav({ active, onNav, session }) {
  const isScout = session?.role === 'scout';
  const items = isScout
    ? [
        { k: 'requests', label: 'Requests' },
        { k: 'trips', label: 'Trips' },
      ]
    : [
        { k: 'plan', label: 'Plan' },
        { k: 'trips', label: 'Trips' },
        { k: 'camera', label: 'AI' },
        { k: 'profile', label: 'You' },
      ];
  return (
    <nav className="app-bottom-nav" aria-label="Bottom">
      {items.map(i => (
        <button key={i.k} className={active === i.k ? 'is-active' : ''} onClick={() => onNav(i.k)}>
          {SidebarIcons[i.k]}
          <span>{i.label}</span>
        </button>
      ))}
    </nav>
  );
}

/* ----------- Topbar ----------- */
function Topbar({ title, session, onProfile, onMenuToggle }) {
  return (
    <div className="app-topbar">
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, minWidth: 0 }}>
        <button onClick={onMenuToggle} className="menu-toggle" aria-label="Open menu">
          <span className="menu-toggle__icon" aria-hidden="true"><span /><span /><span /></span>
          <span>Menu</span>
        </button>
        <h1 className="app-topbar__title" style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{title}</h1>
      </div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
        <button className="user-pill" onClick={onProfile} aria-label="Your profile">
          <span className="user-pill__avatar">{session.initials}</span>
          <span>{session.name?.split(' ')[0]}</span>
        </button>
      </div>
    </div>
  );
}

/* ============================================================
   Screen: Plan (default home)
   ============================================================ */
function PlanScreen({ session, onResults }) {
  const [query, setQuery] = shUseState('');
  const [needs, setNeeds] = shUseState(session.needs || []);
  const [listening, setListening] = shUseState(false);

  shUseEffect(() => {
    const pending = sessionStorage.getItem('wayfare:pendingQuery');
    if (pending) {
      setQuery(pending);
      sessionStorage.removeItem('wayfare:pendingQuery');
    }
  }, []);

  const cities = [
    { name: 'Jaipur', tag: '142 verified venues', color: '#C68B59' },
    { name: 'Bangalore', tag: 'Coming next week', color: '#3A7CA5', soon: true },
    { name: 'Mumbai', tag: 'Coming next week', color: '#7BAA80', soon: true },
    { name: 'Goa', tag: 'Coming next week', color: '#F4A261', soon: true },
  ];

  return (
    <div className="app-content" style={{ display: 'flex', flexDirection: 'column', gap: 32 }}>
      <div className="planner-hero">
        <div style={{ position: 'relative', zIndex: 1 }}>
          <span className="eyebrow" style={{ color: 'var(--accent)' }}>● Wayfare AI</span>
          <h2 className="h-section" style={{ marginTop: 14, color: '#fff', maxWidth: '18ch', fontSize: 'clamp(28px, 3.5vw, 48px)' }}>
            Hi {session.name?.split(' ')[0]}, where shall we go?
          </h2>
          <p style={{ marginTop: 14, fontSize: 16, lineHeight: 1.55, color: 'rgba(255,255,255,0.78)', maxWidth: '52ch' }}>
            Speak or type your trip. I'll filter for {needs.length ? needs.length + ' accessibility needs' : 'your needs'}, score every venue, and surface scout-verified options.
          </p>

          <div style={{ marginTop: 20 }}>
            <VoiceInput
              value={query}
              onChange={setQuery}
              onSubmit={() => query.trim() && onResults({ query, needs })}
              presets={[
                'Jaipur · 3 days · step-free hotels',
                'Bangalore · museums · low vision',
                'Goa · sensory-friendly · with kids',
              ]}
            />
          </div>
        </div>
      </div>

      {/* A11y profile chips */}
      <section>
        <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 14 }}>
          <h3 style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 22, margin: 0 }}>Your trip filters</h3>
          <span style={{ fontSize: 13, color: 'var(--muted)' }}>Tap to toggle</span>
        </div>
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
          {NEED_OPTIONS.map(opt => (
            <button
              key={opt.key}
              className="chip"
              aria-pressed={needs.includes(opt.key)}
              onClick={() => setNeeds(needs.includes(opt.key) ? needs.filter(n => n !== opt.key) : [...needs, opt.key])}
            >
              {opt.label}
            </button>
          ))}
        </div>
      </section>

      {/* Cities */}
      <section>
        <h3 style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 22, margin: '0 0 14px' }}>Or jump into a verified city</h3>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 14 }}>
          {cities.map(c => (
            <button
              key={c.name}
              disabled={c.soon}
              onClick={() => !c.soon && onResults({ query: `Trip to ${c.name}`, needs })}
              className="card"
              style={{
                textAlign: 'left',
                cursor: c.soon ? 'not-allowed' : 'pointer',
                opacity: c.soon ? 0.6 : 1,
                background: 'var(--surface)',
                font: 'inherit',
                color: 'inherit',
                padding: 0,
                overflow: 'hidden',
              }}
            >
              <VenuePhoto kind="city" accent={c.color} height={120} />
              <div style={{ padding: 16 }}>
                <div style={{ fontFamily: 'var(--font-serif)', fontSize: 22, fontWeight: 500 }}>{c.name}</div>
                <div style={{ marginTop: 4, fontSize: 13, color: c.soon ? 'var(--muted)' : 'var(--primary)', fontWeight: 600 }}>{c.tag}</div>
              </div>
            </button>
          ))}
        </div>
      </section>

      {/* Recently asked */}
      <section>
        <h3 style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 22, margin: '0 0 14px' }}>Recent prompts from the community</h3>
        <div style={{ display: 'grid', gap: 8 }}>
          {[
            { q: 'Weekend in Jaipur with my partner who uses a power chair', t: '2h ago' },
            { q: 'Sensory-friendly café crawl in C-Scheme', t: 'Yesterday' },
            { q: 'Heritage walks that are step-free or buggy-friendly', t: '3d ago' },
          ].map((r, i) => (
            <button key={i} onClick={() => setQuery(r.q)} className="card" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', textAlign: 'left', cursor: 'pointer', background: 'var(--surface-warm)' }}>
              <span style={{ fontSize: 14.5 }}>{r.q}</span>
              <span style={{ fontSize: 12, color: 'var(--muted)', fontFamily: 'var(--font-mono)' }}>{r.t}</span>
            </button>
          ))}
        </div>
      </section>
    </div>
  );
}

/* ============================================================
   Plan options — 3 alternative itineraries to choose from
   ============================================================ */

const SCOUT_TEAM = [
  {
    id: 'aisha', name: 'Aisha Verma', role: 'Primary scout · full trip',
    photo: 'https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=300&h=300&fit=crop&auto=format',
    bio: 'Wheelchair user, hospitality scout, Jaipur native. 142 verified visits.',
    hours: 'Available 08:00 – 21:00 IST',
    phone: '+91 90••• 14',
  },
  {
    id: 'rohan', name: 'Rohan Kapoor', role: 'Heritage specialist',
    photo: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=300&h=300&fit=crop&auto=format',
    bio: 'Power chair user, certified heritage guide. ISL/BSL signing.',
    hours: 'Joins for heritage segments',
  },
  {
    id: 'maya', name: 'Maya Iyer', role: 'Food & sensory specialist',
    photo: 'https://images.unsplash.com/photo-1544005313-94ddf0286df2?w=300&h=300&fit=crop&auto=format',
    bio: 'Autistic adult, certified nutritionist. Café-crawl regular.',
    hours: 'Joins for food/sensory blocks',
  },
  {
    id: 'priya', name: 'Priya Singh', role: 'Mobility & transport scout',
    photo: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=300&h=300&fit=crop&auto=format',
    bio: 'Manual chair user since 2014. Cab & transport audits lead.',
    hours: 'On-call for transfers',
  },
];

const PLAN_OPTIONS = [
  {
    id: 'heritage',
    title: 'Heritage & Palaces',
    tagline: 'Iconic forts, palace dining, city panoramas.',
    blurb: 'Anchored around Amer Fort and Rambagh, with the buggy route to keep it step-free. Best for first-timers who want the "did Jaipur properly" moment.',
    pace: 'Standard',
    cost: '₹₹₹',
    avgScore: 87,
    stops: 8,
    accentKind: 'palace',
    accent: '#C68B59',
    keyVenueIds: ['taj-rambagh', 'amer-fort', 'anokhi'],
    scoutIds: ['aisha', 'rohan'],
    highlights: ['Amer Fort buggy tour with Rohan', 'Suvarna Mahal dinner', 'Sunset at Nahargarh'],
    days: [
      {
        n: 1, label: 'Mon 14 Mar', title: 'Arrive · Settle · Quiet evening', scoutId: 'aisha',
        slots: [
          { time: '11:15', kind: 'scout', scoutId: 'aisha', label: 'Aisha meets you at JAI Arrivals Gate B', sub: 'Holding a green Wayfare flag. Helps with bags & cab.' },
          { time: '11:30', kind: 'transit', label: 'Step-free airport pickup', sub: 'Aisha rides with you · Ola Mobility (22 min · ₹420)', venueId: 'ola-mobility' },
          { time: '12:30', kind: 'venue', slot: 'Check-in', venueId: 'taj-rambagh', dur: '90 min', note: 'Aisha confirms wing B suite, walks the route to dining hall with you.' },
          { time: '15:30', kind: 'venue', slot: 'Late lunch', venueId: 'anokhi', dur: '75 min', note: 'Aisha sits in for first 20 min, then on-call.' },
          { time: '17:00', kind: 'note', label: 'Free time · Aisha on-call', sub: 'Quiet wing, dimmable lights. Reachable in 8 min if needed.' },
          { time: '19:30', kind: 'venue', slot: 'Dinner', venueId: 'anokhi', dur: '90 min', note: 'Or in-suite — same kitchen.' },
          { time: '21:00', kind: 'scout', scoutId: 'aisha', label: 'Aisha signs off for the day', sub: 'Night concierge briefed on your profile.' },
        ],
      },
      {
        n: 2, label: 'Tue 15 Mar', title: 'Heritage · Buggy access · Sunset', scoutId: 'aisha',
        slots: [
          { time: '08:30', kind: 'note', label: 'Breakfast · Aisha joins for tea', sub: 'Accessible dining hall · 1F (lift)' },
          { time: '09:45', kind: 'scout', scoutId: 'aisha', label: 'Aisha walks you to the cab', sub: 'Hands off to Rohan at Amer Fort gates.' },
          { time: '10:00', kind: 'transit', label: 'Transfer to Amer Fort', sub: 'Ola Mobility (38 min)', venueId: 'ola-mobility' },
          { time: '11:00', kind: 'scout', scoutId: 'rohan', label: 'Rohan meets you at Amer Fort Gate 2', sub: 'Heritage specialist. ISL/BSL ready if needed.' },
          { time: '11:05', kind: 'venue', slot: 'Heritage tour with Rohan', venueId: 'amer-fort', dur: '3 hrs', note: 'Rohan personally guides the buggy route.' },
          { time: '14:00', kind: 'scout', scoutId: 'rohan', label: 'Rohan hands off back to Aisha', sub: 'Briefs Aisha on what you enjoyed.' },
          { time: '14:30', kind: 'venue', slot: 'Late lunch', venueId: 'anokhi', dur: '60 min', note: 'Aisha rejoins. Sister branch in Amer.' },
          { time: '17:00', kind: 'note', label: 'Sunset at Nahargarh · Aisha accompanies', sub: 'Buggy route to terrace. 24°C forecast.' },
          { time: '20:00', kind: 'venue', slot: 'Dinner', venueId: 'taj-rambagh', dur: '90 min', note: 'Suvarna Mahal dining hall (Wayfare 92).' },
          { time: '21:30', kind: 'scout', scoutId: 'aisha', label: 'Aisha signs off', sub: 'On-call overnight via app.' },
        ],
      },
      {
        n: 3, label: 'Wed 16 Mar', title: 'Slow morning · Crafts · Depart', scoutId: 'aisha',
        slots: [
          { time: '09:30', kind: 'note', label: 'Slow breakfast in-suite', sub: 'Checkout extended to 13:00.' },
          { time: '10:45', kind: 'scout', scoutId: 'aisha', label: 'Aisha meets you in the hotel lobby', sub: 'Quiet route to C-Scheme mapped.' },
          { time: '11:00', kind: 'venue', slot: 'Quiet café crawl', venueId: 'anokhi', dur: '2 hrs', note: '3 cafés in 400m, all step-free.' },
          { time: '13:30', kind: 'venue', slot: 'Hotel checkout', venueId: 'taj-rambagh', dur: '30 min', note: 'Concierge handles bags.' },
          { time: '15:30', kind: 'transit', label: 'Aisha rides with you to JAI', sub: 'Ola Mobility (28 min · ₹510). Drop at Gate B.', venueId: 'ola-mobility' },
          { time: '16:00', kind: 'scout', scoutId: 'aisha', label: 'Aisha says goodbye at the kerb', sub: 'Stays in WhatsApp until you clear security.' },
        ],
      },
    ],
  },

  {
    id: 'slow',
    title: 'Slow & Sensory-Friendly',
    tagline: 'Fewer stops, more rest, quiet rooms.',
    blurb: 'Built for sensory-friendly pacing — generous gaps, dim-lit dining, no rush points. Every stop scores Wayfare 89+. Best when you want to enjoy a city, not endure it.',
    pace: 'Easy',
    cost: '₹₹',
    avgScore: 92,
    stops: 5,
    accentKind: 'cafe',
    accent: '#7BAA80',
    keyVenueIds: ['anokhi', 'taj-rambagh', 'amer-fort'],
    scoutIds: ['aisha', 'maya'],
    highlights: ['Two-hour lunches', 'Sensory-mapped café crawl', 'Optional, opt-out anytime'],
    days: [
      {
        n: 1, label: 'Mon 14 Mar', title: 'Soft landing', scoutId: 'aisha',
        slots: [
          { time: '11:15', kind: 'scout', scoutId: 'aisha', label: 'Aisha meets you at JAI Arrivals · low-traffic exit', sub: 'No crowds — Gate D, west wing. Sensory pack ready.' },
          { time: '11:45', kind: 'transit', label: 'Step-free pickup (windows tinted)', sub: 'Ola Mobility — driver briefed for low conversation.', venueId: 'ola-mobility' },
          { time: '12:45', kind: 'venue', slot: 'Quiet check-in (rear lobby)', venueId: 'taj-rambagh', dur: '60 min', note: 'Aisha takes you in through the staff lobby — quieter than main entrance.' },
          { time: '14:00', kind: 'note', label: 'Rest block · 2 hrs', sub: 'Dimmed suite, sound-dampened. Aisha on-call.' },
          { time: '17:00', kind: 'venue', slot: 'Early dinner', venueId: 'anokhi', dur: '90 min', note: 'Off-peak — restaurant near-empty. Maya pre-arranges menu.' },
          { time: '19:30', kind: 'note', label: 'Wind-down at hotel', sub: 'Aisha drops a calm-tea kit at your door.' },
          { time: '21:00', kind: 'scout', scoutId: 'aisha', label: 'Aisha signs off · noise-cancelling backup in room', sub: 'Free of charge.' },
        ],
      },
      {
        n: 2, label: 'Tue 15 Mar', title: 'One thing, properly', scoutId: 'aisha',
        slots: [
          { time: '09:30', kind: 'note', label: 'Lazy breakfast in-suite', sub: 'No fixed time. Aisha checks in at 10:30.' },
          { time: '11:00', kind: 'scout', scoutId: 'maya', label: 'Maya joins for the café crawl', sub: 'Sensory-mapped 3-stop route. 90 min each.' },
          { time: '11:30', kind: 'venue', slot: 'Café crawl with Maya', venueId: 'anokhi', dur: '4 hrs', note: 'Slow pace. Decompression bench between stops 2 & 3.' },
          { time: '15:30', kind: 'scout', scoutId: 'maya', label: 'Maya wraps. Aisha drives you back.', sub: 'Sensory recap sent to your inbox.' },
          { time: '16:00', kind: 'note', label: 'Long rest · 3 hrs', sub: 'No plans. Spa optional (accessible massage room).' },
          { time: '19:00', kind: 'venue', slot: 'Light dinner', venueId: 'anokhi', dur: '75 min', note: 'Same menu, same calm corner.' },
          { time: '20:30', kind: 'scout', scoutId: 'aisha', label: 'Aisha signs off', sub: '' },
        ],
      },
      {
        n: 3, label: 'Wed 16 Mar', title: 'Easy depart', scoutId: 'aisha',
        slots: [
          { time: '10:00', kind: 'note', label: 'Slow breakfast in-suite', sub: 'Checkout extended to 14:00.' },
          { time: '12:00', kind: 'scout', scoutId: 'aisha', label: 'Aisha for final stroll in hotel gardens', sub: 'Step-free loop. Optional — opt out anytime.' },
          { time: '13:30', kind: 'venue', slot: 'Hotel checkout', venueId: 'taj-rambagh', dur: '30 min', note: 'Quiet lounge until departure.' },
          { time: '16:00', kind: 'transit', label: 'Off-peak airport ride', sub: 'Ola Mobility — Aisha rides with you.', venueId: 'ola-mobility' },
          { time: '16:30', kind: 'scout', scoutId: 'aisha', label: 'Aisha says goodbye · quietest gate (D)', sub: 'WhatsApp open until you clear security.' },
        ],
      },
    ],
  },

  {
    id: 'outdoor',
    title: 'Outdoor & Active',
    tagline: 'Sunsets, terraces, accessible outdoor spots.',
    blurb: 'For travellers who want to be outdoors — Nahargarh, Galta Ji, Albert Hall gardens. Higher pace, but every spot scout-verified for mobility access and shade.',
    pace: 'Active',
    cost: '₹₹',
    avgScore: 82,
    stops: 9,
    accentKind: 'fort',
    accent: '#F4A261',
    keyVenueIds: ['amer-fort', 'anokhi', 'ola-mobility'],
    scoutIds: ['aisha', 'rohan', 'priya'],
    highlights: ['Nahargarh sunrise viewpoint', 'Albert Hall gardens', 'Two-fort day with Rohan'],
    days: [
      {
        n: 1, label: 'Mon 14 Mar', title: 'Arrive · Gardens · Golden hour', scoutId: 'aisha',
        slots: [
          { time: '10:30', kind: 'scout', scoutId: 'priya', label: 'Priya meets you at JAI · transport check', sub: 'Mobility scout reviews your gear before transfer.' },
          { time: '11:00', kind: 'transit', label: 'Airport → Rambagh', sub: 'Step-free cab. Priya rides along.', venueId: 'ola-mobility' },
          { time: '12:00', kind: 'scout', scoutId: 'aisha', label: 'Aisha takes over at the hotel lobby', sub: 'Priya hands off — Aisha has your day.' },
          { time: '12:15', kind: 'venue', slot: 'Quick check-in', venueId: 'taj-rambagh', dur: '45 min', note: 'Drop bags, light lunch.' },
          { time: '14:30', kind: 'venue', slot: 'Albert Hall gardens', venueId: 'anokhi', dur: '90 min', note: 'Step-free loop. Shaded benches every 80m.' },
          { time: '17:30', kind: 'note', label: 'Sunset at Nahargarh terrace · Aisha drives', sub: 'Buggy ride up. Cool breeze, golden hour.' },
          { time: '19:30', kind: 'venue', slot: 'Terrace dinner', venueId: 'taj-rambagh', dur: '90 min', note: 'Open-air. Optional indoor backup.' },
          { time: '21:30', kind: 'scout', scoutId: 'aisha', label: 'Aisha signs off', sub: 'On-call overnight.' },
        ],
      },
      {
        n: 2, label: 'Tue 15 Mar', title: 'Two forts · One Rohan', scoutId: 'rohan',
        slots: [
          { time: '07:30', kind: 'scout', scoutId: 'aisha', label: 'Aisha for early breakfast', sub: 'Beat the heat departure.' },
          { time: '08:30', kind: 'scout', scoutId: 'rohan', label: 'Rohan picks up — full day', sub: 'Two-fort plan: Amer + Jaigarh via buggy link.' },
          { time: '09:00', kind: 'venue', slot: 'Amer Fort tour', venueId: 'amer-fort', dur: '3 hrs', note: 'Buggy + ISL/BSL slot at 10:00.' },
          { time: '12:30', kind: 'venue', slot: 'Lunch with view', venueId: 'anokhi', dur: '60 min', note: 'Amer branch terrace.' },
          { time: '14:00', kind: 'note', label: 'Jaigarh link via buggy', sub: 'Rohan walks (rolls) you to viewpoint 2.' },
          { time: '17:00', kind: 'scout', scoutId: 'rohan', label: 'Rohan hands off · Aisha drives back', sub: 'Includes scout debrief.' },
          { time: '19:30', kind: 'venue', slot: 'Casual dinner', venueId: 'anokhi', dur: '75 min', note: 'Light, after a big day.' },
          { time: '21:30', kind: 'scout', scoutId: 'aisha', label: 'Aisha signs off', sub: '' },
        ],
      },
      {
        n: 3, label: 'Wed 16 Mar', title: 'Markets · Galta · Goodbye', scoutId: 'aisha',
        slots: [
          { time: '09:00', kind: 'note', label: 'Breakfast', sub: 'Aisha for tea at 09:30.' },
          { time: '10:30', kind: 'scout', scoutId: 'aisha', label: 'Aisha for Bapu Bazaar accessible loop', sub: 'Step-free shop list pre-confirmed.' },
          { time: '13:00', kind: 'venue', slot: 'Lunch', venueId: 'anokhi', dur: '60 min', note: 'C-Scheme branch.' },
          { time: '14:30', kind: 'venue', slot: 'Hotel checkout', venueId: 'taj-rambagh', dur: '30 min' },
          { time: '15:30', kind: 'transit', label: 'Airport ride', sub: 'Aisha rides with you.', venueId: 'ola-mobility' },
          { time: '16:00', kind: 'scout', scoutId: 'aisha', label: 'Aisha says goodbye at JAI Gate B', sub: 'WhatsApp open through your flight.' },
        ],
      },
    ],
  },
];

/* Legacy alias so existing components keep working */
const ITINERARY = (() => {
  const p = PLAN_OPTIONS[0];
  return {
    city: 'Jaipur', dates: '14 – 16 Mar 2026', travellers: 'You + 1 (3 days)',
    avgScore: p.avgScore, scoutTeam: SCOUT_TEAM, days: p.days,
  };
})();

/* ============================================================
   Plan Options screen — choose 1 of 3 itineraries
   ============================================================ */
function PlanOptionsScreen({ onPick, onCamera }) {
  const [hovered, setHovered] = shUseState(null);
  return (
    <div className="app-content" style={{ display: 'flex', flexDirection: 'column', gap: 28 }}>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 16, flexWrap: 'wrap' }}>
        <div style={{ flex: '1 1 auto', minWidth: 280 }}>
          <span className="eyebrow">● Wayfare AI · 3 drafts</span>
          <h2 className="h-section" style={{ fontSize: 'clamp(28px, 3.5vw, 44px)', marginTop: 10, maxWidth: '24ch' }}>
            I drafted <em>three plans</em> for you. Pick the one that fits today's mood.
          </h2>
          <p className="lede" style={{ marginTop: 10, maxWidth: '60ch', fontSize: 16 }}>
            Same dates, same accessibility profile — different vibes. Each plan is scout-verified end-to-end. You can change later.
          </p>
        </div>
        <button onClick={onCamera} className="btn btn--sm btn--ghost">
          <Icon.camera width="14" height="14" /> Use Camera AI
        </button>
      </div>

      <div className="plan-options-grid">
        {PLAN_OPTIONS.map((p, i) => (
          <PlanOptionCard
            key={p.id}
            plan={p}
            recommended={i === 0}
            hovered={hovered === p.id}
            onHover={(h) => setHovered(h ? p.id : null)}
            onPick={() => onPick(p.id)}
          />
        ))}
      </div>

      {/* Comparison strip */}
      <div className="card" style={{ background: 'var(--surface-warm)' }}>
        <div className="mono" style={{ fontSize: 11, letterSpacing: '0.14em', color: 'var(--primary)', fontWeight: 700, textTransform: 'uppercase', marginBottom: 12 }}>At a glance</div>
        <div style={{ overflowX: 'auto' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13.5, minWidth: 520 }}>
            <thead>
              <tr style={{ borderBottom: '1.5px solid var(--line)', textAlign: 'left' }}>
                <th style={{ padding: '10px 8px', fontWeight: 600, color: 'var(--muted)' }}>Plan</th>
                <th style={{ padding: '10px 8px', fontWeight: 600, color: 'var(--muted)' }}>Pace</th>
                <th style={{ padding: '10px 8px', fontWeight: 600, color: 'var(--muted)' }}>Stops</th>
                <th style={{ padding: '10px 8px', fontWeight: 600, color: 'var(--muted)' }}>Avg score</th>
                <th style={{ padding: '10px 8px', fontWeight: 600, color: 'var(--muted)' }}>Cost</th>
              </tr>
            </thead>
            <tbody>
              {PLAN_OPTIONS.map(p => (
                <tr key={p.id} style={{ borderBottom: '1px solid var(--line)' }}>
                  <td style={{ padding: '12px 8px' }}><strong style={{ fontFamily: 'var(--font-serif)', fontWeight: 500 }}>{p.title}</strong></td>
                  <td style={{ padding: '12px 8px' }}>{p.pace}</td>
                  <td style={{ padding: '12px 8px' }}>{p.stops}</td>
                  <td style={{ padding: '12px 8px', color: 'var(--primary)', fontWeight: 700 }}>{p.avgScore}</td>
                  <td style={{ padding: '12px 8px' }}>{p.cost}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

function PlanOptionCard({ plan, recommended, hovered, onHover, onPick }) {
  const scoutsHere = plan.scoutIds.map(id => SCOUT_TEAM.find(s => s.id === id)).filter(Boolean);
  return (
    <article
      className="plan-card"
      onMouseEnter={() => onHover(true)}
      onMouseLeave={() => onHover(false)}
      style={{
        transform: hovered ? 'translateY(-3px)' : 'translateY(0)',
        boxShadow: hovered ? 'var(--shadow-2)' : 'var(--shadow-1)',
      }}
    >
      <div style={{ position: 'relative' }}>
        <VenuePhoto kind={plan.accentKind} accent={plan.accent} height={170} />
        {recommended && (
          <span style={{ position: 'absolute', top: 14, left: 14, background: 'var(--accent)', color: 'var(--ink)', padding: '5px 12px', borderRadius: 999, fontSize: 11, fontFamily: 'var(--font-mono)', textTransform: 'uppercase', letterSpacing: '0.12em', fontWeight: 700 }}>
            ★ Wayfare AI pick
          </span>
        )}
        <span style={{ position: 'absolute', top: 14, right: 14, background: 'rgba(0,0,0,0.78)', color: '#fff', padding: '5px 10px', borderRadius: 999, fontSize: 11, fontFamily: 'var(--font-mono)', fontWeight: 700 }}>
          {plan.pace} pace
        </span>
      </div>
      <div style={{ padding: 20, display: 'flex', flexDirection: 'column', gap: 12, flex: 1 }}>
        <div>
          <h3 style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 24, margin: 0, lineHeight: 1.15, letterSpacing: '-0.01em' }}>{plan.title}</h3>
          <p style={{ margin: '4px 0 0', fontSize: 13.5, color: 'var(--muted)' }}>{plan.tagline}</p>
        </div>

        <p style={{ margin: 0, fontSize: 14, color: 'var(--ink-soft)', lineHeight: 1.55 }}>{plan.blurb}</p>

        {/* Stat strip */}
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 12, padding: '12px 0', borderBlock: '1.5px solid var(--line)', marginTop: 4 }}>
          <PlanStat label="Avg score" value={plan.avgScore} highlight />
          <PlanStat label="Stops" value={plan.stops} />
          <PlanStat label="Cost" value={plan.cost} />
        </div>

        {/* Highlights */}
        <div>
          <div style={{ fontSize: 11, fontFamily: 'var(--font-mono)', letterSpacing: '0.12em', color: 'var(--muted)', textTransform: 'uppercase', fontWeight: 700, marginBottom: 6 }}>Highlights</div>
          <ul style={{ margin: 0, padding: 0, listStyle: 'none', display: 'grid', gap: 4, fontSize: 13.5 }}>
            {plan.highlights.map(h => (
              <li key={h} style={{ display: 'flex', alignItems: 'flex-start', gap: 8 }}>
                <span style={{ width: 14, height: 14, marginTop: 2, borderRadius: 999, background: 'var(--primary-soft)', color: 'var(--primary)', display: 'grid', placeItems: 'center', flexShrink: 0 }}>
                  <Icon.check width="10" height="10" />
                </span>
                {h}
              </li>
            ))}
          </ul>
        </div>

        {/* Scouts */}
        <div>
          <div style={{ fontSize: 11, fontFamily: 'var(--font-mono)', letterSpacing: '0.12em', color: 'var(--muted)', textTransform: 'uppercase', fontWeight: 700, marginBottom: 8 }}>Your scouts</div>
          <div style={{ display: 'flex', alignItems: 'center', gap: -6 }}>
            <div style={{ display: 'flex' }}>
              {scoutsHere.map((s, i) => (
                <div key={s.id} style={{ marginLeft: i === 0 ? 0 : -10 }}>
                  <ScoutAvatar name={s.name} photo={s.photo} color={plan.accent} size={32} ring="var(--surface)" />
                </div>
              ))}
            </div>
            <span style={{ marginLeft: 10, fontSize: 12.5, color: 'var(--muted)' }}>
              {scoutsHere.map(s => s.name.split(' ')[0]).join(' & ')}
            </span>
          </div>
        </div>

        <button
          onClick={onPick}
          className="btn btn--lg"
          style={{ justifyContent: 'center', marginTop: 'auto', width: '100%', background: recommended ? 'var(--accent)' : 'var(--primary)', color: recommended ? 'var(--ink)' : '#fff' }}
        >
          Choose this plan <Icon.arrow />
        </button>
      </div>
    </article>
  );
}

function PlanStat({ label, value, highlight }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column' }}>
      <span style={{ fontSize: 10.5, fontFamily: 'var(--font-mono)', letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--muted)', fontWeight: 600 }}>{label}</span>
      <span style={{ fontFamily: 'var(--font-serif)', fontSize: 22, fontWeight: 500, color: highlight ? 'var(--primary)' : 'var(--ink)' }}>{value}</span>
    </div>
  );
}

function ResultsScreen({ context, session, onOpenVenue, onCamera }) {
  const startInView = !!context?.startInView;
  const [phase, setPhase] = shUseState(startInView ? 'view' : 'planning'); // planning | choose | view
  const [step, setStep] = shUseState(0);
  const [activeDay, setActiveDay] = shUseState(0);
  const [view, setView] = shUseState('itinerary'); // itinerary | list
  const [selectedPlanId, setSelectedPlanId] = shUseState(context?.planId || null);
  const steps = [
    'Parsing your needs with Wayfare AI…',
    'Querying 142 scout-verified venues…',
    'Calling the Wayfare Score engine…',
    'Building day-by-day schedules…',
    'Cross-checking scout reports…',
    'Drafting 3 itinerary options…',
  ];

  shUseEffect(() => {
    if (phase !== 'planning') return;
    if (step >= steps.length - 1) {
      const t = setTimeout(() => setPhase('choose'), 600);
      return () => clearTimeout(t);
    }
    const t = setTimeout(() => setStep(s => s + 1), 600);
    return () => clearTimeout(t);
  }, [phase, step]);

  const venueById = (id) => VENUE_DATA.find(v => v.id === id);
  const selectedPlan = PLAN_OPTIONS.find(p => p.id === selectedPlanId) || PLAN_OPTIONS[0];

  if (phase === 'planning') {
    return (
      <div className="app-content" style={{ display: 'grid', placeItems: 'center', minHeight: '70vh' }}>
        <div style={{ maxWidth: 480, width: '100%' }}>
          <span className="eyebrow">● Wayfare AI</span>
          <h2 className="h-section" style={{ marginTop: 14, maxWidth: '16ch', fontSize: 'clamp(28px, 3.5vw, 44px)' }}>
            Planning your trip…
          </h2>
          <div style={{ marginTop: 28, display: 'grid', gap: 10 }}>
            {steps.map((s, i) => (
              <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 12, fontSize: 14.5, opacity: i <= step ? 1 : 0.3, transition: 'opacity 300ms' }}>
                <span style={{ width: 22, height: 22, borderRadius: 999, background: i < step ? 'var(--success)' : i === step ? 'var(--accent)' : 'var(--line)', color: '#fff', display: 'grid', placeItems: 'center' }}>
                  {i < step ? <Icon.check width="12" height="12" /> : i === step ? <span style={{ width: 8, height: 8, borderRadius: 999, background: '#fff', animation: 'pulseRing 1s infinite' }} /> : null}
                </span>
                {s}
              </div>
            ))}
          </div>
        </div>
      </div>
    );
  }

  if (phase === 'choose') {
    return (
      <PlanOptionsScreen
        onPick={(id) => { setSelectedPlanId(id); setActiveDay(0); setPhase('view'); }}
        onCamera={onCamera}
      />
    );
  }

  return (
    <div className="app-content" style={{ display: 'flex', flexDirection: 'column', gap: 24 }}>
      {/* Summary header */}
      <div className="card" style={{ background: 'var(--surface-warm)' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
          <button onClick={() => setPhase('choose')} className="btn btn--sm btn--ghost" aria-label="Change plan">
            ‹ Change plan
          </button>
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.14em', color: 'var(--primary)', fontWeight: 700, textTransform: 'uppercase' }}>● {selectedPlan.title}</span>
          <span style={{ flex: 1 }} />
          <button onClick={onCamera} className="btn btn--sm btn--ghost">
            <Icon.camera width="14" height="14" /> Use Camera AI
          </button>
        </div>
        <h2 style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 'clamp(24px, 3vw, 34px)', margin: '10px 0', maxWidth: '34ch', lineHeight: 1.15 }}>
          Your <strong>{selectedPlan.days.length}-day Jaipur</strong> itinerary — {selectedPlan.tagline.toLowerCase()}
        </h2>
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 24, marginTop: 4, fontSize: 14, color: 'var(--ink-soft)' }}>
          <SummaryStat label="Dates" value="14 – 16 Mar 2026" />
          <SummaryStat label="Travellers" value="You + 1" />
          <SummaryStat label="Stops" value={selectedPlan.days.reduce((sum, d) => sum + d.slots.filter(s => s.kind === 'venue').length, 0)} />
          <SummaryStat label="Avg Wayfare" value={selectedPlan.avgScore} highlight />
          <SummaryStat label="Pace" value={selectedPlan.pace} />
          <SummaryStat label="Cost" value={selectedPlan.cost} />
        </div>
      </div>

      {/* View switcher */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
        <div style={{ display: 'inline-flex', background: 'var(--surface)', border: '1.5px solid var(--line)', borderRadius: 999, padding: 3 }}>
          <button
            onClick={() => setView('itinerary')}
            aria-pressed={view === 'itinerary'}
            style={{ padding: '7px 14px', borderRadius: 999, border: 0, fontSize: 13, fontWeight: 600, cursor: 'pointer', background: view === 'itinerary' ? 'var(--ink)' : 'transparent', color: view === 'itinerary' ? 'var(--bg)' : 'var(--ink)' }}
          >
            Day-by-day
          </button>
          <button
            onClick={() => setView('list')}
            aria-pressed={view === 'list'}
            style={{ padding: '7px 14px', borderRadius: 999, border: 0, fontSize: 13, fontWeight: 600, cursor: 'pointer', background: view === 'list' ? 'var(--ink)' : 'transparent', color: view === 'list' ? 'var(--bg)' : 'var(--ink)' }}
          >
            All venues
          </button>
        </div>
        <span style={{ flex: 1 }} />
        <button className="btn btn--sm btn--ghost">⤓ Export PDF</button>
        <button className="btn btn--sm">Book itinerary</button>
      </div>

      {view === 'itinerary' ? (
        <DayWiseItinerary
          plan={selectedPlan}
          activeDay={activeDay}
          setActiveDay={setActiveDay}
          onOpenVenue={(id) => { const v = venueById(id); if (v) onOpenVenue(v); }}
        />
      ) : (
        <AllVenuesGrid onOpenVenue={onOpenVenue} />
      )}
    </div>
  );
}

function SummaryStat({ label, value, highlight }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column' }}>
      <span style={{ fontSize: 11, fontFamily: 'var(--font-mono)', letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--muted)', fontWeight: 600 }}>{label}</span>
      <span style={{ fontFamily: 'var(--font-serif)', fontSize: 20, fontWeight: 500, color: highlight ? 'var(--primary)' : 'var(--ink)' }}>{value}</span>
    </div>
  );
}

/* ============================================================
   Day-wise itinerary
   ============================================================ */
function DayWiseItinerary({ plan, activeDay, setActiveDay, onOpenVenue }) {
  const days = plan.days;
  return (
    <div className="itinerary-layout">
      {/* Day rail */}
      <aside className="itinerary-rail" aria-label="Trip days">
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--muted)', fontWeight: 700, paddingBottom: 4 }}>Your trip</div>
        {days.map((d, i) => (
          <button
            key={d.n}
            onClick={() => setActiveDay(i)}
            aria-pressed={activeDay === i}
            style={{
              textAlign: 'left',
              background: activeDay === i ? 'var(--ink)' : 'var(--surface)',
              color: activeDay === i ? 'var(--bg)' : 'var(--ink)',
              border: '1.5px solid ' + (activeDay === i ? 'var(--ink)' : 'var(--line)'),
              padding: '14px 14px',
              borderRadius: 14,
              cursor: 'pointer',
              display: 'flex', flexDirection: 'column', gap: 4,
              font: 'inherit',
            }}
          >
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.12em', opacity: activeDay === i ? 0.7 : 0.5, fontWeight: 700, textTransform: 'uppercase' }}>Day {d.n} · {d.label}</span>
            <span style={{ fontFamily: 'var(--font-serif)', fontSize: 16, fontWeight: 500, lineHeight: 1.2 }}>{d.title}</span>
            <span style={{ fontSize: 12, opacity: activeDay === i ? 0.7 : 0.55, marginTop: 2 }}>
              {d.slots.filter(s => s.kind === 'venue').length} stops · {d.slots.filter(s => s.kind === 'transit').length} transfers
            </span>
          </button>
        ))}
      </aside>

      {/* Selected day timeline */}
      <DayTimeline day={days[activeDay]} plan={plan} onOpenVenue={onOpenVenue} />
    </div>
  );
}

function DayTimeline({ day, plan, onOpenVenue }) {
  const primaryScout = SCOUT_TEAM.find(s => s.id === day.scoutId);
  const scoutsInDay = [...new Set(day.slots.filter(s => s.kind === 'scout').map(s => s.scoutId))].
  map(id => SCOUT_TEAM.find(s => s.id === id)).
  filter(Boolean);

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 14, flexWrap: 'wrap' }}>
        <div className="mono" style={{ fontSize: 12, letterSpacing: '0.14em', color: 'var(--primary)', fontWeight: 700, textTransform: 'uppercase' }}>Day {day.n} · {day.label}</div>
        <span style={{ width: 6, height: 6, borderRadius: 999, background: 'var(--line)' }} />
        <span style={{ fontSize: 13, color: 'var(--muted)' }}>{day.slots.length} planned moments</span>
      </div>
      <h3 style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 'clamp(24px, 2.6vw, 32px)', margin: '8px 0 20px', lineHeight: 1.15, maxWidth: '24ch' }}>{day.title}</h3>

      {/* Scout team for this day */}
      <div style={{ marginBottom: 20, padding: 16, background: 'var(--ink)', color: 'var(--bg)', borderRadius: 16, display: 'flex', flexWrap: 'wrap', gap: 14, alignItems: 'center' }}>
        <div style={{ flex: '1 1 200px' }}>
          <div className="mono" style={{ fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--accent)', fontWeight: 700 }}>● Your scout team today</div>
          <p style={{ margin: '6px 0 0', fontSize: 14, color: 'rgba(255,255,255,0.78)', lineHeight: 1.5 }}>
            {scoutsInDay.length === 1
              ? <><strong style={{ color: '#fff' }}>{scoutsInDay[0]?.name}</strong> accompanies you through the day, meeting you at marked times below.</>
              : <><strong style={{ color: '#fff' }}>{scoutsInDay[0]?.name}</strong> is your primary scout. <strong style={{ color: '#fff' }}>{scoutsInDay.slice(1).map(s => s?.name).join(' & ')}</strong> {scoutsInDay.length === 2 ? 'joins' : 'join'} for specialist segments.</>
            }
          </p>
        </div>
        <div style={{ display: 'flex', gap: 10 }}>
          {scoutsInDay.map(s => (
            <div key={s.id} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4 }}>
              <ScoutAvatar name={s.name} photo={s.photo} color="var(--accent)" size={48} ring="rgba(255,255,255,0.18)" />
              <span style={{ fontSize: 10.5, color: 'rgba(255,255,255,0.7)', fontFamily: 'var(--font-mono)', fontWeight: 600 }}>{s.name.split(' ')[0]}</span>
            </div>
          ))}
        </div>
      </div>

      <div style={{ position: 'relative', paddingLeft: 22 }}>
        {/* Vertical rail */}
        <span aria-hidden="true" style={{ position: 'absolute', top: 8, bottom: 8, left: 8, width: 2, background: 'var(--line)' }} />
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          {day.slots.map((s, i) => (
            <TimelineSlot key={i} slot={s} onOpenVenue={onOpenVenue} />
          ))}
        </div>
      </div>

      {/* Day footer */}
      <div style={{ marginTop: 24, padding: 16, background: 'var(--primary-soft)', borderRadius: 14, display: 'flex', alignItems: 'center', gap: 12 }}>
        <span style={{ width: 36, height: 36, borderRadius: 999, background: 'var(--primary)', color: '#fff', display: 'grid', placeItems: 'center' }}>
          <Icon.sparkle width="18" height="18" />
        </span>
        <div style={{ flex: 1, fontSize: 13.5, color: 'var(--primary-deep)' }}>
          <strong style={{ display: 'block', fontFamily: 'var(--font-serif)', fontSize: 15.5, fontWeight: 500 }}>Wayfare AI note for Day {day.n}</strong>
          Forecast: 24–28°C, low humidity. Avg transfer time 12 min in cab. Quiet wing booked at Rambagh — request "wing B" at check-in for shortest accessible route to dining hall.
        </div>
      </div>
    </div>
  );
}

function TimelineSlot({ slot, onOpenVenue }) {
  const venue = slot.venueId ? VENUE_DATA.find(v => v.id === slot.venueId) : null;
  const scout = slot.scoutId ? SCOUT_TEAM.find(s => s.id === slot.scoutId) : null;

  if (slot.kind === 'scout') {
    return (
      <div style={{ display: 'grid', gridTemplateColumns: '60px 1fr', gap: 14, position: 'relative' }}>
        <Bullet time={slot.time} kind="scout" />
        <div style={{
          display: 'flex', alignItems: 'center', gap: 14,
          padding: '14px 16px',
          background: 'linear-gradient(140deg, var(--primary), var(--primary-deep))',
          color: '#fff',
          borderRadius: 14,
          border: '1.5px solid var(--primary-deep)',
        }}>
          <ScoutAvatar name={scout?.name} photo={scout?.photo} color="var(--accent)" size={44} ring="rgba(255,255,255,0.25)" />
          <div style={{ flex: 1 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 2 }}>
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10.5, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--accent)', fontWeight: 700 }}>● Scout meet</span>
              {scout?.hours && <span style={{ fontSize: 11, color: 'rgba(255,255,255,0.55)' }}>· {scout.role}</span>}
            </div>
            <strong style={{ fontSize: 14.5, lineHeight: 1.3 }}>{slot.label}</strong>
            {slot.sub && <div style={{ fontSize: 12.5, color: 'rgba(255,255,255,0.7)', marginTop: 2 }}>{slot.sub}</div>}
          </div>
          {scout?.phone && (
            <a
              href={`tel:${scout.phone.replace(/[^0-9+]/g, '')}`}
              aria-label={`Call ${scout?.name}`}
              style={{
                width: 36, height: 36, borderRadius: 999,
                background: 'var(--accent)', color: 'var(--ink)',
                display: 'grid', placeItems: 'center',
                textDecoration: 'none',
              }}
            >
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" width="14" height="14"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92Z"/></svg>
            </a>
          )}
        </div>
      </div>
    );
  }

  if (slot.kind === 'note') {
    return (
      <div style={{ display: 'grid', gridTemplateColumns: '60px 1fr', gap: 14, position: 'relative' }}>
        <Bullet time={slot.time} />
        <div style={{ padding: '12px 14px', background: 'var(--surface)', border: '1.5px dashed var(--line)', borderRadius: 12 }}>
          <strong style={{ fontSize: 14.5 }}>{slot.label}</strong>
          {slot.sub && <p style={{ margin: '4px 0 0', fontSize: 13, color: 'var(--muted)' }}>{slot.sub}</p>}
        </div>
      </div>
    );
  }

  if (slot.kind === 'transit') {
    return (
      <div style={{ display: 'grid', gridTemplateColumns: '60px 1fr', gap: 14, position: 'relative' }}>
        <Bullet time={slot.time} kind="transit" />
        <button
          onClick={() => slot.venueId && onOpenVenue(slot.venueId)}
          style={{
            display: 'flex', alignItems: 'center', gap: 12,
            padding: '12px 14px',
            background: 'var(--bg-alt)',
            border: '1.5px solid var(--line)',
            borderRadius: 12,
            cursor: 'pointer',
            font: 'inherit',
            color: 'inherit',
            textAlign: 'left',
          }}
        >
          <span style={{ width: 30, height: 30, borderRadius: 999, background: 'var(--ink)', color: '#fff', display: 'grid', placeItems: 'center' }}>
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" width="14" height="14"><path d="M5 12h14M13 5l7 7-7 7"/></svg>
          </span>
          <div style={{ flex: 1 }}>
            <strong style={{ fontSize: 14 }}>{slot.label}</strong>
            <div style={{ fontSize: 12.5, color: 'var(--muted)' }}>{slot.sub}</div>
          </div>
          {venue && <ScorePill score={venue.score} />}
        </button>
      </div>
    );
  }

  // venue
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '60px 1fr', gap: 14, position: 'relative' }}>
      <Bullet time={slot.time} kind="venue" />
      <button
        onClick={() => onOpenVenue(slot.venueId)}
        style={{
          display: 'block',
          padding: 0,
          background: 'var(--surface)',
          border: '1.5px solid var(--line)',
          borderRadius: 14,
          overflow: 'hidden',
          cursor: 'pointer',
          font: 'inherit',
          color: 'inherit',
          textAlign: 'left',
          transition: 'transform var(--motion-fast) var(--easing), box-shadow var(--motion-fast) var(--easing)',
        }}
        onMouseEnter={(e) => { e.currentTarget.style.transform = 'translateY(-1px)'; e.currentTarget.style.boxShadow = 'var(--shadow-2)'; }}
        onMouseLeave={(e) => { e.currentTarget.style.transform = ''; e.currentTarget.style.boxShadow = ''; }}
      >
        <div style={{ display: 'grid', gridTemplateColumns: 'minmax(140px, 200px) minmax(0, 1fr)', gap: 0 }}>
          <VenuePhoto kind={venue.photo} accent={venue.accent} height={'100%'} />
          <div style={{ padding: '14px 16px', display: 'flex', flexDirection: 'column', gap: 6 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 11, fontFamily: 'var(--font-mono)', letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--muted)', fontWeight: 600 }}>
              <span>{slot.slot}</span>
              <span>·</span>
              <span>{slot.dur}</span>
              <span style={{ flex: 1 }} />
              <ScorePill score={venue.score} />
            </div>
            <strong style={{ fontFamily: 'var(--font-serif)', fontSize: 18, fontWeight: 500, lineHeight: 1.2 }}>{venue.name}</strong>
            <div style={{ fontSize: 12.5, color: 'var(--muted)', display: 'flex', alignItems: 'center', gap: 6 }}>
              <Icon.pin width="11" height="11" /> {venue.area}
            </div>
            {slot.note && (
              <p style={{ margin: '2px 0 0', fontSize: 13.5, color: 'var(--ink-soft)', lineHeight: 1.45 }}>{slot.note}</p>
            )}
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 11.5, color: 'var(--primary)', fontWeight: 600 }}>
              <ScoutAvatar name={venue.verifiedBy.name} photo={venue.verifiedBy.photo} color={venue.accent} size={20} />
              Verified by {venue.verifiedBy.name}
            </div>
          </div>
        </div>
      </button>
    </div>
  );
}

function Bullet({ time, kind }) {
  const isScout = kind === 'scout';
  const isTransit = kind === 'transit';
  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', paddingTop: 14 }}>
      <span style={{
        width: 18, height: 18, borderRadius: 999,
        background: isScout ? 'var(--accent)' : isTransit ? 'var(--bg)' : 'var(--ink)',
        border: '2.5px solid ' + (isScout ? 'var(--accent-deep)' : 'var(--ink)'),
        zIndex: 1,
      }} />
      <span style={{ marginTop: 6, fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--muted)', fontWeight: 700, letterSpacing: '0.04em' }}>{time}</span>
    </div>
  );
}

/* All-venues grid (alternate view) */
function AllVenuesGrid({ onOpenVenue }) {
  const [filter, setFilter] = shUseState('all');
  const types = [
    { k: 'all', label: 'All' },
    { k: 'hotel', label: 'Stays' },
    { k: 'attraction', label: 'Attractions' },
    { k: 'café', label: 'Food' },
    { k: 'transport', label: 'Transport' },
  ];
  const filtered = filter === 'all' ? VENUE_DATA : VENUE_DATA.filter(v => v.type.toLowerCase().includes(filter));
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
        {types.map(t => (
          <button key={t.k} className="chip" aria-pressed={filter === t.k} onClick={() => setFilter(t.k)}>{t.label}</button>
        ))}
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(260px, 1fr))', gap: 16 }}>
        {filtered.map(v => (
          <button key={v.id} onClick={() => onOpenVenue(v)} className="venue-card" style={{ font: 'inherit', color: 'inherit', textAlign: 'left' }}>
            <VenuePhoto kind={v.photo} accent={v.accent} height={150} label={v.type} />
            <div className="venue-card__body">
              <div style={{ display: 'flex', alignItems: 'flex-start', gap: 8 }}>
                <strong style={{ fontFamily: 'var(--font-serif)', fontSize: 18, fontWeight: 500, flex: 1, lineHeight: 1.2 }}>{v.name}</strong>
                <ScorePill score={v.score} />
              </div>
              <div style={{ fontSize: 12.5, color: 'var(--muted)', display: 'flex', alignItems: 'center', gap: 6 }}>
                <Icon.pin width="12" height="12" /> {v.area} · {v.price}
              </div>
              <p style={{ fontSize: 13.5, lineHeight: 1.45, color: 'var(--ink-soft)', margin: 0 }}>{v.oneline}</p>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12, color: 'var(--primary)', fontWeight: 600 }}>
                <ScoutAvatar name={v.verifiedBy.name} photo={v.verifiedBy.photo} color={v.accent} size={26} />
                Verified by {v.verifiedBy.name}
              </div>
            </div>
          </button>
        ))}
      </div>
    </div>
  );
}

/* ============================================================
   Screen: Detail
   ============================================================ */
function DetailScreen({ venue, onBack, onToast }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column' }}>
      <div style={{ position: 'relative' }}>
        <VenuePhoto kind={venue.photo} accent={venue.accent} height={320} />
        <button onClick={onBack} aria-label="Back" style={{ position: 'absolute', top: 16, left: 16, padding: '8px 14px', background: 'rgba(255,255,255,0.95)', border: 0, borderRadius: 999, fontSize: 14, fontWeight: 600, display: 'flex', alignItems: 'center', gap: 6 }}>
          ‹ Back
        </button>
        <div style={{ position: 'absolute', top: 16, right: 16, background: 'rgba(0,0,0,0.78)', color: '#fff', padding: '8px 14px', borderRadius: 999, fontSize: 12, fontWeight: 700, fontFamily: 'var(--font-mono)', textTransform: 'uppercase', letterSpacing: '0.1em', display: 'inline-flex', alignItems: 'center', gap: 6 }}>
          <Icon.shield width="12" height="12" /> Scout verified
        </div>
      </div>

      <div className="app-content col-2 col-2--detail col-2--start" style={{ gap: 36 }}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 24 }}>
          <div>
            <div className="mono" style={{ fontSize: 11, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '0.14em', fontWeight: 700 }}>{venue.type}</div>
            <h1 style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 'clamp(28px, 3.5vw, 44px)', margin: '6px 0', lineHeight: 1.1, letterSpacing: '-0.02em' }}>{venue.name}</h1>
            <div style={{ fontSize: 14, color: 'var(--muted)', display: 'flex', alignItems: 'center', gap: 6 }}>
              <Icon.pin width="14" height="14" /> {venue.area} · {venue.price}
            </div>
            <div style={{ marginTop: 14, display: 'flex', flexWrap: 'wrap', gap: 6 }}>
              {venue.needs.map(n => {
                const opt = NEED_OPTIONS.find(o => o.key === n);
                if (!opt) return null;
                return <span key={n} className="chip" style={{ background: 'var(--primary-soft)', borderColor: 'var(--primary)', color: 'var(--primary-deep)' }}>{opt.label} ✓</span>;
              })}
            </div>
          </div>

          {/* Score breakdown */}
          <div>
            <h2 style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 22, margin: '0 0 14px' }}>Score breakdown · with evidence</h2>
            <div style={{ display: 'grid', gap: 10 }}>
              {venue.breakdown.map(b => (
                <div key={b.label} className="card">
                  <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 8 }}>
                    <div style={{
                      width: 46, height: 46, flexShrink: 0,
                      borderRadius: 10,
                      background: b.score >= 90 ? 'var(--score-A)' : b.score >= 80 ? 'var(--score-B)' : b.score >= 70 ? 'var(--score-C)' : 'var(--score-D)',
                      color: '#fff', fontFamily: 'var(--font-mono)', fontWeight: 700, fontSize: 16,
                      display: 'grid', placeItems: 'center',
                    }}>{b.score}</div>
                    <strong style={{ fontSize: 16 }}>{b.label}</strong>
                    <div style={{ flex: 1, height: 6, background: 'var(--line)', borderRadius: 999, overflow: 'hidden' }}>
                      <div style={{ width: `${b.score}%`, height: '100%', background: b.score >= 90 ? 'var(--score-A)' : b.score >= 80 ? 'var(--score-B)' : b.score >= 70 ? 'var(--score-C)' : 'var(--score-D)' }} />
                    </div>
                  </div>
                  <p style={{ margin: 0, fontSize: 14, lineHeight: 1.55, color: 'var(--ink-soft)' }}>{b.note}</p>
                </div>
              ))}
            </div>
          </div>
        </div>

        <aside style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
          {/* Wayfare score */}
          <div className="card" style={{ textAlign: 'center' }}>
            <LighthouseScore score={venue.score} size={160} label="" />
            <div style={{ marginTop: 10, fontFamily: 'var(--font-serif)', fontSize: 18 }}>Wayfare Score</div>
            <div style={{ fontSize: 12, color: 'var(--muted)' }}>8 criteria · {venue.verifiedBy.visits} scout visits</div>
          </div>

          {/* Scout */}
          <div className="card card--ink">
            <div className="mono" style={{ fontSize: 11, color: 'var(--accent)', textTransform: 'uppercase', letterSpacing: '0.14em', fontWeight: 700, marginBottom: 10 }}>● Verified by</div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
              <ScoutAvatar name={venue.verifiedBy.name} photo={venue.verifiedBy.photo} color="var(--accent)" size={52} />
              <div>
                <div style={{ fontFamily: 'var(--font-serif)', fontSize: 18, fontWeight: 500 }}>{venue.verifiedBy.name}</div>
                <div style={{ fontSize: 12.5, color: 'rgba(255,255,255,0.7)' }}>{venue.verifiedBy.tagline}</div>
              </div>
            </div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 14 }}>
              {venue.verifiedBy.cred.map(c => (
                <span key={c} style={{ background: 'rgba(255,255,255,0.1)', padding: '4px 10px', borderRadius: 999, fontSize: 11.5 }}>{c}</span>
              ))}
            </div>
          </div>

          <button onClick={() => onToast('Added to your Jaipur itinerary')} className="btn btn--accent btn--lg" style={{ justifyContent: 'center' }}>
            Add to itinerary <Icon.arrow />
          </button>
          <button onClick={() => onToast('Added to your itinerary')} className="btn btn--ghost" style={{ justifyContent: 'center' }}>
            Share with travel companion
          </button>
        </aside>
      </div>
    </div>
  );
}

/* ============================================================
   Screen: Camera AI — LIVE webcam feed
   ============================================================ */
const LIVE_RESPONSES = [
  {
    title: 'Workspace · indoor view',
    body: "I can see <strong>an indoor workspace</strong> — a desk with a laptop and a chair in soft, even daylight from a window on the left. The walking path between desk and chair is <em>about 80 cm</em>, which is comfortable for a manual wheelchair but tight for a power chair. No visible thresholds or steps. Ambient noise looks low (no TV, no music).",
    tags: ['Step-free path', '~80 cm clearance', 'Low sensory load'],
  },
  {
    title: 'Doorway · close-range',
    body: "This looks like <strong>a standard interior doorway</strong>, roughly <em>76 cm clear width</em>. The handle is a lever style, easy to operate one-handed. There's no threshold — flush floor on both sides. The doorway swings inward, taking up a 90 cm arc on the inside.",
    tags: ['76 cm clear', 'Lever handle', 'No threshold'],
  },
  {
    title: 'Hand-held object · text',
    body: "I can read <strong>text in the foreground</strong> — sans-serif type, appears to be a label or menu. Contrast looks good (dark on light). Type size is moderate but might be challenging for low-vision users; I'd suggest holding closer for me to enlarge. Want me to read it aloud?",
    tags: ['Readable text', 'Good contrast', 'Mid-size type'],
  },
  {
    title: 'Open room · ambient',
    body: "Open room, well-lit. Furniture is arranged with <em>clear walking lines</em>. I don't see grab rails or sensory dampening, so this isn't optimised for mobility or sensory needs — but it's navigable. If you tell me where you want to go, I can suggest a route.",
    tags: ['Clear paths', 'No grab rails', 'Bright lighting'],
  },
  {
    title: 'Window scene · outdoors',
    body: "Through the window I can see <strong>outdoor terrain</strong>. The ground looks like flat paving with a kerb at the road edge — there's a dropped section about 4 metres to the right, which would be the accessible crossing point. Traffic looks moderate.",
    tags: ['Flat paving', 'Dropped kerb', 'Moderate traffic'],
  },
];

function CameraScreen() {
  const videoRef = React.useRef(null);
  const streamRef = React.useRef(null);
  const [status, setStatus] = shUseState('requesting'); // requesting | live | denied | unavailable
  const [analyzing, setAnalyzing] = shUseState(false);
  const [current, setCurrent] = shUseState(null);
  const [autoMode, setAutoMode] = shUseState(true);
  const [muted, setMuted] = shUseState(true);
  const [facingMode, setFacingMode] = shUseState('user');
  const [askOpen, setAskOpen] = shUseState(false);
  const [question, setQuestion] = shUseState('');
  const [listening, setListening] = shUseState(false);
  const [answer, setAnswer] = shUseState(null); // { q, a, ts }
  const [thinking, setThinking] = shUseState(false);
  const respIdxRef = React.useRef(0);
  const mutedRef = React.useRef(true);
  const primedRef = React.useRef(false);
  const recRef = React.useRef(null);
  const ttsSupported = typeof window !== 'undefined' && 'speechSynthesis' in window;
  const sttSupported = typeof window !== 'undefined' && !!(window.SpeechRecognition || window.webkitSpeechRecognition);

  // Keep ref in sync so speak() (called from intervals) sees the latest value
  shUseEffect(() => { mutedRef.current = muted; }, [muted]);

  const speak = (text) => {
    if (!ttsSupported || mutedRef.current || !text) return;
    try {
      window.speechSynthesis.cancel();
      // iOS Safari sometimes leaves synth in 'paused' state
      if (window.speechSynthesis.paused) window.speechSynthesis.resume();
      const u = new SpeechSynthesisUtterance(text);
      u.rate = 1.02; u.pitch = 1.0; u.volume = 1; u.lang = 'en-US';
      const voices = window.speechSynthesis.getVoices();
      const en = voices.find(v => /^en[-_]/i.test(v.lang)) || voices[0];
      if (en) u.voice = en;
      window.speechSynthesis.speak(u);
    } catch {}
  };
  const stopSpeaking = () => { if (ttsSupported) { try { window.speechSynthesis.cancel(); } catch {} } };

  // Prime speech synthesis from a user gesture (iOS requirement)
  const primeTTS = () => {
    if (!ttsSupported || primedRef.current) return;
    try {
      // A near-silent, near-empty utterance unlocks subsequent speak() calls
      const u = new SpeechSynthesisUtterance(' ');
      u.volume = 0.01; u.rate = 1;
      window.speechSynthesis.speak(u);
      primedRef.current = true;
    } catch {}
  };

  /* ----- Free-form Q&A ----- */
  const generateAnswer = (q) => {
    const ql = q.toLowerCase();
    if (/(door|width|wide)/.test(ql)) return "The doorway in view looks roughly 90 cm clear — wide enough for most manual wheelchairs (which need ~80 cm). There's no threshold lip.";
    if (/(step|stair|stairs)/.test(ql)) return "I can see two shallow steps, about 12 cm each. There is a side ramp on the right at gentle gradient, about 1:14 — usable with a chair if you can take a small detour.";
    if (/(ramp|gradient|slope)/.test(ql)) return "The ramp gradient looks gentle — around 1:14. UK Building Regs recommend max 1:12, so this is well within accessible limits.";
    if (/(sign|read|text|menu)/.test(ql)) return "I can read the sign — it says 'WELCOME'. The contrast is good (dark on light), type is sans-serif, comfortable for most low-vision users.";
    if (/(light|bright|dim|dark)/.test(ql)) return "Lighting is soft and even — no glare on reflective surfaces, no flickering. About 350 lux at this distance. Comfortable for most sensory profiles.";
    if (/(noise|loud|quiet|sound)/.test(ql)) return "Ambient noise is low — I'm estimating around 42 dB. No music, no shouting. Sensory-friendly.";
    if (/(seat|seating|chair|table)/.test(ql)) return "I can see seating with adequate clearance between tables — about 90 cm. A wheelchair would fit at the corner table without blocking the aisle.";
    if (/(bathroom|toilet|washroom|wc)/.test(ql)) return "I can't see a bathroom from this angle. Want me to scan the venue's accessibility page for bathroom details?";
    if (/(parking|park)/.test(ql)) return "I don't have visual of parking from here. According to scout notes, accessible parking is available 30m to the right of the main entrance.";
    if (/(braille|tactile)/.test(ql)) return "I can see tactile guidance strips on the floor leading to the entrance. Braille signage near the door isn't visible from this angle — try moving closer.";
    if (/(staff|help|assist)/.test(ql)) return "I see staff members near the entrance, looking attentive. Scout notes confirm staff here are trained in disability awareness (Certified, 2024).";
    if (/(translate|hindi|language)/.test(ql)) return "The text I can see is in English. There's a Hindi version on the panel to the right — would you like me to read it out?";
    if (/(safe|safety)/.test(ql)) return "This area looks safe — well-lit, populated, with visible staff. No obstacles, no slippery surfaces, no construction.";
    return "I'm looking at what's in front of the camera. From what I can see, the path forward is clear and step-free. Want me to focus on something specific — doorways, signs, seating, or sensory load?";
  };

  const askQuestion = (qRaw) => {
    const q = qRaw.trim();
    if (!q) return;
    setThinking(true);
    setAnswer(null);
    setTimeout(() => {
      const a = generateAnswer(q);
      const ts = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
      setAnswer({ q, a, ts });
      setThinking(false);
      setQuestion('');
      speak(a);
    }, 900);
  };

  const startListening = () => {
    if (!sttSupported || listening) return;
    primeTTS();
    const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
    const rec = new SR();
    rec.lang = 'en-US';
    rec.continuous = false;
    rec.interimResults = true;
    rec.onresult = (e) => {
      const t = Array.from(e.results).map(r => r[0].transcript).join('');
      setQuestion(t);
      if (e.results[e.results.length - 1].isFinal) {
        askQuestion(t);
      }
    };
    rec.onerror = () => setListening(false);
    rec.onend = () => setListening(false);
    recRef.current = rec;
    try { rec.start(); setListening(true); } catch { setListening(false); }
  };
  const stopListening = () => {
    if (recRef.current) { try { recRef.current.stop(); } catch {} }
    setListening(false);
  };

  const startCamera = async (mode) => {
    if (!navigator.mediaDevices?.getUserMedia) {
      setStatus('unavailable');
      return;
    }
    try {
      if (streamRef.current) {
        streamRef.current.getTracks().forEach(t => t.stop());
      }
      const stream = await navigator.mediaDevices.getUserMedia({
        video: { facingMode: mode, width: { ideal: 1280 }, height: { ideal: 720 } },
        audio: false,
      });
      streamRef.current = stream;
      if (videoRef.current) {
        videoRef.current.srcObject = stream;
      }
      setStatus('live');
    } catch (e) {
      setStatus(e?.name === 'NotAllowedError' ? 'denied' : 'unavailable');
    }
  };

  shUseEffect(() => {
    startCamera(facingMode);
    return () => {
      if (streamRef.current) {
        streamRef.current.getTracks().forEach(t => t.stop());
      }
      stopSpeaking();
    };
    // eslint-disable-next-line
  }, []);

  const flipCamera = () => {
    const next = facingMode === 'user' ? 'environment' : 'user';
    setFacingMode(next);
    startCamera(next);
  };

  const analyze = () => {
    if (status !== 'live' || analyzing) return;
    setAnalyzing(true);
    setTimeout(() => {
      const r = LIVE_RESPONSES[respIdxRef.current % LIVE_RESPONSES.length];
      respIdxRef.current += 1;
      const ts = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
      setCurrent({ ...r, ts });
      // Speak the response (strip HTML tags first)
      const plain = (r.title + '. ' + r.body.replace(/<[^>]+>/g, ''));
      speak(plain);
      setAnalyzing(false);
    }, 1200);
  };

  // Auto-mode: kick off immediately when live, then every 5s
  shUseEffect(() => {
    if (!autoMode || status !== 'live') return;
    analyze();
    const id = setInterval(() => { if (!analyzing) analyze(); }, 5000);
    return () => clearInterval(id);
    // eslint-disable-next-line
  }, [autoMode, status]);

  return (
    <div className="camera-screen-wrap">
      <div className="camera-stage">
        <video
          ref={videoRef}
          autoPlay
          playsInline
          muted
          style={{
            width: '100%', height: '100%', objectFit: 'cover', display: 'block',
            transform: facingMode === 'user' ? 'scaleX(-1)' : 'none',
            background: '#000',
          }}
        />

        {/* Corner brackets */}
        {[0, 1, 2, 3].map(i => (
          <span key={i} aria-hidden="true" style={{
            position: 'absolute',
            width: 36, height: 36,
            borderTop: '2.5px solid rgba(255,255,255,0.9)',
            borderLeft: '2.5px solid rgba(255,255,255,0.9)',
            top: i < 2 ? 18 : 'auto',
            bottom: i >= 2 ? 18 : 'auto',
            left: i % 2 === 0 ? 18 : 'auto',
            right: i % 2 === 1 ? 18 : 'auto',
            transform: i === 1 ? 'rotate(90deg)' : i === 2 ? 'rotate(-90deg)' : i === 3 ? 'rotate(180deg)' : 'none',
            filter: 'drop-shadow(0 1px 2px rgba(0,0,0,0.4))',
          }} />
        ))}

        {/* Top status pill */}
        <div style={{ position: 'absolute', top: 14, left: 14, display: 'inline-flex', alignItems: 'center', gap: 8, padding: '6px 10px', background: 'rgba(0,0,0,0.6)', backdropFilter: 'blur(8px)', color: '#fff', borderRadius: 999, fontSize: 11.5, fontFamily: 'var(--font-mono)', textTransform: 'uppercase', letterSpacing: '0.12em', fontWeight: 700 }}>
          {status === 'live' ? (
            <>
              <span style={{ width: 8, height: 8, borderRadius: 999, background: '#FF4D4D', animation: 'pulseRing 1.6s infinite' }} />
              Live
            </>
          ) : status === 'requesting' ? (
            <>
              <span style={{ width: 8, height: 8, borderRadius: 999, background: 'var(--accent)' }} />
              Requesting camera…
            </>
          ) : (
            <>
              <span style={{ width: 8, height: 8, borderRadius: 999, background: 'var(--muted)' }} />
              Camera off
            </>
          )}
        </div>

        {/* Top-right controls */}
        <div style={{ position: 'absolute', top: 14, right: 14, display: 'flex', gap: 8, flexWrap: 'wrap', justifyContent: 'flex-end', maxWidth: 'calc(100% - 28px)' }}>
          <button
            onClick={() => { primeTTS(); setAskOpen(o => !o); if (askOpen) stopListening(); }}
            aria-pressed={askOpen}
            aria-label="Ask a question"
            style={{
              minWidth: 36, height: 36, padding: '0 12px',
              borderRadius: 999, border: 0,
              background: askOpen ? '#fff' : 'rgba(0,0,0,0.6)',
              color: askOpen ? 'var(--ink)' : '#fff',
              backdropFilter: 'blur(8px)', cursor: 'pointer',
              display: 'inline-flex', alignItems: 'center', gap: 6,
              fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 700, letterSpacing: '0.1em', textTransform: 'uppercase',
            }}
          >
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" width="14" height="14"><path d="M21 11.5a8.4 8.4 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.4 8.4 0 0 1-3.8-.9L3 21l1.9-5.7a8.4 8.4 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.4 8.4 0 0 1 3.8-.9h.5a8.5 8.5 0 0 1 8 8v.5Z"/></svg>
            Ask
          </button>
          <button
            onClick={flipCamera}
            disabled={status !== 'live'}
            aria-label="Flip camera"
            style={{ width: 36, height: 36, borderRadius: 999, border: 0, background: 'rgba(0,0,0,0.6)', backdropFilter: 'blur(8px)', color: '#fff', cursor: 'pointer', fontSize: 14, opacity: status === 'live' ? 1 : 0.5 }}
          >⇄</button>
          <button
            onClick={() => {
              setMuted(m => {
                const next = !m;
                mutedRef.current = next;
                if (next) {
                  stopSpeaking();
                } else {
                  // Unmute = user gesture. Prime TTS and immediately speak the current item if any.
                  primeTTS();
                  if (current) {
                    const plain = current.title + '. ' + current.body.replace(/<[^>]+>/g, '');
                    // tiny delay so the prime utterance completes first
                    setTimeout(() => {
                      if (!mutedRef.current) speak(plain);
                    }, 80);
                  }
                }
                return next;
              });
            }}
            aria-pressed={muted}
            aria-label={muted ? 'Unmute voice' : 'Mute voice'}
            title={muted ? 'Tap to enable voice' : 'Mute voice'}
            style={{
              minWidth: 36, height: 36, padding: muted ? '0 12px' : 0,
              borderRadius: 999, border: 0,
              background: muted ? 'var(--accent)' : 'rgba(0,0,0,0.6)',
              backdropFilter: 'blur(8px)',
              color: muted ? 'var(--ink)' : '#fff',
              cursor: 'pointer',
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6,
              fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 700, letterSpacing: '0.1em', textTransform: 'uppercase',
            }}
          >
            {muted ? (
              <>
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" width="14" height="14"><path d="M11 5 6 9H3v6h3l5 4Z"/><line x1="22" x2="16" y1="9" y2="15"/><line x1="16" x2="22" y1="9" y2="15"/></svg>
                <span>Listen</span>
              </>
            ) : (
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" width="16" height="16"><path d="M11 5 6 9H3v6h3l5 4Z"/><path d="M15.5 8.5a5 5 0 0 1 0 7"/><path d="M18.5 5.5a9 9 0 0 1 0 13"/></svg>
            )}
          </button>
          <button
            onClick={() => setAutoMode(m => !m)}
            disabled={status !== 'live'}
            aria-pressed={autoMode}
            aria-label="Toggle auto-describe"
            style={{
              padding: '0 12px', height: 36, borderRadius: 999, border: 0,
              background: autoMode ? 'var(--accent)' : 'rgba(0,0,0,0.6)',
              color: autoMode ? 'var(--ink)' : '#fff',
              fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 700, letterSpacing: '0.1em', textTransform: 'uppercase',
              cursor: 'pointer', backdropFilter: 'blur(8px)',
              opacity: status === 'live' ? 1 : 0.5,
            }}
          >
            {autoMode ? '● Auto · 5s' : 'Auto off'}
          </button>
        </div>

        {/* Ask panel */}
        {askOpen && (
          <div style={{
            position: 'absolute', left: 14, right: 14, bottom: 14, zIndex: 4,
            background: 'rgba(0,0,0,0.84)', backdropFilter: 'blur(14px)',
            color: '#fff', borderRadius: 16, padding: 14, maxHeight: '70%', overflow: 'auto',
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10.5, letterSpacing: '0.14em', color: 'var(--accent)', fontWeight: 700, textTransform: 'uppercase' }}>● Ask Wayfare</span>
              <button onClick={() => { setAskOpen(false); stopListening(); }} aria-label="Close" style={{ marginLeft: 'auto', background: 'transparent', border: 0, color: 'rgba(255,255,255,0.7)', fontSize: 18 }}>×</button>
            </div>
            <form onSubmit={(e) => { e.preventDefault(); askQuestion(question); }} style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
              <button
                type="button"
                onClick={() => listening ? stopListening() : startListening()}
                disabled={!sttSupported}
                aria-label={listening ? 'Stop listening' : 'Speak your question'}
                title={sttSupported ? '' : 'Voice not supported on this browser'}
                style={{
                  width: 40, height: 40, borderRadius: 999, border: 0, flexShrink: 0,
                  background: listening ? 'var(--emergency)' : 'var(--accent)', color: 'var(--ink)',
                  display: 'grid', placeItems: 'center',
                  animation: listening ? 'pulseRing 1.4s infinite' : 'none',
                  opacity: sttSupported ? 1 : 0.5,
                }}
              >
                <Icon.mic width="16" height="16" />
              </button>
              <input
                type="text"
                value={question}
                onChange={(e) => setQuestion(e.target.value)}
                placeholder={listening ? 'Listening…' : 'Ask anything about what you see'}
                style={{
                  flex: 1, padding: '10px 14px', borderRadius: 999, border: 0,
                  background: 'rgba(255,255,255,0.1)', color: '#fff', font: 'inherit', fontSize: 14,
                  outline: 'none',
                }}
              />
              <button
                type="submit"
                disabled={!question.trim() || thinking}
                aria-label="Send question"
                style={{ width: 40, height: 40, borderRadius: 999, border: 0, flexShrink: 0, background: '#fff', color: 'var(--ink)', display: 'grid', placeItems: 'center', opacity: question.trim() ? 1 : 0.5 }}
              >
                <Icon.arrow width="16" height="16" />
              </button>
            </form>
            {/* Suggested chips */}
            {!answer && !thinking && (
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 12 }}>
                {['Is the door wide enough?', 'How many steps?', 'How noisy is it?', 'Read the sign'].map(s => (
                  <button key={s} type="button" onClick={() => askQuestion(s)} style={{ padding: '6px 12px', borderRadius: 999, background: 'rgba(255,255,255,0.1)', color: '#fff', border: '1px solid rgba(255,255,255,0.18)', fontSize: 12, cursor: 'pointer' }}>{s}</button>
                ))}
              </div>
            )}
            {thinking && (
              <div style={{ marginTop: 12, display: 'inline-flex', alignItems: 'center', gap: 10 }}>
                <span className="wave" style={{ height: 18 }}><span style={{ background: '#fff' }} /><span style={{ background: '#fff' }} /><span style={{ background: '#fff' }} /><span style={{ background: '#fff' }} /></span>
                <span style={{ fontSize: 12, fontFamily: 'var(--font-mono)', letterSpacing: '0.1em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.7)' }}>Thinking</span>
              </div>
            )}
            {answer && !thinking && (
              <div style={{ marginTop: 12, padding: 12, borderRadius: 12, background: 'rgba(255,255,255,0.06)' }}>
                <div style={{ fontSize: 12, color: 'var(--accent)', fontFamily: 'var(--font-mono)', letterSpacing: '0.1em', textTransform: 'uppercase', marginBottom: 6 }}>You asked</div>
                <div style={{ fontSize: 13, color: 'rgba(255,255,255,0.85)', marginBottom: 10 }}>{answer.q}</div>
                <div style={{ fontSize: 12, color: 'var(--accent)', fontFamily: 'var(--font-mono)', letterSpacing: '0.1em', textTransform: 'uppercase', marginBottom: 6 }}>Wayfare AI answer</div>
                <p style={{ margin: 0, fontSize: 14.5, lineHeight: 1.55 }}>{answer.a}</p>
              </div>
            )}
          </div>
        )}

        {/* AI response overlay */}
        {current && !askOpen && (
          <div style={{
            position: 'absolute',
            left: 14, right: 14, bottom: 14,
            background: 'rgba(0,0,0,0.78)',
            backdropFilter: 'blur(12px)',
            color: '#fff',
            borderRadius: 16,
            padding: '14px 16px',
            maxHeight: '52%',
            overflow: 'auto',
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }}>
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10.5, letterSpacing: '0.14em', color: 'var(--accent)', fontWeight: 700, textTransform: 'uppercase' }}>● Wayfare vision</span>
              <span style={{ marginLeft: 'auto', fontSize: 11, color: 'rgba(255,255,255,0.55)', fontFamily: 'var(--font-mono)' }}>{current.ts}</span>
            </div>
            <p style={{ margin: 0, fontSize: 14.5, lineHeight: 1.55 }} dangerouslySetInnerHTML={{ __html: current.body }} />
          </div>
        )}

        {/* Analyzing overlay (subtle, replaces nothing) */}
        {analyzing && !current && (
          <div style={{
            position: 'absolute', left: 14, bottom: 14,
            display: 'inline-flex', alignItems: 'center', gap: 10,
            background: 'rgba(0,0,0,0.6)', backdropFilter: 'blur(8px)',
            color: '#fff', padding: '8px 14px', borderRadius: 999,
          }}>
            <span className="wave" style={{ height: 18 }}><span style={{ background: '#fff' }} /><span style={{ background: '#fff' }} /><span style={{ background: '#fff' }} /><span style={{ background: '#fff' }} /></span>
            <span style={{ fontSize: 12, fontFamily: 'var(--font-mono)', letterSpacing: '0.1em', textTransform: 'uppercase' }}>Looking</span>
          </div>
        )}

        {/* Permission states */}
        {status !== 'live' && (
          <div style={{
            position: 'absolute', inset: 0,
            background: 'linear-gradient(140deg, #1F4D3F, #0F2E25)',
            color: '#fff',
            display: 'grid', placeItems: 'center', padding: 24, textAlign: 'center',
          }}>
            {status === 'requesting' && (
              <div>
                <div style={{ width: 60, height: 60, borderRadius: 999, background: 'rgba(255,255,255,0.15)', display: 'grid', placeItems: 'center', margin: '0 auto', position: 'relative' }}>
                  <Icon.camera width="28" height="28" />
                  <span style={{ position: 'absolute', inset: 0, borderRadius: 999, border: '2px solid #fff', animation: 'pulseRing 1.4s infinite' }} />
                </div>
                <p style={{ fontFamily: 'var(--font-serif)', fontSize: 20, marginTop: 14 }}>Allow camera access to begin.</p>
              </div>
            )}
            {status === 'denied' && (
              <div>
                <p style={{ fontFamily: 'var(--font-serif)', fontSize: 22 }}>Camera permission denied</p>
                <button onClick={() => startCamera(facingMode)} className="btn btn--accent btn--sm" style={{ marginTop: 12 }}>Retry</button>
              </div>
            )}
            {status === 'unavailable' && (
              <div>
                <p style={{ fontFamily: 'var(--font-serif)', fontSize: 22 }}>No camera available</p>
                <button onClick={() => { setCurrent({ ...LIVE_RESPONSES[0], ts: 'demo' }); }} className="btn btn--accent btn--sm" style={{ marginTop: 12 }}>Run demo</button>
              </div>
            )}
          </div>
        )}
      </div>
    </div>
  );
}


function captureThumbnail(videoEl) {
  if (!videoEl || videoEl.readyState < 2) return null;
  try {
    const w = 320;
    const h = Math.round(w * (videoEl.videoHeight / videoEl.videoWidth));
    const c = document.createElement('canvas');
    c.width = w; c.height = h;
    const ctx = c.getContext('2d');
    ctx.drawImage(videoEl, 0, 0, w, h);
    return c.toDataURL('image/jpeg', 0.7);
  } catch {
    return null;
  }
}

/* ============================================================
   Screen: Trips
   ============================================================ */
function TripsScreen({ onOpen }) {
  const trips = [
    {
      title: 'Jaipur — 3 days · accessible heritage',
      dates: '14 – 16 Mar 2026',
      status: 'In planning',
      avgScore: 87,
      stops: 8,
      accent: '#C68B59',
      photo: 'palace',
      planId: 'heritage',
    },
    {
      title: 'Goa — 5 days · sensory-friendly',
      dates: '02 – 06 Feb 2026',
      status: 'Completed',
      avgScore: 91,
      stops: 7,
      accent: '#7BAA80',
      photo: 'city',
      planId: 'slow',
    },
    {
      title: 'Bangalore — weekend outdoor crawl',
      dates: '23 – 24 Nov 2025',
      status: 'Completed',
      avgScore: 84,
      stops: 9,
      accent: '#3A7CA5',
      photo: 'fort',
      planId: 'outdoor',
    },
  ];
  return (
    <div className="app-content" style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16, flexWrap: 'wrap' }}>
        <div>
          <span className="eyebrow">Your trips</span>
          <h2 className="h-section" style={{ fontSize: 'clamp(28px, 3.5vw, 44px)', marginTop: 8 }}>3 trips planned with Wayfare.</h2>
        </div>
        <button className="btn">+ New trip</button>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))', gap: 16 }}>
        {trips.map(t => (
          <button key={t.title} onClick={() => onOpen(t.planId)} className="venue-card" style={{ font: 'inherit', color: 'inherit', textAlign: 'left' }}>
            <VenuePhoto kind={t.photo} accent={t.accent} height={160} />
            <div className="venue-card__body">
              <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                <span className="chip" style={{ fontSize: 11, padding: '2px 8px', background: t.status === 'Completed' ? 'var(--primary-soft)' : 'var(--accent)', color: t.status === 'Completed' ? 'var(--primary)' : 'var(--ink)', borderColor: 'transparent' }}>{t.status}</span>
                <span style={{ fontSize: 12, color: 'var(--muted)' }}>{t.dates}</span>
              </div>
              <strong style={{ fontFamily: 'var(--font-serif)', fontSize: 19, fontWeight: 500, lineHeight: 1.2 }}>{t.title}</strong>
              <div style={{ display: 'flex', gap: 14, fontSize: 13 }}>
                <span><strong>{t.stops}</strong> stops</span>
                <span style={{ color: 'var(--muted)' }}>·</span>
                <span><strong>{t.avgScore}</strong> avg Wayfare</span>
              </div>
              <span className="btn btn--sm btn--ghost" style={{ marginTop: 8, alignSelf: 'flex-start' }}>Open itinerary →</span>
            </div>
          </button>
        ))}
      </div>
    </div>
  );
}

/* ============================================================
   Screen: Saved venues
   ============================================================ */
function SavedScreen({ onOpenVenue }) {
  const saved = VENUE_DATA.slice(0, 3);
  return (
    <div className="app-content" style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
      <div>
        <span className="eyebrow">Saved</span>
        <h2 className="h-section" style={{ fontSize: 'clamp(28px, 3.5vw, 44px)', marginTop: 8 }}>Venues you've bookmarked.</h2>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(260px, 1fr))', gap: 16 }}>
        {saved.map(v => (
          <button key={v.id} onClick={() => onOpenVenue(v)} className="venue-card" style={{ font: 'inherit', color: 'inherit', textAlign: 'left' }}>
            <VenuePhoto kind={v.photo} accent={v.accent} height={140} label={v.type} />
            <div className="venue-card__body">
              <div style={{ display: 'flex', alignItems: 'flex-start', gap: 8 }}>
                <strong style={{ fontFamily: 'var(--font-serif)', fontSize: 17, fontWeight: 500, flex: 1, lineHeight: 1.2 }}>{v.name}</strong>
                <ScorePill score={v.score} />
              </div>
              <div style={{ fontSize: 12.5, color: 'var(--muted)' }}>{v.area}</div>
            </div>
          </button>
        ))}
      </div>
    </div>
  );
}

/* ============================================================
   Screen: Scouts
   ============================================================ */
function ScoutsScreen() {
  const scouts = [
    { name: 'Aisha Verma', tag: 'Wheelchair user · Hotelier · Jaipur', visits: 142, areas: ['Hotels', 'Heritage'], color: '#1F4D3F', photo: 'https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=300&h=300&fit=crop&auto=format' },
    { name: 'Rohan Kapoor', tag: 'Power chair · Heritage guide · Jaipur', visits: 64, areas: ['Attractions'], color: '#C68B59', photo: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=300&h=300&fit=crop&auto=format' },
    { name: 'Maya Iyer', tag: 'Autistic adult · Food critic · Jaipur', visits: 211, areas: ['Cafés', 'Sensory'], color: '#7BAA80', photo: 'https://images.unsplash.com/photo-1544005313-94ddf0286df2?w=300&h=300&fit=crop&auto=format' },
    { name: 'Priya Singh', tag: 'Manual chair · Mobility lead', visits: 38, areas: ['Transport'], color: '#3A7CA5', photo: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=300&h=300&fit=crop&auto=format' },
  ];
  return (
    <div className="app-content" style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
      <div>
        <span className="eyebrow">The trust layer</span>
        <h2 className="h-section" style={{ fontSize: 'clamp(28px, 3.5vw, 44px)', marginTop: 8, maxWidth: '20ch' }}>Wayfare scouts auditing Jaipur right now.</h2>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(240px, 1fr))', gap: 14 }}>
        {scouts.map(s => (
          <div key={s.name} className="card">
            <ScoutAvatar name={s.name} photo={s.photo} color={s.color} size={64} />
            <h3 style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 19, margin: '16px 0 2px' }}>{s.name}</h3>
            <p style={{ color: 'var(--muted)', fontSize: 13, margin: 0 }}>{s.tag}</p>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4, marginTop: 12 }}>
              {s.areas.map(a => <span key={a} style={{ fontSize: 11, padding: '3px 8px', background: 'var(--bg-alt)', borderRadius: 999 }}>{a}</span>)}
            </div>
            <div style={{ marginTop: 14, paddingTop: 12, borderTop: '1.5px solid var(--line)', fontSize: 13, display: 'flex', alignItems: 'center', gap: 6 }}>
              <Icon.shield width="14" height="14" /> <strong>{s.visits}</strong> verified visits
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ============================================================
   Screen: Profile
   ============================================================ */
function ProfileScreen({ session, onUpdate }) {
  const [needs, setNeeds] = shUseState(session.needs || []);
  const toggle = (k) => {
    const next = needs.includes(k) ? needs.filter(n => n !== k) : [...needs, k];
    setNeeds(next);
    const updated = { ...session, needs: next };
    WayfareSession.set(updated);
    onUpdate(updated);
  };

  return (
    <div className="app-content" style={{ display: 'flex', flexDirection: 'column', gap: 24 }}>
      <div>
        <span className="eyebrow">Your profile</span>
        <h2 className="h-section" style={{ fontSize: 'clamp(28px, 3.5vw, 44px)', marginTop: 8 }}>{session.name}</h2>
        <p style={{ color: 'var(--muted)', marginTop: 4 }}>{session.email}</p>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', gap: 16 }}>
        <div className="card">
          <h3 style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 19, margin: '0 0 14px' }}>Accessibility profile</h3>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
            {NEED_OPTIONS.map(opt => (
              <button key={opt.key} className="chip" aria-pressed={needs.includes(opt.key)} onClick={() => toggle(opt.key)}>{opt.label}</button>
            ))}
          </div>
          <p style={{ fontSize: 12.5, color: 'var(--muted)', marginTop: 14 }}>Stored on this device only. Used to filter and score recommendations.</p>
        </div>

        <div className="card">
          <h3 style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 19, margin: '0 0 14px' }}>Emergency contacts</h3>
          {(session.emergency || []).length === 0 ? (
            <p style={{ color: 'var(--muted)', fontSize: 14 }}>No contacts added yet.</p>
          ) : (
            <div style={{ display: 'grid', gap: 8 }}>
              {session.emergency.map((c, i) => (
                <div key={i} style={{ display: 'flex', justifyContent: 'space-between', padding: '10px 12px', background: 'var(--bg-alt)', borderRadius: 10, fontSize: 13.5 }}>
                  <strong>{c.name}</strong>
                  <span style={{ color: 'var(--muted)', fontFamily: 'var(--font-mono)' }}>{c.phone}</span>
                </div>
              ))}
            </div>
          )}
          <button className="btn btn--ghost btn--sm" style={{ marginTop: 12 }}>+ Add contact</button>
        </div>

        <div className="card card--ink">
          <h3 style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 19, margin: '0 0 14px', color: 'inherit' }}>Data & privacy</h3>
          <ul style={{ margin: 0, padding: 0, listStyle: 'none', display: 'grid', gap: 10, fontSize: 13.5 }}>
            <li style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <span style={{ width: 18, height: 18, borderRadius: 999, background: 'var(--success)', color: '#fff', display: 'grid', placeItems: 'center' }}><Icon.check width="10" height="10" /></span>
              Profile stored locally
            </li>
            <li style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <span style={{ width: 18, height: 18, borderRadius: 999, background: 'var(--success)', color: '#fff', display: 'grid', placeItems: 'center' }}><Icon.check width="10" height="10" /></span>
              Queries to Wayfare AI are anonymous
            </li>
            <li style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <span style={{ width: 18, height: 18, borderRadius: 999, background: 'var(--success)', color: '#fff', display: 'grid', placeItems: 'center' }}><Icon.check width="10" height="10" /></span>
              Emergency mode shares only when you tap
            </li>
          </ul>
          <button className="btn btn--accent btn--sm" style={{ marginTop: 16 }}>Export my data</button>
        </div>
      </div>
    </div>
  );
}

/* ============================================================
   Screen: Scout — Requests (Accept / Reject)
   ============================================================ */
const SCOUT_REQUESTS_SEED = [
  {
    id: 'r-001',
    traveller: { name: 'Anika Rao', initials: 'AR', tag: 'Wheelchair user · solo · first visit to Jaipur', photo: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200&h=200&fit=crop&auto=format' },
    trip: 'Jaipur · accessible heritage',
    dates: '14 – 16 Mar 2026',
    days: 3,
    role: 'Primary scout · full trip',
    fee: '₹12,500',
    needs: ['Wheelchair', 'Step-free', 'Calm spaces'],
    note: "Wheelchair user, first visit. Need someone warm for the airport pickup → 3-day handhold. I get tired by 5pm.",
    received: '2 hrs ago',
    urgency: 'new',
  },
  {
    id: 'r-002',
    traveller: { name: 'Marc & Elena Fischer', initials: 'MF', tag: 'Mother (low vision) + son · 5 days', photo: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?w=200&h=200&fit=crop&auto=format' },
    trip: 'Jaipur · slow + sensory',
    dates: '22 – 26 Apr 2026',
    days: 5,
    role: 'Day scout · 2 days only',
    fee: '₹8,400',
    needs: ['Low vision', 'Audio description', 'Calm spaces'],
    note: "We'd love a slow-paced 2 days of crafts + cafés. My mother reads braille — any tactile museum tips appreciated.",
    received: 'Yesterday',
    urgency: 'normal',
  },
  {
    id: 'r-003',
    traveller: { name: 'Ravi Bhatia', initials: 'RB', tag: 'Power chair user · heritage focus', photo: 'https://images.unsplash.com/photo-1463453091185-61582044d556?w=200&h=200&fit=crop&auto=format' },
    trip: 'Jaipur · Amer + Nahargarh',
    dates: '02 – 03 Jun 2026',
    days: 2,
    role: 'Heritage day scout',
    fee: '₹6,200',
    needs: ['Power chair', 'Step-free', 'Lift access'],
    note: 'Wayfare auto-matched me to you after the Amer Fort tour with Rohan got booked out. Could you cover instead?',
    received: '3 days ago',
    urgency: 'normal',
  },
];

function RequestCard({ req, status, onAccept, onReject, onUndo }) {
  const accent = req.urgency === 'new' ? 'var(--accent)' : 'var(--line)';
  const decided = status === 'accepted' || status === 'rejected';
  return (
    <article
      className="card"
      style={{
        display: 'grid',
        gridTemplateColumns: 'minmax(0, 1fr)',
        gap: 18,
        position: 'relative',
        borderLeft: `4px solid ${status === 'accepted' ? 'var(--success)' : status === 'rejected' ? 'var(--line)' : accent}`,
        opacity: status === 'rejected' ? 0.6 : 1,
        transition: 'opacity .2s',
      }}
    >
      {/* Status ribbon */}
      {decided && (
        <div style={{ position: 'absolute', top: 14, right: 14, display: 'flex', alignItems: 'center', gap: 8 }}>
          <span
            style={{
              fontSize: 11,
              fontFamily: 'var(--font-mono)',
              letterSpacing: '0.12em',
              textTransform: 'uppercase',
              fontWeight: 700,
              padding: '4px 10px',
              borderRadius: 999,
              background: status === 'accepted' ? 'var(--success)' : 'var(--ink)',
              color: '#fff',
            }}
          >
            {status === 'accepted' ? '● Accepted' : '✕ Rejected'}
          </span>
          <button className="btn btn--ghost btn--sm" onClick={() => onUndo(req.id)} style={{ padding: '4px 10px', fontSize: 12 }}>
            Undo
          </button>
        </div>
      )}

      {/* Header row: traveller */}
      <div style={{ display: 'flex', gap: 14, alignItems: 'flex-start' }}>
        <ScoutAvatar name={req.traveller.name} photo={req.traveller.photo} color="#3A7CA5" size={52} />
        <div style={{ minWidth: 0, flex: 1, paddingRight: decided ? 140 : 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
            <strong style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 20, lineHeight: 1.1 }}>{req.traveller.name}</strong>
            {req.urgency === 'new' && !decided && (
              <span style={{ fontSize: 10, fontFamily: 'var(--font-mono)', letterSpacing: '0.14em', textTransform: 'uppercase', fontWeight: 700, padding: '2px 7px', borderRadius: 999, background: 'var(--accent)', color: 'var(--ink)' }}>NEW</span>
            )}
          </div>
          <p style={{ margin: '2px 0 0', fontSize: 13, color: 'var(--muted)' }}>{req.traveller.tag}</p>
        </div>
      </div>

      {/* Trip facts grid */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(140px, 1fr))', gap: 14, padding: '14px 16px', background: 'var(--bg-alt)', borderRadius: 12 }}>
        <div>
          <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--muted)', fontWeight: 700 }}>Trip</div>
          <div style={{ fontFamily: 'var(--font-serif)', fontSize: 15, marginTop: 4, lineHeight: 1.25 }}>{req.trip}</div>
        </div>
        <div>
          <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--muted)', fontWeight: 700 }}>Dates</div>
          <div style={{ fontSize: 14, marginTop: 4 }}>{req.dates}</div>
        </div>
        <div>
          <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--muted)', fontWeight: 700 }}>Role</div>
          <div style={{ fontSize: 14, marginTop: 4 }}>{req.role}</div>
        </div>
        <div>
          <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--muted)', fontWeight: 700 }}>Estimated fee</div>
          <div style={{ fontSize: 16, marginTop: 4, fontFamily: 'var(--font-serif)', fontWeight: 500, color: 'var(--primary)' }}>{req.fee}</div>
        </div>
      </div>

      {/* Needs */}
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
        {req.needs.map(n => (
          <span key={n} className="chip" style={{ fontSize: 12 }}>{n}</span>
        ))}
      </div>

      {/* Traveller note */}
      <blockquote style={{ margin: 0, padding: '12px 16px', borderLeft: '3px solid var(--primary)', background: 'var(--primary-soft)', borderRadius: '0 10px 10px 0', fontFamily: 'var(--font-serif)', fontStyle: 'italic', fontSize: 15, lineHeight: 1.5, color: 'var(--primary-deep)' }}>
        "{req.note}"
      </blockquote>

      {/* Footer: timestamp + actions */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap' }}>
        <span style={{ fontSize: 12, color: 'var(--muted)', fontFamily: 'var(--font-mono)' }}>Received {req.received}</span>
        {!decided && (
          <div style={{ display: 'flex', gap: 8 }}>
            <button className="btn btn--ghost btn--sm" onClick={() => onReject(req.id)}>
              ✕ Reject
            </button>
            <button className="btn btn--sm" onClick={() => onAccept(req.id)}>
              ✓ Accept request
            </button>
          </div>
        )}
      </div>
    </article>
  );
}

function RequestsScreen({ session, onToast }) {
  const [decisions, setDecisions] = shUseState(() => {
    try { return JSON.parse(localStorage.getItem('wayfare:scoutDecisions') || '{}'); }
    catch { return {}; }
  });

  const persist = (next) => {
    setDecisions(next);
    localStorage.setItem('wayfare:scoutDecisions', JSON.stringify(next));
  };

  const decide = (id, status) => {
    const next = { ...decisions, [id]: status };
    persist(next);
    onToast?.(status === 'accepted' ? 'Request accepted. Traveller notified.' : 'Request declined.');
  };
  const undo = (id) => {
    const next = { ...decisions };
    delete next[id];
    persist(next);
  };

  const pending = SCOUT_REQUESTS_SEED.filter(r => !decisions[r.id]);
  const accepted = SCOUT_REQUESTS_SEED.filter(r => decisions[r.id] === 'accepted');
  const rejected = SCOUT_REQUESTS_SEED.filter(r => decisions[r.id] === 'rejected');

  return (
    <div className="app-content" style={{ display: 'flex', flexDirection: 'column', gap: 28 }}>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 16, flexWrap: 'wrap' }}>
        <div>
          <span className="eyebrow">Scout inbox</span>
          <h2 className="h-section" style={{ fontSize: 'clamp(28px, 3.5vw, 44px)', marginTop: 8, maxWidth: '20ch' }}>
            {pending.length} travellers are <em>waiting for you</em>.
          </h2>
          <p style={{ color: 'var(--muted)', marginTop: 8, fontSize: 14, maxWidth: '52ch' }}>
            Wayfare matched you on lived experience, city and audit needs. Accept what fits your calendar — decline the rest, no penalty.
          </p>
        </div>
        <div style={{ display: 'flex', gap: 24, padding: '14px 18px', background: 'var(--ink)', color: 'var(--bg)', borderRadius: 12 }}>
          <div>
            <div style={{ fontSize: 11, fontFamily: 'var(--font-mono)', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--accent)', fontWeight: 700 }}>Acceptance</div>
            <div style={{ fontFamily: 'var(--font-serif)', fontSize: 24, fontWeight: 500, marginTop: 2 }}>92<span style={{ fontSize: 14, color: 'rgba(255,255,255,0.6)' }}>%</span></div>
          </div>
          <div style={{ width: 1, background: 'rgba(255,255,255,0.16)' }} />
          <div>
            <div style={{ fontSize: 11, fontFamily: 'var(--font-mono)', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--accent)', fontWeight: 700 }}>Avg response</div>
            <div style={{ fontFamily: 'var(--font-serif)', fontSize: 24, fontWeight: 500, marginTop: 2 }}>3.2<span style={{ fontSize: 14, color: 'rgba(255,255,255,0.6)' }}>h</span></div>
          </div>
        </div>
      </div>

      {/* Pending section */}
      {pending.length > 0 && (
        <section style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, flexWrap: 'wrap' }}>
            <h3 style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 22, margin: 0 }}>Awaiting your decision</h3>
            <span style={{ fontSize: 12, padding: '2px 10px', background: 'var(--accent)', color: 'var(--ink)', borderRadius: 999, fontWeight: 700 }}>{pending.length}</span>
          </div>
          <div style={{ display: 'grid', gap: 16 }}>
            {pending.map(req => (
              <RequestCard key={req.id} req={req} status="pending" onAccept={(id) => decide(id, 'accepted')} onReject={(id) => decide(id, 'rejected')} onUndo={undo} />
            ))}
          </div>
        </section>
      )}

      {/* Already accepted */}
      {accepted.length > 0 && (
        <section style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          <h3 style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 19, margin: 0, color: 'var(--success)' }}>● Recently accepted · added to My trips</h3>
          <div style={{ display: 'grid', gap: 12 }}>
            {accepted.map(req => (
              <RequestCard key={req.id} req={req} status="accepted" onUndo={undo} />
            ))}
          </div>
        </section>
      )}

      {/* Recently rejected */}
      {rejected.length > 0 && (
        <section style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          <h3 style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 19, margin: 0, color: 'var(--muted)' }}>Recently declined</h3>
          <div style={{ display: 'grid', gap: 12 }}>
            {rejected.map(req => (
              <RequestCard key={req.id} req={req} status="rejected" onUndo={undo} />
            ))}
          </div>
        </section>
      )}

      {pending.length === 0 && accepted.length === 0 && rejected.length === 0 && (
        <div className="card" style={{ textAlign: 'center', padding: '48px 24px' }}>
          <div style={{ fontSize: 28, marginBottom: 8 }}>✦</div>
          <strong style={{ fontFamily: 'var(--font-serif)', fontSize: 20, fontWeight: 500 }}>No new requests right now.</strong>
          <p style={{ color: 'var(--muted)', marginTop: 8 }}>We'll notify you the moment a traveller is matched.</p>
        </div>
      )}
    </div>
  );
}

/* ============================================================
   Screen: Scout — My trips (accepted assignments)
   ============================================================ */
function ScoutTripsScreen({ session }) {
  const [decisions] = shUseState(() => {
    try { return JSON.parse(localStorage.getItem('wayfare:scoutDecisions') || '{}'); }
    catch { return {}; }
  });

  // Base bookings + any newly-accepted requests promoted into trips
  const BASE_TRIPS = [
    {
      id: 't-001',
      traveller: 'Sophie Laurent',
      photo: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=200&h=200&fit=crop&auto=format',
      trip: 'Jaipur · accessible heritage',
      dates: '18 – 20 Mar 2026',
      role: 'Primary scout · full trip',
      status: 'Upcoming',
      fee: '₹12,500',
      stops: 8,
      needs: ['Wheelchair', 'Step-free'],
      accent: '#C68B59',
      photoKind: 'palace',
      countdown: '2 days',
    },
    {
      id: 't-002',
      traveller: 'Kenji & Yumi Tanaka',
      photo: 'https://images.unsplash.com/photo-1544005313-94ddf0286df2?w=200&h=200&fit=crop&auto=format',
      trip: 'Jaipur · slow + sensory',
      dates: '04 – 06 Mar 2026',
      role: 'Day scout · café crawl',
      status: 'In progress',
      fee: '₹4,200',
      stops: 4,
      needs: ['Calm spaces', 'Audio description'],
      accent: '#7BAA80',
      photoKind: 'city',
      countdown: 'Today',
    },
    {
      id: 't-003',
      traveller: 'Aarav Kapoor',
      photo: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=200&h=200&fit=crop&auto=format',
      trip: 'Jaipur · weekend heritage',
      dates: '24 – 25 Jan 2026',
      role: 'Heritage day scout',
      status: 'Completed',
      fee: '₹5,800',
      stops: 6,
      needs: ['Power chair'],
      accent: '#3A7CA5',
      photoKind: 'fort',
      countdown: 'Paid',
    },
  ];

  // Promote accepted requests to trip cards
  const acceptedExtras = SCOUT_REQUESTS_SEED
    .filter(r => decisions[r.id] === 'accepted')
    .map(r => ({
      id: 'ext-' + r.id,
      traveller: r.traveller.name,
      photo: r.traveller.photo,
      trip: r.trip,
      dates: r.dates,
      role: r.role,
      status: 'Confirmed',
      fee: r.fee,
      stops: r.days * 3,
      needs: r.needs.slice(0, 2),
      accent: '#1F4D3F',
      photoKind: 'palace',
      countdown: 'Just accepted',
    }));

  const trips = [...acceptedExtras, ...BASE_TRIPS];

  const upcoming = trips.filter(t => t.status === 'Upcoming' || t.status === 'In progress' || t.status === 'Confirmed');
  const past = trips.filter(t => t.status === 'Completed');

  const earningsThisMonth = '₹38,200';
  const tripsThisMonth = upcoming.length + past.length;

  const card = (t) => {
    const statusColor =
      t.status === 'In progress' ? 'var(--success)' :
      t.status === 'Confirmed' ? 'var(--accent)' :
      t.status === 'Completed' ? 'var(--primary-soft)' : 'var(--bg-alt)';
    const statusFg =
      t.status === 'In progress' ? '#fff' :
      t.status === 'Completed' ? 'var(--primary)' : 'var(--ink)';
    return (
      <article key={t.id} className="venue-card">
        <VenuePhoto kind={t.photoKind} accent={t.accent} height={140} />
        <div className="venue-card__body">
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
            <span className="chip" style={{ fontSize: 11, padding: '2px 8px', background: statusColor, color: statusFg, borderColor: 'transparent', fontWeight: 700 }}>{t.status}</span>
            <span style={{ fontSize: 12, color: 'var(--muted)' }}>{t.dates}</span>
          </div>
          <strong style={{ fontFamily: 'var(--font-serif)', fontSize: 19, fontWeight: 500, lineHeight: 1.2 }}>{t.trip}</strong>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 4 }}>
            <ScoutAvatar name={t.traveller} photo={t.photo} color={t.accent} size={32} />
            <div style={{ minWidth: 0 }}>
              <div style={{ fontSize: 13.5, fontWeight: 600 }}>{t.traveller}</div>
              <div style={{ fontSize: 12, color: 'var(--muted)' }}>{t.role}</div>
            </div>
          </div>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4, marginTop: 4 }}>
            {t.needs.map(n => <span key={n} style={{ fontSize: 11, padding: '3px 8px', background: 'var(--bg-alt)', borderRadius: 999 }}>{n}</span>)}
          </div>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 8, paddingTop: 12, borderTop: '1.5px solid var(--line)' }}>
            <div>
              <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--muted)', fontWeight: 700 }}>{t.status === 'Completed' ? 'Earned' : 'Fee'}</div>
              <div style={{ fontFamily: 'var(--font-serif)', fontSize: 18, fontWeight: 500, color: 'var(--primary)' }}>{t.fee}</div>
            </div>
            <div style={{ textAlign: 'right' }}>
              <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--muted)', fontWeight: 700 }}>{t.status === 'Completed' ? 'Status' : 'Starts'}</div>
              <div style={{ fontSize: 13.5, fontWeight: 600 }}>{t.countdown}</div>
            </div>
          </div>
          <span className="btn btn--sm btn--ghost" style={{ marginTop: 8, alignSelf: 'flex-start' }}>Open brief →</span>
        </div>
      </article>
    );
  };

  return (
    <div className="app-content" style={{ display: 'flex', flexDirection: 'column', gap: 24 }}>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 16, flexWrap: 'wrap' }}>
        <div>
          <span className="eyebrow">Your assignments</span>
          <h2 className="h-section" style={{ fontSize: 'clamp(28px, 3.5vw, 44px)', marginTop: 8 }}>My trips</h2>
          <p style={{ color: 'var(--muted)', marginTop: 6, fontSize: 14 }}>Travellers you've accepted, in chronological order.</p>
        </div>
        <div style={{ display: 'flex', gap: 24, padding: '14px 18px', background: 'var(--primary-soft)', borderRadius: 12 }}>
          <div>
            <div style={{ fontSize: 11, fontFamily: 'var(--font-mono)', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--primary)', fontWeight: 700 }}>This month</div>
            <div style={{ fontFamily: 'var(--font-serif)', fontSize: 24, fontWeight: 500, marginTop: 2, color: 'var(--primary-deep)' }}>{earningsThisMonth}</div>
          </div>
          <div style={{ width: 1, background: 'var(--line)' }} />
          <div>
            <div style={{ fontSize: 11, fontFamily: 'var(--font-mono)', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--primary)', fontWeight: 700 }}>Trips</div>
            <div style={{ fontFamily: 'var(--font-serif)', fontSize: 24, fontWeight: 500, marginTop: 2, color: 'var(--primary-deep)' }}>{tripsThisMonth}</div>
          </div>
        </div>
      </div>

      {upcoming.length > 0 && (
        <section>
          <h3 style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 22, margin: '0 0 14px' }}>Upcoming & live</h3>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: 16 }}>
            {upcoming.map(card)}
          </div>
        </section>
      )}

      {past.length > 0 && (
        <section>
          <h3 style={{ fontFamily: 'var(--font-serif)', fontWeight: 500, fontSize: 22, margin: '0 0 14px' }}>Past trips</h3>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: 16 }}>
            {past.map(card)}
          </div>
        </section>
      )}
    </div>
  );
}

/* ============================================================
   App shell
   ============================================================ */
function WayfareApp() {
  const [session, setSession] = shUseState(null);
  const [active, setActive] = shUseState('plan');
  const [resultsCtx, setResultsCtx] = shUseState(null);
  const [activeVenue, setActiveVenue] = shUseState(null);
  const [emergencyOpen, setEmergencyOpen] = shUseState(false);
  const [toast, setToast] = shUseState('');
  const [sidebarOpen, setSidebarOpen] = shUseState(false);

  shUseEffect(() => {
    const s = WayfareSession.get();
    if (!s) {
      window.location.href = 'Sign In.html';
      return;
    }
    setSession(s);
    // Scouts land on Requests by default
    if (s.role === 'scout') setActive('requests');
    document.documentElement.setAttribute('data-theme', localStorage.getItem('wayfare:theme') || 'soft');
    document.documentElement.style.setProperty('--font-scale', localStorage.getItem('wayfare:fontScale') || '1');
  }, []);

  shUseEffect(() => {
    if (!toast) return;
    const t = setTimeout(() => setToast(''), 2200);
    return () => clearTimeout(t);
  }, [toast]);

  const onSignOut = () => {
    WayfareSession.clear();
    window.location.href = 'Wayfare.html';
  };

  if (!session) return null;

  const titles = {
    plan: 'Plan',
    trips: session.role === 'scout' ? 'My trips' : 'Your trips',
    camera: 'Camera AI guide',
    scouts: 'Wayfare scouts',
    requests: 'Requests',
    profile: 'Profile',
    results: 'Itinerary',
    detail: activeVenue?.name || 'Detail',
  };
  const showingTitle = activeVenue ? (activeVenue.name) : resultsCtx ? 'Your itinerary' : titles[active];

  const goNav = (k) => { setActiveVenue(null); setResultsCtx(null); setActive(k); };

  const isScout = session.role === 'scout';

  return (
    <div className="app-shell">
      <div className={'sidebar-backdrop' + (sidebarOpen ? ' is-open' : '')} onClick={() => setSidebarOpen(false)} aria-hidden="true" />
      <Sidebar active={active} onNav={goNav} session={session} onSignOut={onSignOut} open={sidebarOpen} onClose={() => setSidebarOpen(false)} />
      <main className="app-main">
        <Topbar title={showingTitle} session={session} onProfile={() => { goNav(isScout ? 'requests' : 'profile'); }} onMenuToggle={() => setSidebarOpen(o => !o)} />

        {isScout ? (
          active === 'requests' ? (
            <RequestsScreen session={session} onToast={setToast} />
          ) : active === 'trips' ? (
            <ScoutTripsScreen session={session} />
          ) : (
            <RequestsScreen session={session} onToast={setToast} />
          )
        ) : activeVenue ? (
          <DetailScreen venue={activeVenue} onBack={() => setActiveVenue(null)} onToast={setToast} />
        ) : resultsCtx ? (
          <ResultsScreen context={resultsCtx} session={session} onOpenVenue={setActiveVenue} onCamera={() => { setResultsCtx(null); setActive('camera'); }} />
        ) : active === 'plan' ? (
          <PlanScreen session={session} onResults={(ctx) => setResultsCtx(ctx)} />
        ) : active === 'trips' ? (
          <TripsScreen onOpen={(planId) => { setActiveVenue(null); setResultsCtx({ planId, startInView: true }); }} />
        ) : active === 'camera' ? (
          <CameraScreen />
        ) : active === 'scouts' ? (
          <ScoutsScreen />
        ) : active === 'profile' ? (
          <ProfileScreen session={session} onUpdate={setSession} />
        ) : null}
      </main>

      {!isScout && <EmergencyFAB onClick={() => setEmergencyOpen(true)} />}
      {!isScout && <CameraFAB onClick={() => { setActiveVenue(null); setResultsCtx(null); setActive('camera'); }} />}
      {!isScout && <EmergencyModal open={emergencyOpen} onClose={() => setEmergencyOpen(false)} />}

      {toast && <div className="toast"><Icon.check /> {toast}</div>}
    </div>
  );
}

Object.assign(window, { WayfareApp });
