// ============================================================================
// Screens v2 — Place Detail + Lightbox + all secondary screens
// ============================================================================

const { useState: pS, useEffect: pE, useMemo: pM, useRef: pR } = React;

// ---------- LIGHTBOX ----------
function Lightbox({ images, startIndex = 0, onClose }) {
  const [i, setI] = pS(startIndex);
  pE(() => {
    const h = (e) => {
      if (e.key === 'Escape') onClose();
      if (e.key === 'ArrowLeft') setI((x) => Math.max(0, x - 1));
      if (e.key === 'ArrowRight') setI((x) => Math.min(images.length - 1, x + 1));
    };
    window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, [images.length]);
  const img = images[i];
  if (!img) return null;
  return (
    <div className="lightbox" onClick={onClose}>
      <img src={img.src} alt={img.alt} onClick={(e) => e.stopPropagation()} />
      {img.alt && <div className="lb-caption">{img.alt}</div>}
      <button className="lb-close" onClick={onClose}><Icon name="close" size={18} /></button>
      {i > 0 && (
        <button className="lb-nav prev" onClick={(e) => { e.stopPropagation(); setI(i - 1); }}>
          <Icon name="back" size={18} />
        </button>
      )}
      {i < images.length - 1 && (
        <button className="lb-nav next" onClick={(e) => { e.stopPropagation(); setI(i + 1); }}>
          <Icon name="chev" size={18} />
        </button>
      )}
    </div>
  );
}

// ---------- PLACE DETAIL ----------
function PlaceScreen({ pointId, initialTab = 'overview' }) {
  const nav = useNav();
  const [tab, setTab] = pS(initialTab);
  const point = window.POINTS[pointId];
  const wx = point ? window.WEATHER[point.id] : null;
  const tips = window.LOCAL_TIPS[pointId];

  if (!point) {
    return (
      <div className="screen">
        <div className="top-bar">
          <button className="rbtn" onClick={() => nav.back()}><Icon name="back" size={16} /></button>
          <div className="tb-title">Not found</div>
          <div />
        </div>
        <div className="empty">
          <h4>Place not found</h4>
          <p>Pick a point from the map.</p>
        </div>
      </div>
    );
  }

  const hasTips = tips && (tips.hidden_eats?.length || tips.curiosities?.length);
  const hasSlang = tips?.slang?.length;

  return (
    <div className="screen">
      <div className="screen-inner">
        {/* Hero */}
        <div className="place-hero">
          {point.images?.[0] && <img src={point.images[0].src} alt={point.images[0].alt} />}
          <button onClick={() => nav.back()} className="rbtn glass" style={{
            position: 'absolute', top: 50, left: 14, zIndex: 5, width: 38, height: 38,
          }}>
            <Icon name="back" size={16} />
          </button>
          <div className="tb-actions" style={{ position: 'absolute', top: 50, right: 14, zIndex: 5 }}>
            <button className="rbtn glass" onClick={() => window.open(point.mapsUrl, '_blank')}>
              <Icon name="share" size={16} />
            </button>
          </div>
          <div className="place-hero-content">
            <div className="mono">{point.region}</div>
            <h1 className="title">{point.shortName}</h1>
            <div className="region">{point.name}</div>
          </div>
        </div>

        {/* Tabs */}
        <div className="place-tabs">
          <button className={`place-tab ${tab === 'overview' ? 'active' : ''}`} onClick={() => setTab('overview')}>Overview</button>
          <button className={`place-tab ${tab === 'gallery' ? 'active' : ''}`} onClick={() => setTab('gallery')}>Photos</button>
          {hasTips && <button className={`place-tab ${tab === 'tips' ? 'active' : ''}`} onClick={() => setTab('tips')}>Hidden eats</button>}
          <button className={`place-tab ${tab === 'nearby' ? 'active' : ''}`} onClick={() => setTab('nearby')}>Nearby</button>
          {hasSlang && <button className={`place-tab ${tab === 'slang' ? 'active' : ''}`} onClick={() => setTab('slang')}>Slang</button>}
        </div>

        {tab === 'overview' && (
          <>
            {wx && (
              <div className="section" style={{ paddingTop: 22 }}>
                <button onClick={() => nav.push({ screen: 'weather' })} style={{ width: '100%' }}>
                  <div className={`wx-card ${wx.code}`} style={{ margin: 0 }}>
                    <div className="wc-top">
                      <div>
                        <div className="wc-loc">During your stay</div>
                        <div className="wc-date">{wx.summary}</div>
                      </div>
                      <div className="wc-glyph">{wxGlyph(wx.code)}</div>
                    </div>
                    <div className="wc-temp display">{wx.t_max}°</div>
                    <div className="wc-range">H {wx.t_max}°  ·  L {wx.t_min}°  ·  Wind {wx.wind} km/h</div>
                  </div>
                </button>
              </div>
            )}
            <div className="section">
              <div className="section-head"><h3>Highlights</h3></div>
              <div className="highlights" style={{ padding: 0 }}>
                {point.highlights.map((h, i) => <span key={i} className="highlight-chip" style={{ fontSize: 13, padding: '8px 12px' }}>{h}</span>)}
              </div>
            </div>
            {point.tips?.length > 0 && (
              <div className="section">
                <div className="section-head"><h3>Local tips</h3></div>
                {point.tips.map((t, i) => (
                  <div key={i} className="tip-card">
                    <div className="tk-label">Tip {i + 1}</div>
                    {t}
                  </div>
                ))}
              </div>
            )}
            <div className="section" style={{ paddingBottom: 20 }}>
              <button onClick={() => window.open(point.mapsUrl, '_blank')} className="sa-btn primary" style={{ width: '100%', padding: 14 }}>
                <Icon name="directions" size={16} /> Open in Google Maps
              </button>
            </div>
          </>
        )}

        {tab === 'gallery' && (
          <div className="gallery">
            {point.images.slice(0, 5).map((img, i) => (
              <div key={i} className={`g-item ${i === 4 && point.images.length > 5 ? 'g-more' : ''}`}
                   onClick={() => window.__lightbox(point.images, i)}>
                <img src={img.src} alt={img.alt} loading="lazy" />
              </div>
            ))}
          </div>
        )}

        {tab === 'tips' && hasTips && (
          <div style={{ padding: '22px 16px' }}>
            {tips.hidden_eats?.length > 0 && (
              <>
                <h3 className="display" style={{ fontSize: 22, marginBottom: 14, fontWeight: 400, letterSpacing: '-0.015em' }}>Must-eat · off the tourist track</h3>
                {tips.hidden_eats.map((e, i) => {
                  const mapsUrl = `https://maps.google.com/maps?daddr=${encodeURIComponent(e.name + ', ' + point.shortName)}`;
                  return (
                    <a key={i} href={mapsUrl} target="_blank" rel="noopener noreferrer"
                       className="eat-card eat-card-nav" style={{ display: 'block', textDecoration: 'none' }}>
                      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 10 }}>
                        <div style={{ minWidth: 0 }}>
                          <div className="nm">{e.name}</div>
                          <div className="why">{e.why}</div>
                          <div className="meta">
                            <span className="price">{e.price}</span>
                            {e.ig && <span className="badge">Insta-worthy</span>}
                          </div>
                        </div>
                        <div className="nearby-nav-arrow" style={{ marginTop: 2 }}>
                          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                            <polygon points="3 11 22 2 13 21 11 13 3 11"/>
                          </svg>
                        </div>
                      </div>
                    </a>
                  );
                })}
              </>
            )}
            {tips.curiosities?.length > 0 && (
              <>
                <h3 className="display" style={{ fontSize: 22, margin: '24px 0 14px', fontWeight: 400, letterSpacing: '-0.015em' }}>Did you know?</h3>
                {tips.curiosities.map((c, i) => (
                  <div key={i} className="tip-card">
                    <div className="tk-label">Local trivia</div>
                    {c}
                  </div>
                ))}
              </>
            )}
          </div>
        )}

        {tab === 'nearby' && (
          <div style={{ padding: '22px 16px' }}>
            {['cheap_eats', 'grocery', 'toilet'].map((cat) => {
              const list = point.nearby?.[cat] || [];
              const catIcon = { cheap_eats: '🍴', grocery: '🛒', toilet: '🚻' }[cat];
              const label = { cheap_eats: 'Jedzenie w pobliżu', grocery: 'Sklep / apteka', toilet: 'Toaleta' }[cat];
              return (
                <div key={cat} style={{ marginBottom: 24 }}>
                  <h3 className="display" style={{ fontSize: 20, marginBottom: 12, fontWeight: 500, letterSpacing: '-0.015em' }}>
                    {catIcon} {label}
                  </h3>
                  {list.length > 0 ? list.map((n, i) => {
                    const mapsUrl = `https://maps.google.com/maps?daddr=${encodeURIComponent(n.name + ', ' + point.shortName)}`;
                    return (
                      <a key={i} href={mapsUrl} target="_blank" rel="noopener noreferrer"
                         className="eat-card eat-card-nav" style={{ display: 'block', textDecoration: 'none' }}>
                        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10 }}>
                          <div style={{ minWidth: 0 }}>
                            <div className="nm">{n.name}</div>
                            <div className="meta">
                              <span className="price">{n.dist}</span>
                              {n.rating && <span className="badge">★ {n.rating}</span>}
                            </div>
                          </div>
                          <div className="nearby-nav-arrow">
                            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                              <polygon points="3 11 22 2 13 21 11 13 3 11"/>
                            </svg>
                          </div>
                        </div>
                      </a>
                    );
                  }) : (
                    <div className="tip-card" style={{ color: 'var(--ink-3)' }}>Brak danych — zapytaj na recepcji lub sprawdź Google Maps.</div>
                  )}
                </div>
              );
            })}
            <div style={{ padding: '8px 0 4px', textAlign: 'center', fontSize: 11, color: 'var(--ink-4)' }}>
              Tap any item to open directions in Google Maps
            </div>
          </div>
        )}

        {tab === 'slang' && hasSlang && (
          <div style={{ paddingTop: 18 }}>
            <div style={{ padding: '0 22px 18px' }}>
              <div className="mono" style={{ marginBottom: 6 }}>Heard in {point.shortName}</div>
              <div style={{ fontSize: 13.5, color: 'var(--ink-3)', lineHeight: 1.5 }}>Listen for these. Use them sparingly — locals clock tourists fast.</div>
            </div>
            {tips.slang.map((s, i) => (
              <div key={i} className="slang-item">
                <div className="term">{s.term}</div>
                <div className="means">{s.means}</div>
                <div className="ex">{s.ex}</div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

// ---------- WEATHER ----------
function WeatherScreen() {
  const nav = useNav();
  const [liveWx, setLiveWx] = pS({});
  const [loading, setLoading] = pS(true);

  pE(() => {
    const points = [...new Map(
      window.DAYS.map(d => window.primaryPointForDay(d)).filter(Boolean).map(p => [p.id, p])
    ).values()];
    let done = 0;
    points.forEach(async (p) => {
      const wx = await window.fetchLiveWeather(p.id);
      if (wx) setLiveWx(prev => ({ ...prev, [p.id]: wx }));
      if (++done === points.length) setLoading(false);
    });
    if (!points.length) setLoading(false);
  }, []);

  return (
    <div className="screen">
      <div className="top-bar">
        <button className="rbtn" onClick={() => nav.back()}><Icon name="back" size={16} /></button>
        <div className="tb-title">Forecast</div>
        <div style={{ fontSize: 11, color: 'var(--ink-3)', paddingRight: 4 }}>
          {loading ? 'Updating…' : Object.values(liveWx).some(w => w.live) ? 'Live' : 'Cached'}
        </div>
      </div>
      <div className="screen-inner">
        <div style={{ padding: '8px 22px 20px' }}>
          <div className="mono">12 days · all stops</div>
          <h2 className="display" style={{ fontSize: 30, lineHeight: 1.05, marginTop: 4, fontWeight: 400, letterSpacing: '-0.02em' }}>
            Expect a 20° swing between Death Valley and the SF fog.
          </h2>
        </div>
        {window.DAYS.map((d) => {
          const p = window.primaryPointForDay(d);
          const wx = p ? (liveWx[p.id] || window.WEATHER[p.id]) : null;
          return (
            <div key={d.id} className={`wx-row ${!wx ? 'empty' : ''}`}
                 onClick={() => p && nav.push({ screen: 'place', pointId: p.id })}>
              <div className="daynum display">{d.n}</div>
              <div>
                <div className="place">{p?.shortName || '—'}</div>
                <div className="cond">{wx?.summary || 'In transit'}</div>
              </div>
              <div className="range">{wx ? `${wx.t_min}° / ${wx.t_max}°` : '—'}</div>
              <div className="glyph">{wx ? wxGlyph(wx.code) : '·'}</div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ---------- TEAM ----------
function TeamScreen() {
  const nav = useNav();
  const sorted = [...window.TEAM].sort((a, b) => b.photosUploaded - a.photosUploaded);
  return (
    <div className="screen">
      <div className="top-bar">
        <button className="rbtn" onClick={() => nav.back()}><Icon name="back" size={16} /></button>
        <div className="tb-title">Team</div>
        <div />
      </div>
      <div className="screen-inner">
        <div style={{ padding: '8px 22px 18px' }}>
          <div className="mono">Photo League · Week 1</div>
          <h2 className="display" style={{ fontSize: 30, lineHeight: 1.05, marginTop: 4, fontWeight: 400, letterSpacing: '-0.02em' }}>
            {sorted[0].name} is pulling away.
          </h2>
        </div>
        <div className="team-grid">
          {sorted.map((t, i) => (
            <div key={t.id} className={`team-card ${i === 0 ? 'p1' : ''}`}>
              <div className="rank">{i + 1}</div>
              <div className="team-avatar" style={{ backgroundImage: `url(${t.avatar})`, ['--_c']: t.color }} />
              <div className="body">
                <div className="nm">{t.name}</div>
                <div className="ro">{t.role}</div>
              </div>
              <div className="photos">
                <div className="big display">{t.photosUploaded}</div>
                <div className="lbl">Photos</div>
              </div>
            </div>
          ))}
        </div>
        <div className="section">
          <div className="section-head"><h3>Challenges</h3></div>
          {window.CHALLENGES.slice(0, 3).map((c) => (
            <button key={c.id} onClick={() => nav.push({ screen: 'challenges' })} style={{ width: '100%', display: 'block' }}>
              <div className="challenge">
                <div className="ch-kind">{c.kind}</div>
                <div className="ch-title display">{c.title}</div>
                <div className="ch-sub">{c.subtitle}</div>
                <div className="ch-rule">{c.rule}</div>
              </div>
            </button>
          ))}
        </div>
      </div>
    </div>
  );
}

// ---------- CHALLENGES ----------
function ChallengesScreen() {
  const nav = useNav();
  const [bingo, setBingo] = pS(() => {
    try { return JSON.parse(localStorage.getItem('v2:bingo') || '[]'); } catch { return []; }
  });
  const toggle = (term) => {
    setBingo((b) => {
      const n = b.includes(term) ? b.filter((x) => x !== term) : [...b, term];
      localStorage.setItem('v2:bingo', JSON.stringify(n));
      return n;
    });
  };
  const bingoCard = window.CHALLENGES.find((c) => c.id === 'slang-bingo')?.card || [];

  return (
    <div className="screen">
      <div className="top-bar">
        <button className="rbtn" onClick={() => nav.back()}><Icon name="back" size={16} /></button>
        <div className="tb-title">Family challenges</div>
        <div />
      </div>
      <div className="screen-inner">
        <div style={{ padding: '8px 22px 18px' }}>
          <div className="mono">5 people · 12 days</div>
          <h2 className="display" style={{ fontSize: 30, lineHeight: 1.05, marginTop: 4, fontWeight: 400, letterSpacing: '-0.02em' }}>
            Games to keep the van alive.
          </h2>
        </div>
        {window.CHALLENGES.map((c) => (
          <div key={c.id} className="challenge">
            <div className="ch-kind">{c.kind}</div>
            <div className="ch-title display">{c.title}</div>
            <div className="ch-sub">{c.subtitle}</div>
            <div className="ch-rule">{c.rule}</div>
            {c.id === 'slang-bingo' && (
              <div className="bingo">
                {bingoCard.map((t) => (
                  <div key={t} className={`sq ${bingo.includes(t) ? 'checked' : ''}`} onClick={() => toggle(t)}>{t}</div>
                ))}
              </div>
            )}
            {c.items && (
              <div style={{ marginTop: 12, display: 'grid', gap: 6 }}>
                {c.items.slice(0, 6).map((it, i) => (
                  <div key={i} style={{ fontSize: 13, color: 'var(--ink-2)', paddingLeft: 16, position: 'relative' }}>
                    <span style={{ position: 'absolute', left: 0, color: 'var(--ink-4)', fontFamily: 'var(--mono)', fontSize: 10 }}>{String(i + 1).padStart(2, '0')}</span>
                    {it}
                  </div>
                ))}
                <div style={{ fontSize: 12, color: 'var(--ink-3)', fontStyle: 'italic', paddingLeft: 16 }}>+ {c.items.length - 6} more moments to find.</div>
              </div>
            )}
          </div>
        ))}
      </div>
    </div>
  );
}

// ---------- CHECKLIST ----------
function ChecklistScreen() {
  const nav = useNav();
  const [state, setState] = pS(() => {
    try { return JSON.parse(localStorage.getItem('v2:packing') || '{}'); } catch { return {}; }
  });
  const toggle = (key) => {
    setState((s) => {
      const n = { ...s, [key]: !s[key] };
      localStorage.setItem('v2:packing', JSON.stringify(n));
      return n;
    });
  };
  const isOn = (cat, i, def) => (state[`${cat}:${i}`] !== undefined ? state[`${cat}:${i}`] : def);

  const total = window.PACKING.reduce((a, c) => a + c.items.length, 0);
  const done = window.PACKING.reduce((a, c) => a + c.items.filter((it, i) => isOn(c.cat, i, it.packed)).length, 0);

  return (
    <div className="screen">
      <div className="top-bar">
        <button className="rbtn" onClick={() => nav.back()}><Icon name="back" size={16} /></button>
        <div className="tb-title">Packing</div>
        <div />
      </div>
      <div className="screen-inner">
        <div style={{ padding: '8px 22px 6px' }}>
          <div className="mono">{done} of {total} packed</div>
          <h2 className="display" style={{ fontSize: 30, lineHeight: 1.05, marginTop: 4, fontWeight: 400, letterSpacing: '-0.02em' }}>
            {done === total ? 'You\'re ready.' : `${total - done} items to go.`}
          </h2>
          <div style={{ marginTop: 14, height: 6, borderRadius: 3, background: 'var(--bg-elev-2)', overflow: 'hidden' }}>
            <div style={{ width: `${(done / total) * 100}%`, height: '100%', background: 'var(--brand)', transition: 'width 300ms' }} />
          </div>
        </div>

        <div className="check-cat display" style={{ marginTop: 18 }}>Pre-flight</div>
        <PreflightWorkflow variant="checklist" />

        {window.PACKING.map((c) => (
          <div key={c.cat}>
            <div className="check-cat display">{c.cat}</div>
            <div className="check-items">
              {c.items.map((it, i) => {
                const on = isOn(c.cat, i, it.packed);
                return (
                  <div key={i} className={`check-item ${on ? 'on' : ''}`} onClick={() => toggle(`${c.cat}:${i}`)}>
                    <div className={`check-box ${on ? 'on' : ''}`} />
                    <div className="lbl">{it.name}</div>
                  </div>
                );
              })}
            </div>
          </div>
        ))}
        <div style={{ height: 40 }} />
      </div>
    </div>
  );
}

// ---------- PRE-FLIGHT WORKFLOW ----------
// Per-member checklist — each step has done/pending status per traveller.
// Used in two places: Flights > Before you fly (collapsible card)
// and Checklist > Pre-flight (dedicated section, always open).
const PREFLIGHT_STEPS = [
  { k: 'app',   title: 'Install Air France app',                    sub: 'Download from App Store / Google Play. Boarding pass lives here.' },
  { k: 'acct',  title: 'Sign in / create account',                  sub: 'Flying Blue — free. Enables seat management and upgrade bids.' },
  { k: 'book',  title: 'Add booking to the app',                    sub: 'Bookings → Add reservation → #8710697 + last name.' },
  { k: 'seat',  title: 'Check assigned seats',                      sub: 'Verify we sit together on both long hauls (CDG↔EWR, LAX↔CDG).' },
  { k: 'upg',   title: 'Monitor possible seat change / upgrade offers', sub: 'Plus Grade bids usually surface 5–7 days before. You only pay if the bid wins — not guaranteed.' },
  { k: 'ci',    title: 'Complete check-in when available',          sub: 'Opens 30h before departure. Saves ~20 min at WAW.' },
  { k: 'cash',  title: 'Bring $640 USD cash',                       sub: 'Per person, paid to the pilot (tour lead) at WAW on Day 1. Clean bills preferred. This covers the group kitty.' },
];

function usePreflightState() {
  const [state, setState] = pS(() => {
    try { return JSON.parse(localStorage.getItem('v2:preflight') || '{}'); } catch { return {}; }
  });
  const toggle = (memberId, stepKey) => {
    setState((s) => {
      const key = `${memberId}:${stepKey}`;
      const n = { ...s, [key]: !s[key] };
      localStorage.setItem('v2:preflight', JSON.stringify(n));
      return n;
    });
  };
  const isDone = (memberId, stepKey) => !!state[`${memberId}:${stepKey}`];
  const doneForStep = (stepKey) => window.TEAM.filter((m) => isDone(m.id, stepKey)).length;
  const doneForMember = (memberId) => PREFLIGHT_STEPS.filter((s) => isDone(memberId, s.k)).length;
  const totalCells = PREFLIGHT_STEPS.length * window.TEAM.length;
  const totalDone = Object.values(state).filter(Boolean).length;
  return { state, toggle, isDone, doneForStep, doneForMember, totalCells, totalDone };
}

function MemberDot({ member, on, onClick, size = 26 }) {
  return (
    <button
      onClick={onClick}
      title={`${member.name} · ${on ? 'done' : 'pending'}`}
      style={{
        position: 'relative',
        width: size, height: size,
        borderRadius: '50%',
        padding: 0, border: 'none', background: 'transparent',
        cursor: 'pointer',
      }}
    >
      <div style={{
        width: '100%', height: '100%', borderRadius: '50%',
        backgroundImage: `url(${member.avatar})`,
        backgroundSize: 'cover', backgroundPosition: 'center',
        boxShadow: on
          ? `0 0 0 2px var(--bg-elev), 0 0 0 3.5px ${member.color}`
          : `0 0 0 2px var(--bg-elev), 0 0 0 3px var(--line)`,
        opacity: on ? 1 : 0.42,
        filter: on ? 'none' : 'grayscale(0.8)',
        transition: 'opacity 150ms, filter 150ms, box-shadow 150ms',
      }} />
      {on && (
        <div style={{
          position: 'absolute', right: -2, bottom: -2,
          width: 12, height: 12, borderRadius: '50%',
          background: 'var(--brand)',
          border: '2px solid var(--bg-elev)',
          display: 'grid', placeItems: 'center',
        }}>
          <svg width="6" height="6" viewBox="0 0 10 10" fill="none"><path d="M1.5 5 L4 7.5 L8.5 2.5" stroke="white" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" /></svg>
        </div>
      )}
    </button>
  );
}

function PreflightStepRow({ step, index, isDone, toggle, doneForStep }) {
  const total = window.TEAM.length;
  const done = doneForStep(step.k);
  return (
    <div style={{
      padding: '14px 18px 16px',
      borderTop: index === 0 ? 'none' : '0.5px solid var(--line)',
    }}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr auto', gap: 12, alignItems: 'start', marginBottom: 10 }}>
        <div>
          <div style={{ fontSize: 13.5, fontWeight: 600, color: 'var(--ink)' }}>{step.title}</div>
          <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 2, lineHeight: 1.4 }}>{step.sub}</div>
        </div>
        <div style={{
          fontFamily: 'var(--mono)', fontSize: 10, fontWeight: 700,
          color: done === total ? 'var(--brand)' : 'var(--ink-3)',
          whiteSpace: 'nowrap',
          padding: '3px 8px',
          borderRadius: 20,
          background: done === total ? 'color-mix(in oklch, var(--brand) 14%, transparent)' : 'var(--bg-elev-2)',
          letterSpacing: '0.04em',
        }}>{done}/{total}</div>
      </div>
      <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
        {window.TEAM.map((m) => (
          <div key={m.id} style={{ display: 'grid', justifyItems: 'center', gap: 4 }}>
            <MemberDot member={m} on={isDone(m.id, step.k)} onClick={() => toggle(m.id, step.k)} />
            <div style={{ fontSize: 9.5, fontFamily: 'var(--mono)', fontWeight: 700, color: isDone(m.id, step.k) ? 'var(--ink-2)' : 'var(--ink-3)', letterSpacing: '0.04em' }}>
              {m.name.toUpperCase()}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

function PreflightWorkflow({ variant = 'flights' }) {
  const collapsible = variant === 'flights';
  const [open, setOpen] = pS(true);
  const pf = usePreflightState();
  const pct = pf.totalCells === 0 ? 0 : Math.round((pf.totalDone / pf.totalCells) * 100);

  const header = (
    <>
      <div style={{ width: 40, height: 40, borderRadius: 10, background: 'linear-gradient(135deg, #002157 0%, #ed2939 100%)', display: 'grid', placeItems: 'center', color: 'white', fontSize: 16, fontWeight: 700, fontFamily: 'var(--display)', letterSpacing: '-0.02em', flexShrink: 0 }}>AF</div>
      <div>
        <div style={{ fontSize: 15, fontWeight: 600 }}>
          {variant === 'flights' ? 'Before you fly' : 'Pre-flight workflow'}
        </div>
        <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 2 }}>
          {pf.totalDone}/{pf.totalCells} actions · {window.TEAM.length} travellers · {pct}%
        </div>
      </div>
    </>
  );

  return (
    <div style={{ margin: '0 16px 18px', background: 'var(--bg-elev)', border: '0.5px solid var(--line)', borderRadius: 16, overflow: 'hidden', boxShadow: 'var(--sh-xs)' }}>
      {collapsible ? (
        <button onClick={() => setOpen(!open)} style={{ width: '100%', display: 'grid', gridTemplateColumns: '40px 1fr auto', gap: 12, alignItems: 'center', padding: '14px 16px', textAlign: 'left', background: 'transparent', border: 'none' }}>
          {header}
          <div style={{ color: 'var(--ink-3)', fontSize: 12, fontFamily: 'var(--mono)', fontWeight: 700, transform: open ? 'rotate(180deg)' : 'none', transition: 'transform 200ms' }}>▼</div>
        </button>
      ) : (
        <div style={{ display: 'grid', gridTemplateColumns: '40px 1fr', gap: 12, alignItems: 'center', padding: '14px 16px' }}>
          {header}
        </div>
      )}

      {(open || !collapsible) && (
        <>
          <div style={{ height: 4, background: 'var(--bg-elev-2)' }}>
            <div style={{ height: '100%', width: `${pct}%`, background: 'var(--brand)', transition: 'width 250ms' }} />
          </div>
          <div>
            {PREFLIGHT_STEPS.map((s, i) => (
              <PreflightStepRow
                key={s.k}
                step={s}
                index={i}
                isDone={pf.isDone}
                toggle={pf.toggle}
                doneForStep={pf.doneForStep}
              />
            ))}
          </div>
          <div style={{ padding: '12px 18px 14px', background: 'var(--bg-warm)', borderTop: '0.5px solid var(--line)' }}>
            <div style={{ fontSize: 10, fontFamily: 'var(--mono)', fontWeight: 700, color: 'var(--ink-3)', letterSpacing: '0.06em', marginBottom: 6 }}>PER TRAVELLER</div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 8 }}>
              {window.TEAM.map((m) => {
                const d = pf.doneForMember(m.id);
                const total = PREFLIGHT_STEPS.length;
                const complete = d === total;
                return (
                  <div key={m.id} style={{ textAlign: 'center' }}>
                    <div style={{ fontSize: 10, fontFamily: 'var(--mono)', fontWeight: 700, color: complete ? 'var(--brand)' : 'var(--ink-3)', letterSpacing: '0.04em' }}>
                      {m.name.toUpperCase()}
                    </div>
                    <div style={{ fontFamily: 'var(--display)', fontSize: 18, marginTop: 2, color: complete ? 'var(--brand)' : 'var(--ink)', fontWeight: 400 }}>
                      {d}/{total}
                    </div>
                    <div style={{ fontSize: 9.5, fontFamily: 'var(--mono)', fontWeight: 700, color: complete ? 'var(--brand)' : 'var(--ink-3)', letterSpacing: '0.04em', marginTop: 1 }}>
                      {complete ? 'DONE' : 'PENDING'}
                    </div>
                  </div>
                );
              })}
            </div>
          </div>
        </>
      )}
    </div>
  );
}

// Back-compat alias — used in Flights screen render
function BeforeYouFly() { return <PreflightWorkflow variant="flights" />; }

// ---------- FLIGHTS ----------

function FlightsScreen() {
  const nav = useNav();
  return (
    <div className="screen">
      <div className="top-bar">
        <button className="rbtn" onClick={() => nav.back()}><Icon name="back" size={16} /></button>
        <div className="tb-title">Flights</div>
        <div />
      </div>
      <div className="screen-inner">
        <div style={{ padding: '8px 22px 20px' }}>
          <div className="mono">Air France · Booking #{window.TRIP.bookingRef}</div>
          <h2 className="display" style={{ fontSize: 30, lineHeight: 1.05, marginTop: 4, fontWeight: 400, letterSpacing: '-0.02em' }}>
            Warsaw → Newark · Los Angeles → Warsaw
          </h2>
        </div>

        <BeforeYouFly />

        {window.FLIGHTS.map((f) => (
          <div key={f.dir} style={{ margin: '0 16px 16px', background: 'var(--bg-elev)', border: '0.5px solid var(--line)', borderRadius: 16, overflow: 'hidden', boxShadow: 'var(--sh-xs)' }}>
            <div style={{ padding: '16px 18px', borderBottom: '0.5px solid var(--line)' }}>
              <div className="mono">{f.title}</div>
              <div style={{ fontSize: 16, fontWeight: 600, marginTop: 4 }}>{f.date}</div>
            </div>
            {f.legs.map((leg, i) => (
              <div key={i} style={{ padding: '16px 18px', borderBottom: i < f.legs.length - 1 ? '0.5px solid var(--line)' : 'none' }}>
                <div style={{ display: 'grid', gridTemplateColumns: '1fr auto 1fr', gap: 10, alignItems: 'center' }}>
                  <div>
                    <div style={{ fontFamily: 'var(--display)', fontSize: 28, lineHeight: 1, fontWeight: 400 }}>{leg.dep}</div>
                    <div style={{ fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--ink-3)', marginTop: 4, fontWeight: 700 }}>{leg.from}</div>
                    <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 1 }}>{leg.fromCity}</div>
                  </div>
                  <div style={{ textAlign: 'center', color: 'var(--ink-3)' }}>
                    <div style={{ fontSize: 10, fontFamily: 'var(--mono)', fontWeight: 700 }}>{leg.dur}</div>
                    <div style={{ fontSize: 18 }}>→</div>
                    <div style={{ fontSize: 10, fontFamily: 'var(--mono)', fontWeight: 700 }}>{leg.flight}</div>
                  </div>
                  <div style={{ textAlign: 'right' }}>
                    <div style={{ fontFamily: 'var(--display)', fontSize: 28, lineHeight: 1, fontWeight: 400 }}>{leg.arr}</div>
                    <div style={{ fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--ink-3)', marginTop: 4, fontWeight: 700 }}>{leg.to}</div>
                    <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 1 }}>{leg.toCity}</div>
                  </div>
                </div>
              </div>
            ))}
            <div style={{ padding: '10px 18px', background: 'var(--bg-warm)', fontSize: 12, color: 'var(--ink-3)' }}>
              Layover: {f.layover}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ---------- HOTELS ----------
function HotelCard({ h, onPress }) {
  const [details, setDetails] = pS(null);
  pE(() => {
    if (!h.confirmed || h.address === 'TBC') return;
    const query = encodeURIComponent(h.name + ' ' + h.city);
    fetch(`/api/place-details?query=${query}`)
      .then(r => r.ok ? r.json() : null)
      .then(d => { if (d?.found) setDetails(d); })
      .catch(() => {});
  }, [h.name]);

  const photo = details?.photoUrl;
  const rating = details?.rating;
  const website = details?.website;

  return (
    <button onClick={onPress} style={{ width: '100%', textAlign: 'left' }}>
      <div style={{ background: 'var(--bg-elev)', border: '0.5px solid var(--line)', borderRadius: 16, overflow: 'hidden', boxShadow: 'var(--sh-xs)' }}>
        {/* Photo strip */}
        <div style={{ height: 110, background: photo ? `url(${photo}) center/cover no-repeat` : 'var(--bg-elev-2)', position: 'relative' }}>
          {!h.confirmed && (
            <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <span style={{ fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--ink-3)', letterSpacing: '0.08em' }}>TO BE CONFIRMED</span>
            </div>
          )}
          {rating && (
            <div style={{ position: 'absolute', top: 8, right: 8, background: 'rgba(0,0,0,0.55)', borderRadius: 8, padding: '3px 8px', fontSize: 12, fontWeight: 700, color: '#fff' }}>
              ★ {rating.toFixed(1)}
            </div>
          )}
        </div>
        {/* Info */}
        <div style={{ padding: '12px 14px' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 4 }}>
            <div className="mono">{h.nights} night{h.nights > 1 ? 's' : ''} · {h.city}</div>
            <div className="mono" style={{ color: h.confirmed ? 'var(--ok)' : 'var(--warn)' }}>
              {h.confirmed ? '● Confirmed' : '○ TBC'}
            </div>
          </div>
          <div style={{ fontSize: 15, fontWeight: 600, marginBottom: 2, lineHeight: 1.2 }}>{h.name}</div>
          {h.confirmed && h.address !== 'TBC' && (
            <div style={{ fontSize: 12, color: 'var(--ink-2)', marginTop: 3, lineHeight: 1.4 }}>{h.address}</div>
          )}
          <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 3 }}>{h.dates}</div>
          {website && (
            <a href={website} target="_blank" rel="noopener noreferrer"
               onClick={e => e.stopPropagation()}
               style={{ display: 'inline-block', marginTop: 6, fontSize: 12, color: 'var(--brand)', textDecoration: 'none', fontFamily: 'var(--mono)' }}>
              Website ↗
            </a>
          )}
        </div>
      </div>
    </button>
  );
}

function HotelsScreen() {
  const nav = useNav();
  return (
    <div className="screen">
      <div className="top-bar">
        <button className="rbtn" onClick={() => nav.back()}><Icon name="back" size={16} /></button>
        <div className="tb-title">Hotels</div>
        <div />
      </div>
      <div className="screen-inner">
        <div style={{ padding: '8px 22px 18px' }}>
          <div className="mono">11 nights · 7 hotels</div>
          <h2 className="display" style={{ fontSize: 30, lineHeight: 1.05, marginTop: 4, fontWeight: 400, letterSpacing: '-0.02em' }}>
            Where you sleep.
          </h2>
        </div>
        <div style={{ padding: '0 16px 20px', display: 'grid', gap: 10 }}>
          {window.HOTELS.map((h, i) => {
            const p = window.POINTS[h.pointId];
            return (
              <HotelCard key={i} h={h} onPress={() => p && nav.push({ screen: 'place', pointId: h.pointId })} />
            );
          })}
        </div>
      </div>
    </div>
  );
}

// ---------- DOCS ----------
function DocsScreen() {
  const nav = useNav();
  return (
    <div className="screen">
      <div className="top-bar">
        <button className="rbtn" onClick={() => nav.back()}><Icon name="back" size={16} /></button>
        <div className="tb-title">Documents</div>
        <div />
      </div>
      <div className="screen-inner">
        <div style={{ padding: '8px 22px 18px' }}>
          <div className="mono">All confirmed · synced</div>
          <h2 className="display" style={{ fontSize: 30, lineHeight: 1.05, marginTop: 4, fontWeight: 400, letterSpacing: '-0.02em' }}>
            Everything you need, on hand.
          </h2>
        </div>
        <div style={{ margin: '0 16px', background: 'var(--bg-elev)', border: '0.5px solid var(--line)', borderRadius: 16, overflow: 'hidden', boxShadow: 'var(--sh-xs)' }}>
          {window.DOCS.map((d, i) => (
            <div key={i} style={{
              padding: '14px 18px',
              borderTop: i > 0 ? '0.5px solid var(--line)' : 'none',
              display: 'grid', gridTemplateColumns: '1fr auto', gap: 12, alignItems: 'center',
            }}>
              <div>
                <div className="mono" style={{ marginBottom: 3 }}>{d.kind}</div>
                <div style={{ fontSize: 14.5, fontWeight: 600 }}>{d.label}</div>
                <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 2 }}>{d.meta}</div>
              </div>
              <div style={{ width: 22, height: 22, borderRadius: '50%', background: 'var(--ok)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white' }}>
                <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12 L10 17 L20 7" /></svg>
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// ---------- TIPS (hidden eats + curiosities for point) ----------
function TipsScreen({ pointId }) {
  // Delegate to PlaceScreen's tips tab
  return <PlaceScreen pointId={pointId} initialTab="tips" />;
}

function SlangScreen({ pointId }) {
  return <PlaceScreen pointId={pointId} initialTab="slang" />;
}

Object.assign(window, {
  Lightbox, PlaceScreen, WeatherScreen, TeamScreen,
  ChallengesScreen, ChecklistScreen, BeforeYouFly, PreflightWorkflow, FlightsScreen, HotelsScreen, DocsScreen,
  TipsScreen, SlangScreen,
});
