// screens.jsx — live, data-backed screens for the PWA.

const { T: TT, Icons: IC, H1, H2, Label, Muted, Card, Chip, SeverityBadge, Switch, Page, Sheet, PrimaryButton, GhostButton, MiniBars } = window;

// ───────────────── HELPERS ─────────────────
function nowIsoLocal() {
  const d = new Date();
  const off = d.getTimezoneOffset() * 60000;
  return new Date(d - off).toISOString().slice(0, 16); // YYYY-MM-DDTHH:MM
}

// Always returns YYYY-MM-DD in local time, avoiding UTC-date-as-midnight parse bugs.
function localDateStr(d) {
  return `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`;
}

function fmtClock(iso) {
  if (!iso) return '';
  const d = new Date(iso);
  const h = d.getHours(), m = d.getMinutes();
  const ap = h >= 12 ? 'PM' : 'AM';
  return `${(h % 12 || 12)}:${m.toString().padStart(2, '0')} ${ap}`;
}

function fmtDayLong(iso) {
  if (!iso) return '';
  // Date-only strings (YYYY-MM-DD) parse as UTC midnight in browsers; force local.
  const d = iso.length === 10 ? new Date(iso + 'T00:00:00') : new Date(iso);
  return d.toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric' });
}

function todayDate() { return localDateStr(new Date()); }

function todayHasEntry(entries) {
  const today = todayDate();
  return entries.some((e) => e.date === today);
}

// ───────────────── 1) HOME / TODAY ─────────────────
function HomeScreen({ user, entries, weather, allergens, onNavigate, onLog, readOnly }) {
  const recent = entries.slice(0, 3);
  const weekCount = entries.filter((e) => Date.now() - new Date(e.occurredAt).getTime() < 7 * 86400000).length;
  const dailyBars = computeDailyBars(entries, 14);

  return (
    <Page>
      <div style={{ marginTop: 6, marginBottom: 14 }}>
        <Muted size={12}>{new Date().toLocaleDateString(undefined, { weekday: 'long', month: 'long', day: 'numeric' })}</Muted>
        <H1 style={{ marginTop: 4 }}>Hi, {user ? user.name.split(/\s+/)[0] : 'there'}.</H1>
        <Muted size={14} style={{ marginTop: 2 }}>
          {todayHasEntry(entries) ? `${entriesToday(entries).length} headache${entriesToday(entries).length > 1 ? 's' : ''} logged today.` : 'No headache logged today.'}
        </Muted>
      </div>

      {!readOnly && (
        <>
          <button onClick={onLog} style={{
            width: '100%', height: 76, border: 'none', cursor: 'pointer',
            background: TT.accent, color: '#fff', borderRadius: 18,
            fontFamily: TT.font, fontWeight: 600, fontSize: 17,
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            padding: '0 20px 0 22px',
            boxShadow: `0 8px 24px ${TT.accent}30, 0 1px 0 rgba(0,0,0,0.04)`,
          }}>
            <div style={{ textAlign: 'left' }}>
              <div style={{ fontSize: 18 }}>Log a headache now</div>
              <div style={{ fontSize: 12, fontWeight: 400, opacity: 0.85, marginTop: 2 }}>
                Auto-times to {fmtClock(new Date().toISOString())}
              </div>
            </div>
            <div style={{ width: 44, height: 44, borderRadius: 999, background: 'rgba(255,255,255,0.18)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <IC.plus size={22} strokeWidth={2.4}/>
            </div>
          </button>

          <div style={{ display: 'flex', gap: 8, marginTop: 10 }}>
            <GhostButton onClick={onLog} style={{ flex: 1 }}>Backfill earlier…</GhostButton>
            <GhostButton onClick={() => onNavigate('home', { addDayNote: true })} style={{ flex: 1 }}>Add a day note</GhostButton>
          </div>
        </>
      )}

      {/* Today in Birmingham */}
      <div style={{ marginTop: 18 }}>
        <Label style={{ marginBottom: 10 }}>Today in Birmingham</Label>
        <Card pad={14}>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
            <Stat icon="sun"  label="Weather"  value={weather ? (weather.temp + '°') : '—'} sub={weather ? weather.condition : 'tap to refresh'}/>
            <Stat icon="leaf" label="Pollen"   value={allergens ? allergens.pollenLabel : '—'} sub={allergens && allergens.mainPollen.length ? allergens.mainPollen.join(', ') : ''}/>
            <Stat icon="wind" label="Air"      value={allergens?.aqi != null ? ('AQI ' + Math.round(allergens.aqi)) : '—'} sub={allergens?.aqi != null ? aqiBand(allergens.aqi) : ''}/>
            <Stat icon="drop" label="Humidity" value={weather?.humidity != null ? Math.round(weather.humidity) + '%' : '—'} sub=""/>
          </div>
        </Card>
      </div>

      {/* This week */}
      <div style={{ marginTop: 18 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 10 }}>
          <Label>This week</Label>
          <a onClick={() => onNavigate('patterns')} style={{ fontSize: 12, color: TT.accentInk, fontWeight: 600, cursor: 'pointer' }}>Patterns →</a>
        </div>
        <Card pad={14}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' }}>
            <div>
              <div style={{ fontFamily: TT.fontDisplay, fontSize: 36, fontWeight: 600, lineHeight: 1, color: TT.ink, letterSpacing: -1 }}>{weekCount}</div>
              <Muted size={12} style={{ marginTop: 4 }}>headache{weekCount === 1 ? '' : 's'} this week</Muted>
            </div>
            <MiniBars values={dailyBars} w={140} h={44}/>
          </div>
        </Card>
      </div>

      {/* Recent */}
      {recent.length > 0 && (
        <div style={{ marginTop: 18 }}>
          <Label style={{ marginBottom: 10 }}>Recent</Label>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {recent.map((e) => <CompactEntry key={e.id} entry={e} onClick={() => onNavigate('history')}/>)}
          </div>
        </div>
      )}
    </Page>
  );
}

function entriesToday(entries) {
  const t = todayDate();
  return entries.filter((e) => e.date === t);
}

function Stat({ icon, label, value, sub }) {
  const I = IC[icon];
  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, color: TT.muted }}>
        <I size={13}/>
        <span style={{ fontSize: 11, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.6 }}>{label}</span>
      </div>
      <div style={{ marginTop: 4, fontFamily: TT.fontDisplay, fontSize: 22, fontWeight: 600, color: TT.ink, letterSpacing: -0.4 }}>{value}</div>
      {sub && <Muted size={11} style={{ marginTop: 1 }}>{sub}</Muted>}
    </div>
  );
}

function CompactEntry({ entry, onClick }) {
  return (
    <Card pad={12} style={{ cursor: 'pointer' }}>
      <div onClick={onClick} style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
        <SeverityBadge level={entry.severity} size="sm"/>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 14, fontWeight: 600, color: TT.ink }}>{fmtClock(entry.occurredAt)} · {fmtDayLong(entry.occurredAt)}</div>
          <div style={{ fontSize: 12, color: TT.muted, marginTop: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
            {(entry.locations || []).join(' · ') || 'no location'}{entry.activity ? ' · ' + entry.activity : ''}
          </div>
        </div>
        <IC.chev size={14} style={{ color: TT.muted }}/>
      </div>
    </Card>
  );
}

function aqiBand(v) {
  if (v < 50) return 'Good';
  if (v < 100) return 'Moderate';
  if (v < 150) return 'Sensitive';
  if (v < 200) return 'Unhealthy';
  return 'Very unhealthy';
}

function computeDailyBars(entries, days) {
  const out = new Array(days).fill(0);
  const today = new Date(); today.setHours(0,0,0,0);
  entries.forEach((e) => {
    const d = new Date(e.occurredAt); d.setHours(0,0,0,0);
    const diff = Math.round((today - d) / 86400000);
    if (diff >= 0 && diff < days) out[days - 1 - diff] += 1;
  });
  return out;
}

// ───────────────── 2) LOG FORM (modal sheet) ─────────────────
function LogForm({ open, onClose, onSave, prefill, weather, allergens }) {
  const [time, setTime] = React.useState(prefill?.occurredAt ? prefill.occurredAt.slice(0, 16) : nowIsoLocal());
  const [severity, setSeverity] = React.useState(prefill?.severity || 'moderate');
  // Track whether the selected time is a backfill (>20 min in the past).
  const [backfillWeather, setBackfillWeather] = React.useState(null);
  const [backfillAllergens, setBackfillAllergens] = React.useState(null);
  const [weatherLoading, setWeatherLoading] = React.useState(false);
  // Lazy-loaded data for when the form opens before the parent's async fetches complete.
  const [localWeather, setLocalWeather] = React.useState(null);
  const [localAllergens, setLocalAllergens] = React.useState(null);
  React.useEffect(() => {
    if (!open) return;
    const diffMin = (Date.now() - new Date(time).getTime()) / 60000;
    if (diffMin > 20) {
      // Backfill mode — fetch archived weather for the chosen hour.
      setWeatherLoading(true);
      setBackfillWeather(null); setBackfillAllergens(null);
      WeatherApi.fetchHistoricalWeather({ isoDateTime: new Date(time).toISOString() })
        .then((w) => { setBackfillWeather(w); setWeatherLoading(false); })
        .catch(() => setWeatherLoading(false));
      // Air-quality archive not available from Open-Meteo; clear it for backfills.
      setBackfillAllergens(null);
    } else {
      setBackfillWeather(null); setBackfillAllergens(null); setWeatherLoading(false);
      // If the parent hasn't finished loading yet, fetch here so pollen is captured.
      if (!weather) WeatherApi.fetchCurrentWeather().then(setLocalWeather).catch(() => {});
      if (!allergens) WeatherApi.fetchAirQuality().then(setLocalAllergens).catch(() => {});
    }
  }, [time, open]);
  // Use live data for "now" entries, archived for backfills.
  const activeWeather = backfillWeather || weather || localWeather;
  const activeAllergens = backfillAllergens || (!backfillWeather ? (allergens || localAllergens) : null);
  const [locations, setLocations] = React.useState(prefill?.locations || []);
  const [activity, setActivity] = React.useState(prefill?.activity || '');
  const [notes, setNotes] = React.useState(prefill?.notes || '');

  const [allergyOn, setAllergyOn] = React.useState(prefill?.allergy?.active || false);
  const [allergySymptoms, setAllergySymptoms] = React.useState(prefill?.allergy?.symptoms || '');

  const [medOn, setMedOn] = React.useState(prefill?.medicine?.taken || false);
  const [medWhat, setMedWhat] = React.useState(prefill?.medicine?.what || '');
  const [medRelief, setMedRelief] = React.useState(prefill?.medicine?.relief || null);

  const [onPeriod, setOnPeriod] = React.useState(prefill?.onPeriod || false);

  if (!open) return null;

  const toggleLocation = (l) => {
    setLocations((cur) => cur.includes(l) ? cur.filter((x) => x !== l) : [...cur, l]);
  };
  const toggleAllergyQuick = (q) => {
    const list = allergySymptoms ? allergySymptoms.split(',').map((s) => s.trim()).filter(Boolean) : [];
    if (list.includes(q)) {
      setAllergySymptoms(list.filter((x) => x !== q).join(', '));
    } else {
      setAllergySymptoms([...list, q].join(', '));
    }
  };
  const allergySelected = (q) => (allergySymptoms || '').toLowerCase().includes(q.toLowerCase());

  const save = () => {
    const occLocal = new Date(time); // datetime-local string parses as local time
    const isoOccurred = occLocal.toISOString();
    const payload = {
      occurredAt: isoOccurred,
      date: localDateStr(occLocal),
      severity,
      locations,
      activity,
      notes,
      allergy: { active: allergyOn, symptoms: allergyOn ? allergySymptoms : '' },
      medicine: medOn ? { taken: true, what: medWhat, takenAt: new Date().toISOString(), relief: medRelief } : { taken: false },
      onPeriod,
      cycleDay: null,
      weather: activeWeather, allergens: activeAllergens,
    };
    onSave(payload);
  };

  return (
    <Sheet open={open} onClose={onClose} height="92vh">
      {/* Sticky header */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 14 }}>
        <button onClick={onClose} style={{ background: 'none', border: 'none', color: TT.inkSoft, fontFamily: TT.font, fontSize: 14, padding: 0, cursor: 'pointer' }}>Cancel</button>
        <div style={{ fontFamily: TT.font, fontSize: 14, fontWeight: 600 }}>New headache</div>
        <button onClick={save} style={{ background: 'none', border: 'none', color: TT.accentInk, fontFamily: TT.font, fontSize: 14, fontWeight: 600, padding: 0, cursor: 'pointer' }}>Save</button>
      </div>

      {/* When */}
      <FormSection label="When">
        <div style={{ display: 'flex', gap: 8 }}>
          <button onClick={() => setTime(nowIsoLocal())} style={{
            flex: '0 0 auto', height: 44, padding: '0 14px',
            borderRadius: 12, background: TT.accent, color: '#fff',
            border: 'none', fontFamily: TT.font, fontWeight: 600, fontSize: 14,
            display: 'inline-flex', alignItems: 'center', gap: 6, cursor: 'pointer',
          }}>
            <IC.clock size={14}/> Now
          </button>
          <input type="datetime-local" value={time} onChange={(e) => setTime(e.target.value)} style={{
            flex: 1, height: 44, borderRadius: 12,
            border: '1px solid ' + TT.hairline, background: TT.surface,
            padding: '0 14px', fontFamily: TT.font, fontSize: 14, color: TT.ink,
            outline: 'none',
          }}/>
        </div>
        <Muted size={12} style={{ marginTop: 6 }}>Backfill earlier — historical weather will be fetched.</Muted>
      </FormSection>

      {/* Severity */}
      <FormSection label="Severity">
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 6 }}>
          {window.SEVERITIES.map((s) => {
            const sel = severity === s;
            const c = TT.sev[s];
            return (
              <button key={s} onClick={() => setSeverity(s)} style={{
                height: 60, padding: '6px 4px', cursor: 'pointer',
                borderRadius: 12,
                background: sel ? c.bg : TT.surface,
                border: '1px solid ' + (sel ? c.dot : TT.hairline),
                color: sel ? c.ink : TT.inkSoft,
                fontFamily: TT.font, fontWeight: sel ? 600 : 500, fontSize: 11.5,
                display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 4,
                textTransform: 'capitalize',
              }}>
                <span style={{ width: 8, height: 8, borderRadius: '50%', background: c.dot }}/>
                {s}
              </button>
            );
          })}
        </div>
      </FormSection>

      {/* Location */}
      <FormSection label="Location" hint="tap all that apply">
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
          {window.LOCATION_CHIPS.map((l) => (
            <Chip key={l} active={locations.includes(l)} onClick={() => toggleLocation(l)} size="sm">{l}</Chip>
          ))}
        </div>
      </FormSection>

      {/* Activity */}
      <FormSection label="What were you doing?">
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 8 }}>
          {window.ACTIVITY_CHIPS.map((a) => (
            <Chip key={a} active={activity === a} onClick={() => setActivity(activity === a ? '' : a)} size="sm">{a}</Chip>
          ))}
        </div>
        <input value={activity} onChange={(e) => setActivity(e.target.value)} placeholder="Or type a custom activity…" style={inputStyle}/>
      </FormSection>

      {/* Auto-detected */}
      <FormSection label={backfillWeather ? 'Historical weather' : weatherLoading ? 'Fetching archived weather…' : 'Auto-detected'} hint="from Open-Meteo">
        <Card pad={12}>
          <div style={{ display: 'flex', gap: 12, alignItems: 'center', flexWrap: 'wrap' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <IC.sun size={16} style={{ color: TT.accentInk }}/>
              <div>
                <div style={{ fontFamily: TT.fontDisplay, fontSize: 18, fontWeight: 600 }}>{activeWeather ? activeWeather.temp + '°' : weatherLoading ? '…' : '—'}</div>
                <Muted size={11}>{activeWeather ? activeWeather.condition : weatherLoading ? 'loading' : 'unavailable'}</Muted>
              </div>
            </div>
            <div style={{ width: 1, height: 32, background: TT.hairline }}/>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <IC.leaf size={16} style={{ color: TT.accentInk }}/>
              <div>
                <div style={{ fontFamily: TT.fontDisplay, fontSize: 14, fontWeight: 600 }}>{activeAllergens?.pollenLabel || (backfillWeather ? 'not available' : '—')} pollen</div>
                <Muted size={11}>{activeAllergens?.mainPollen?.join(', ') || (backfillWeather ? 'archive only has weather' : '—')}{activeAllergens?.aqi != null ? ' · AQI ' + Math.round(activeAllergens.aqi) : ''}</Muted>
              </div>
            </div>
          </div>
        </Card>
      </FormSection>

      {/* Allergy */}
      <FormSection label="Allergy symptoms">
        <ToggleCard icon="leaf" label="Allergy symptoms" sub={allergyOn ? 'Add details below' : 'Tap to add'} on={allergyOn} onChange={setAllergyOn}/>
        {allergyOn && (
          <div style={{ marginTop: 8, padding: 12, background: TT.accentSoft, borderRadius: 12 }}>
            <Label style={{ marginBottom: 6 }}>Quick tap</Label>
            <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 10 }}>
              {window.ALLERGY_QUICK.map((q) => (
                <Chip key={q} active={allergySelected(q)} onClick={() => toggleAllergyQuick(q)} size="sm">{q}</Chip>
              ))}
            </div>
            <textarea value={allergySymptoms} onChange={(e) => setAllergySymptoms(e.target.value)}
              placeholder="Describe symptoms…"
              style={{ ...inputStyle, minHeight: 60, padding: '10px 12px', resize: 'vertical' }}/>
          </div>
        )}
      </FormSection>

      {/* Medicine */}
      <FormSection label="Medicine">
        <ToggleCard icon="pill" label="Took medicine" sub={medOn ? 'What & how it worked' : 'Tap to add'} on={medOn} onChange={setMedOn}/>
        {medOn && (
          <div style={{ marginTop: 8, padding: 12, background: TT.accentSoft, borderRadius: 12 }}>
            <Label style={{ marginBottom: 6 }}>What did you take?</Label>
            <input value={medWhat} onChange={(e) => setMedWhat(e.target.value)} placeholder="e.g. Excedrin Migraine 2 tab" style={inputStyle}/>
            <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginTop: 8 }}>
              {window.MEDICINE_QUICK.map((m) => (
                <Chip key={m} active={medWhat === m} onClick={() => setMedWhat(m)} size="sm">{m}</Chip>
              ))}
            </div>
            <Label style={{ marginTop: 12, marginBottom: 6 }}>Did it help?</Label>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 6 }}>
              {window.RELIEF_OPTIONS.map((r) => {
                const sel = medRelief === r.id;
                return (
                  <button key={r.id} onClick={() => setMedRelief(sel ? null : r.id)} style={{
                    height: 44, padding: '6px 4px', cursor: 'pointer',
                    borderRadius: 10,
                    background: sel ? TT.accent : TT.surface,
                    border: '1px solid ' + (sel ? TT.accent : TT.hairline),
                    color: sel ? '#fff' : TT.inkSoft,
                    fontFamily: TT.font, fontSize: 12.5, fontWeight: sel ? 600 : 500,
                  }}>{r.label}</button>
                );
              })}
            </div>
          </div>
        )}
      </FormSection>

      {/* Period */}
      <FormSection label="Cycle">
        <ToggleCard icon="heart" label="On period" sub="Logged with this entry for pattern analysis" on={onPeriod} onChange={setOnPeriod}/>
      </FormSection>

      {/* Notes */}
      <FormSection label="Notes">
        <textarea value={notes} onChange={(e) => setNotes(e.target.value)}
          placeholder="Anything else worth remembering?"
          style={{ ...inputStyle, minHeight: 70, padding: '10px 12px', resize: 'vertical' }}/>
      </FormSection>

      <PrimaryButton onClick={save} style={{ marginTop: 16 }}>Save headache</PrimaryButton>
    </Sheet>
  );
}

const inputStyle = {
  width: '100%', height: 44, borderRadius: 12,
  border: '1px solid ' + TT.hairline, background: TT.surface,
  padding: '0 14px', fontFamily: TT.font, fontSize: 14, color: TT.ink,
  outline: 'none', boxSizing: 'border-box',
};

function FormSection({ label, hint, children }) {
  return (
    <div style={{ marginTop: 16 }}>
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 8 }}>
        <Label>{label}</Label>
        {hint && <Muted size={11}>{hint}</Muted>}
      </div>
      {children}
    </div>
  );
}

function ToggleCard({ icon, label, sub, on, onChange }) {
  const I = IC[icon];
  return (
    <div onClick={() => onChange(!on)} style={{
      display: 'flex', alignItems: 'center', gap: 12, cursor: 'pointer',
      padding: '10px 12px', borderRadius: 12,
      background: TT.surface, border: '1px solid ' + TT.hairline,
    }}>
      <div style={{
        width: 32, height: 32, borderRadius: 999,
        background: on ? TT.accentSoft : TT.surfaceAlt,
        color: on ? TT.accentInk : TT.muted,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}><I size={16}/></div>
      <div style={{ flex: 1 }}>
        <div style={{ fontSize: 14, fontWeight: 500, color: TT.ink }}>{label}</div>
        {sub && <div style={{ fontSize: 11.5, color: TT.muted, marginTop: 1 }}>{sub}</div>}
      </div>
      <Switch on={on} onChange={onChange}/>
    </div>
  );
}

// ───────────────── 3) HISTORY ─────────────────
function HistoryScreen({ entries, onSelect }) {
  const [filter, setFilter] = React.useState('all');
  const filtered = entries.filter((e) => {
    if (filter === 'all') return true;
    if (filter === 'severe+') return e.severity === 'severe' || e.severity === 'debilitating';
    if (filter === 'allergy') return e.allergy?.active;
    if (filter === 'month') return Date.now() - new Date(e.occurredAt).getTime() < 30 * 86400000;
    return true;
  });
  const groups = groupByDay(filtered);

  return (
    <Page title="History">
      <div style={{ display: 'flex', gap: 6, marginBottom: 14, overflowX: 'auto' }}>
        {[
          { id: 'all', label: 'All' },
          { id: 'month', label: 'This month' },
          { id: 'severe+', label: 'Severe+' },
          { id: 'allergy', label: 'Allergy days' },
        ].map((f) => (
          <Chip key={f.id} active={filter === f.id} onClick={() => setFilter(f.id)} size="sm">{f.label}</Chip>
        ))}
      </div>

      {filtered.length === 0 && (
        <Card pad={20} style={{ textAlign: 'center' }}>
          <Muted size={14}>No entries match this filter.</Muted>
        </Card>
      )}

      {groups.map((g) => (
        <div key={g.date} style={{ marginBottom: 16 }}>
          <Label style={{ marginBottom: 8 }}>{g.label}</Label>
          {g.entries.map((e) => <HistoryRow key={e.id} entry={e} onClick={() => onSelect(e)}/>)}
        </div>
      ))}
    </Page>
  );
}

function groupByDay(entries) {
  const today = todayDate();
  const yest = localDateStr(new Date(Date.now() - 86400000));
  const map = {};
  entries.forEach((e) => {
    if (!map[e.date]) map[e.date] = [];
    map[e.date].push(e);
  });
  return Object.keys(map).sort().reverse().map((date) => {
    let label;
    if (date === today) label = 'Today · ' + fmtDayLong(date);
    else if (date === yest) label = 'Yesterday · ' + fmtDayLong(date);
    else label = fmtDayLong(date);
    return { date, label, entries: map[date].sort((a, b) => b.occurredAt.localeCompare(a.occurredAt)) };
  });
}

function HistoryRow({ entry, onClick }) {
  return (
    <Card pad={14} style={{ marginBottom: 8, cursor: 'pointer' }}>
      <div onClick={onClick} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 12 }}>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <span style={{ fontFamily: TT.fontDisplay, fontSize: 18, fontWeight: 600, color: TT.ink }}>{fmtClock(entry.occurredAt)}</span>
            <SeverityBadge level={entry.severity} size="sm"/>
          </div>
          {entry.locations?.length > 0 && (
            <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginTop: 8 }}>
              {entry.locations.map((l) => (
                <span key={l} style={{ fontSize: 11, color: TT.inkSoft, background: TT.surfaceAlt, padding: '3px 7px', borderRadius: 999, border: '1px solid ' + TT.hairline }}>{l}</span>
              ))}
            </div>
          )}
          {entry.notes && <Muted size={12.5} style={{ marginTop: 8, lineHeight: 1.45 }}>{entry.notes}</Muted>}
        </div>
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 4, flexShrink: 0 }}>
          {entry.weather?.temp != null && <span style={{ fontSize: 11, color: TT.muted, display: 'inline-flex', alignItems: 'center', gap: 4 }}><IC.sun size={12}/>{entry.weather.temp}°</span>}
          {entry.allergens?.pollenLabel && entry.allergens.pollenLabel !== '—' && <span style={{ fontSize: 11, color: TT.muted, display: 'inline-flex', alignItems: 'center', gap: 4 }}><IC.leaf size={12}/>{entry.allergens.pollenLabel}</span>}
          {entry.medicine?.taken && <span style={{ fontSize: 11, color: TT.muted, display: 'inline-flex', alignItems: 'center', gap: 4 }}><IC.pill size={12}/>{entry.medicine.relief || 'taken'}</span>}
        </div>
      </div>
    </Card>
  );
}

// ───────────────── 4) PATTERNS ─────────────────
function PatternsScreen({ entries }) {
  const [range, setRange] = React.useState('3mo');
  const days = { '1mo': 30, '3mo': 90, '6mo': 180, ytd: dayOfYear() }[range];
  const since = Date.now() - days * 86400000;
  const recent = entries.filter((e) => new Date(e.occurredAt).getTime() >= since);

  const weeklyAvg = recent.length / (days / 7);
  const triggers = countBy(recent, (e) => e.activity || '—');
  const locs = countByMulti(recent, (e) => e.locations);
  const sevCounts = countBy(recent, (e) => e.severity);
  const sevTotal = recent.length || 1;
  const allergyDayPct = recent.length ? Math.round(100 * recent.filter((e) => e.allergens?.pollenLabel === 'High' || e.allergens?.pollenLabel === 'Very high').length / recent.length) : 0;

  return (
    <Page title="Patterns">
      <div style={{ display: 'flex', gap: 6, marginBottom: 14 }}>
        {['1mo', '3mo', '6mo', 'ytd'].map((r) => (
          <Chip key={r} active={range === r} onClick={() => setRange(r)} size="sm">{r === 'ytd' ? 'YTD' : r}</Chip>
        ))}
      </div>

      {recent.length === 0 ? (
        <Card pad={20} style={{ textAlign: 'center' }}>
          <Muted size={14}>Log a few headaches and patterns will appear here.</Muted>
        </Card>
      ) : (
        <>
          <Card pad={14} style={{ marginBottom: 12 }}>
            <Label style={{ marginBottom: 10 }}>Headaches per week</Label>
            <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between' }}>
              <div>
                <div style={{ fontFamily: TT.fontDisplay, fontSize: 34, fontWeight: 600, color: TT.ink, letterSpacing: -0.8, lineHeight: 1 }}>{weeklyAvg.toFixed(1)}</div>
                <Muted size={12} style={{ marginTop: 4 }}>avg / week · {recent.length} total</Muted>
              </div>
              <MiniBars values={computeWeeklyBars(recent, days)} w={150} h={48}/>
            </div>
          </Card>

          <Card pad={14} style={{ marginBottom: 12 }}>
            <Label style={{ marginBottom: 10 }}>Top triggers</Label>
            {triggers.slice(0, 5).map(([label, n]) => (
              <TriggerBar key={label} label={label} pct={n / recent.length} count={n}/>
            ))}
          </Card>

          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
            <Card pad={14}>
              <Label style={{ marginBottom: 10 }}>Severity</Label>
              <div style={{ display: 'flex', height: 10, borderRadius: 999, overflow: 'hidden' }}>
                {window.SEVERITIES.map((s) => {
                  const n = sevCounts.find(([k]) => k === s)?.[1] || 0;
                  return n > 0 ? <div key={s} style={{ flex: n, background: TT.sev[s].dot }}/> : null;
                })}
              </div>
              <div style={{ marginTop: 10, display: 'flex', flexDirection: 'column', gap: 5 }}>
                {window.SEVERITIES.map((s) => {
                  const n = sevCounts.find(([k]) => k === s)?.[1] || 0;
                  return (
                    <div key={s} style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11, color: TT.inkSoft }}>
                      <span style={{ width: 6, height: 6, borderRadius: '50%', background: TT.sev[s].dot }}/>
                      <span style={{ textTransform: 'capitalize', flex: 1 }}>{s}</span>
                      <span style={{ color: TT.muted, fontVariantNumeric: 'tabular-nums' }}>{Math.round(n / sevTotal * 100)}%</span>
                    </div>
                  );
                })}
              </div>
            </Card>
            <Card pad={14}>
              <Label style={{ marginBottom: 10 }}>Top spots</Label>
              {locs.slice(0, 4).map(([label, n]) => {
                const max = locs[0][1];
                return (
                  <div key={label} style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 6 }}>
                    <span style={{ fontSize: 11, color: TT.ink, width: 78, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{label}</span>
                    <div style={{ flex: 1, height: 5, background: TT.subtle, borderRadius: 999, overflow: 'hidden' }}>
                      <div style={{ width: (n / max * 100) + '%', height: '100%', background: TT.accent }}/>
                    </div>
                    <span style={{ fontSize: 10.5, color: TT.muted, fontVariantNumeric: 'tabular-nums', width: 14, textAlign: 'right' }}>{n}</span>
                  </div>
                );
              })}
            </Card>
          </div>

          {allergyDayPct > 0 && (
            <Card pad={14} style={{ marginTop: 12, background: TT.accentSoft, boxShadow: `inset 0 0 0 1px ${TT.hairline}` }}>
              <div style={{ display: 'flex', gap: 12, alignItems: 'flex-start' }}>
                <div style={{ width: 32, height: 32, borderRadius: 999, background: TT.accent, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
                  <IC.spark size={16}/>
                </div>
                <div>
                  <div style={{ fontFamily: TT.font, fontSize: 14, fontWeight: 700, color: TT.accentInk }}>{allergyDayPct}% on high-pollen days</div>
                  <Muted size={12} style={{ marginTop: 4 }}>Of recent headaches landed on days with high or very high pollen.</Muted>
                </div>
              </div>
            </Card>
          )}
        </>
      )}
    </Page>
  );
}

function TriggerBar({ label, pct, count }) {
  return (
    <div style={{ marginTop: 10, marginBottom: 8 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>
        <span style={{ fontSize: 13, color: TT.ink }}>{label}</span>
        <span style={{ fontSize: 12, color: TT.muted, fontVariantNumeric: 'tabular-nums' }}>{count}</span>
      </div>
      <div style={{ height: 6, background: TT.subtle, borderRadius: 999, overflow: 'hidden' }}>
        <div style={{ width: (pct * 100) + '%', height: '100%', background: TT.accent, borderRadius: 999 }}/>
      </div>
    </div>
  );
}

function countBy(arr, getKey) {
  const m = {};
  arr.forEach((e) => { const k = getKey(e); m[k] = (m[k] || 0) + 1; });
  return Object.entries(m).sort((a, b) => b[1] - a[1]);
}

function countByMulti(arr, getKeys) {
  const m = {};
  arr.forEach((e) => { (getKeys(e) || []).forEach((k) => { m[k] = (m[k] || 0) + 1; }); });
  return Object.entries(m).sort((a, b) => b[1] - a[1]);
}

function computeWeeklyBars(entries, days) {
  const weeks = Math.max(2, Math.ceil(days / 7));
  const out = new Array(weeks).fill(0);
  const now = Date.now();
  entries.forEach((e) => {
    const diff = Math.floor((now - new Date(e.occurredAt).getTime()) / (7 * 86400000));
    if (diff >= 0 && diff < weeks) out[weeks - 1 - diff] += 1;
  });
  return out;
}

function dayOfYear() {
  const start = new Date(new Date().getFullYear(), 0, 0);
  return Math.floor((Date.now() - start) / 86400000);
}

// ───────────────── 5) CALENDAR ─────────────────
function CalendarScreen({ entries, onSelectDay }) {
  const [cur, setCur] = React.useState(() => { const d = new Date(); d.setDate(1); return d; });
  const year = cur.getFullYear();
  const month = cur.getMonth();
  const startCol = new Date(year, month, 1).getDay();
  const daysInMonth = new Date(year, month + 1, 0).getDate();

  const dayEntries = {};
  entries.forEach((e) => {
    const d = new Date(e.occurredAt);
    if (d.getFullYear() === year && d.getMonth() === month) {
      const day = d.getDate();
      if (!dayEntries[day]) dayEntries[day] = [];
      dayEntries[day].push(e);
    }
  });

  const worstSev = (list) => {
    const order = ['mild', 'moderate', 'severe', 'debilitating'];
    return list.reduce((a, b) => order.indexOf(b.severity) > order.indexOf(a) ? b.severity : a, 'mild');
  };

  const cells = [];
  for (let i = 0; i < startCol; i++) cells.push({ empty: true });
  for (let d = 1; d <= daysInMonth; d++) {
    const list = dayEntries[d] || [];
    cells.push({ d, list, level: list.length > 0 ? worstSev(list) : null, today: new Date().getFullYear() === year && new Date().getMonth() === month && new Date().getDate() === d });
  }
  while (cells.length % 7) cells.push({ empty: true });

  const monthName = cur.toLocaleDateString(undefined, { month: 'long' });

  return (
    <Page title="Calendar">
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
          <span style={{ fontFamily: TT.fontDisplay, fontSize: 18, fontWeight: 600 }}>{monthName}</span>
          <span style={{ fontFamily: TT.fontDisplay, fontSize: 18, color: TT.muted, fontWeight: 400 }}>{year}</span>
        </div>
        <div style={{ display: 'flex', gap: 6 }}>
          <button onClick={() => setCur(new Date(year, month - 1, 1))} style={navBtn}><IC.back size={14}/></button>
          <button onClick={() => setCur(new Date(year, month + 1, 1))} style={navBtn}><IC.chev size={14}/></button>
        </div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 2, marginBottom: 6 }}>
        {['S','M','T','W','T','F','S'].map((d, i) => (
          <div key={i} style={{ fontSize: 10.5, color: TT.muted, textAlign: 'center', fontWeight: 600, letterSpacing: 0.6 }}>{d}</div>
        ))}
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 4 }}>
        {cells.map((c, i) => {
          if (c.empty) return <div key={i} style={{ height: 44 }}/>;
          const sev = c.level && TT.sev[c.level];
          return (
            <div key={i} onClick={() => c.list?.length && onSelectDay({ year, month, day: c.d, entries: c.list })} style={{
              height: 44, borderRadius: 8,
              background: sev ? sev.bg : 'transparent',
              border: c.today ? '1.5px solid ' + TT.accent : 'none',
              display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
              cursor: c.list?.length ? 'pointer' : 'default',
            }}>
              <span style={{ fontSize: 13, fontWeight: c.today ? 700 : 500, color: sev ? sev.ink : TT.inkSoft }}>{c.d}</span>
              {c.list?.length > 1 && <span style={{ fontSize: 9, color: sev.ink, marginTop: 1 }}>×{c.list.length}</span>}
              {c.list?.length === 1 && <span style={{ width: 4, height: 4, borderRadius: '50%', background: sev.dot, marginTop: 2 }}/>}
            </div>
          );
        })}
      </div>

      <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', marginTop: 14 }}>
        {window.SEVERITIES.map((s) => (
          <div key={s} style={{ display: 'flex', alignItems: 'center', gap: 5, fontSize: 10.5, color: TT.muted }}>
            <span style={{ width: 8, height: 8, borderRadius: 2, background: TT.sev[s].bg, border: '1px solid ' + TT.sev[s].dot }}/>
            <span style={{ textTransform: 'capitalize' }}>{s}</span>
          </div>
        ))}
      </div>
    </Page>
  );
}

const navBtn = {
  width: 32, height: 32, borderRadius: 999,
  background: TT.surface, border: '1px solid ' + TT.hairline,
  color: TT.inkSoft, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer',
};

// ───────────────── 6) EXPORT ─────────────────
function ExportScreen({ entries, user }) {
  const [range, setRange] = React.useState('90');
  const days = parseInt(range, 10);
  const since = Date.now() - days * 86400000;
  const recent = entries.filter((e) => new Date(e.occurredAt).getTime() >= since);

  const downloadCsv = () => {
    const header = 'id,occurredAt,severity,locations,activity,notes,allergyActive,allergySymptoms,medicineTaken,medicineWhat,medicineRelief,onPeriod,temp,condition,humidity,pressure,pollenLabel,mainPollen,aqi';
    const lines = recent.map((e) => [
      e.id, e.occurredAt, e.severity,
      JSON.stringify((e.locations || []).join('|')),
      JSON.stringify(e.activity || ''),
      JSON.stringify((e.notes || '').replace(/\n/g, ' ')),
      e.allergy?.active, JSON.stringify(e.allergy?.symptoms || ''),
      e.medicine?.taken, JSON.stringify(e.medicine?.what || ''), e.medicine?.relief || '',
      e.onPeriod ? 'yes' : '',
      e.weather?.temp ?? '', JSON.stringify(e.weather?.condition || ''), e.weather?.humidity ?? '', e.weather?.pressure ?? '',
      JSON.stringify(e.allergens?.pollenLabel || ''), JSON.stringify((e.allergens?.mainPollen || []).join('|')), e.allergens?.aqi ?? '',
    ].join(','));
    const csv = [header, ...lines].join('\n');
    const blob = new Blob([csv], { type: 'text/csv' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `headaches-${todayDate()}.csv`;
    a.click();
    setTimeout(() => URL.revokeObjectURL(url), 1000);
  };

  const downloadReport = () => {
    // Doctor PDF: print stylesheet handles layout. Open a printable doc in a new window.
    const html = buildDoctorReport(recent, user);
    const w = window.open('', '_blank');
    if (w) {
      w.document.write(html);
      w.document.close();
      setTimeout(() => w.print(), 400);
    }
  };

  const sevPct = (s) => Math.round(100 * recent.filter((e) => e.severity === s).length / Math.max(recent.length, 1));

  return (
    <Page title="Export">
      <Muted size={13} style={{ marginBottom: 14 }}>Share data with your doctor or back up to a spreadsheet.</Muted>
      <div style={{ display: 'flex', gap: 6, marginBottom: 12 }}>
        {[
          { id: '7', label: '7 days' },
          { id: '30', label: '30 days' },
          { id: '90', label: '90 days' },
          { id: '365', label: 'Year' },
        ].map((r) => (
          <Chip key={r.id} active={range === r.id} onClick={() => setRange(r.id)} size="sm">{r.label}</Chip>
        ))}
      </div>

      <Card pad={0} style={{ overflow: 'hidden', marginBottom: 14 }}>
        <div style={{ padding: '14px 14px 10px', borderBottom: '1px solid ' + TT.hairline }}>
          <Label>Doctor's report</Label>
          <H2 style={{ marginTop: 4 }}>{user?.name || 'You'}</H2>
          <Muted size={11} style={{ marginTop: 2 }}>Last {range} days · {recent.length} entries</Muted>
        </div>
        <div style={{ padding: '12px 14px', display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 8 }}>
          <ReportStat value={String(recent.length)} label="entries"/>
          <ReportStat value={(recent.length / (days / 7)).toFixed(1)} label="per week"/>
          <ReportStat value={(sevPct('severe') + sevPct('debilitating')) + '%'} label="severe+"/>
        </div>
      </Card>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        <ExportRow icon="doc"      title="PDF report" sub="One-page summary for your doctor" onClick={downloadReport}/>
        <ExportRow icon="download" title="Spreadsheet (.csv)" sub="Every field, every entry" onClick={downloadCsv}/>
        <ExportRow icon="share"    title="Share link" sub="Read-only, expires in 7 days"/>
      </div>
    </Page>
  );
}

function ReportStat({ value, label }) {
  return (
    <div style={{ textAlign: 'center', padding: '4px 0' }}>
      <div style={{ fontFamily: TT.fontDisplay, fontSize: 22, fontWeight: 600, color: TT.ink, letterSpacing: -0.5 }}>{value}</div>
      <div style={{ fontSize: 10.5, color: TT.muted, letterSpacing: 0.4, textTransform: 'uppercase', fontWeight: 600, marginTop: 2 }}>{label}</div>
    </div>
  );
}

function ExportRow({ icon, title, sub, onClick }) {
  const I = IC[icon];
  return (
    <button onClick={onClick} style={{
      width: '100%', padding: 14, cursor: onClick ? 'pointer' : 'default',
      background: TT.surface, border: '1px solid ' + TT.hairline,
      borderRadius: 12, textAlign: 'left',
      display: 'flex', alignItems: 'center', gap: 12,
      fontFamily: TT.font,
    }}>
      <div style={{ width: 36, height: 36, borderRadius: 999, background: TT.accentSoft, color: TT.accentInk, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><I size={18}/></div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 14, fontWeight: 600, color: TT.ink }}>{title}</div>
        <div style={{ fontSize: 11.5, color: TT.muted, marginTop: 1 }}>{sub}</div>
      </div>
      <IC.chev size={14} style={{ color: TT.muted }}/>
    </button>
  );
}

function buildDoctorReport(entries, user) {
  const rows = entries.map((e) => `
    <tr>
      <td>${new Date(e.occurredAt).toLocaleString()}</td>
      <td>${e.severity}</td>
      <td>${(e.locations || []).join(', ')}</td>
      <td>${e.activity || ''}</td>
      <td>${e.weather?.temp ?? ''}° ${e.weather?.condition || ''}</td>
      <td>${e.allergens?.pollenLabel || ''}</td>
      <td>${e.medicine?.taken ? (e.medicine.what + ' · ' + (e.medicine.relief || '?')) : ''}</td>
      <td>${e.notes || ''}</td>
    </tr>
  `).join('');
  return `<!doctype html><meta charset="utf-8"><title>Headache report</title><style>
    body { font: 12pt/1.4 -apple-system, "SF Pro Text", Helvetica, sans-serif; padding: 0.6in 0.7in; color: #101418; }
    h1 { font-size: 22pt; margin: 0 0 4pt; }
    .meta { color: #6B7384; font-size: 10pt; margin-bottom: 24pt; }
    table { width: 100%; border-collapse: collapse; font-size: 9.5pt; }
    th, td { padding: 6pt 8pt; border-bottom: 0.5pt solid #E4E7EC; text-align: left; vertical-align: top; }
    th { font-size: 8pt; text-transform: uppercase; letter-spacing: 0.6pt; color: #6B7384; }
    @page { margin: 0.5in; }
  </style>
  <h1>Headache log</h1>
  <div class="meta">${user?.name || ''} · ${user?.email || ''} · ${entries.length} entries · generated ${new Date().toLocaleString()}</div>
  <table><thead><tr><th>When</th><th>Severity</th><th>Location</th><th>Activity</th><th>Weather</th><th>Pollen</th><th>Medicine</th><th>Notes</th></tr></thead>
  <tbody>${rows}</tbody></table>`;
}

// ───────────────── 7) SETTINGS ─────────────────
function SettingsScreen({ user, pendingSync, lastSync, shares, onShareChange, onSwitchViewAs, viewAs }) {
  return (
    <Page title="Settings">
      <Card pad={14} style={{ marginBottom: 14 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <div style={{
            width: 48, height: 48, borderRadius: 999,
            background: TT.accentSoft, color: TT.accentInk,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontFamily: TT.fontDisplay, fontSize: 18, fontWeight: 600,
          }}>{user ? user.name.split(/\s+/).map(p => p[0]).slice(0, 2).join('') : '—'}</div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 15, fontWeight: 600, color: TT.ink }}>{user?.name || 'Not signed in'}</div>
            <div style={{ fontSize: 12, color: TT.muted, marginTop: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{user?.email}</div>
          </div>
        </div>
        <div style={{
          marginTop: 10, padding: '8px 10px', background: TT.surfaceAlt,
          borderRadius: 8, fontSize: 11, color: TT.muted,
          display: 'flex', alignItems: 'center', gap: 6,
        }}>
          <IC.check size={12} style={{ color: TT.accent }}/>
          {user?.source === 'cloudflare-access' ? 'Signed in via Cloudflare Access' :
           user?.source === 'cf-jwt-cookie' ? 'CF Access JWT detected (unverified — verify server-side)' :
           user?.source === 'meta' ? 'Identity from worker-injected meta' :
           'Demo mode · running unprotected for local dev'}
        </div>
      </Card>

      <SettingsGroup label="Tracking">
        <SettingsRow icon="pin"   title="Location"      detail="Birmingham, AL"/>
        <SettingsRow icon="leaf"  title="Allergens & air quality" detail="On"/>
        <SettingsRow icon="heart" title="On period tracking" detail="On · checkbox per entry"/>
      </SettingsGroup>

      <SharingSection
        shares={shares || { grantedToOthers: [], grantedToMe: [] }}
        onChange={onShareChange}
        onSwitchViewAs={onSwitchViewAs}
        viewAs={viewAs}
      />

      <SettingsGroup label="Data">
        <SettingsRow icon="sync"  title="Pending sync"  detail={pendingSync ? `${pendingSync} queued` : 'Up to date'} badge={pendingSync ? String(pendingSync) : null}/>
        <SettingsRow icon="download" title="Export all data"/>
      </SettingsGroup>

      <SettingsGroup label="App">
        <SettingsRow icon="bolt"  title="Version" detail="1.0.0"/>
      </SettingsGroup>
    </Page>
  );
}

function SettingsGroup({ label, children }) {
  return (
    <div style={{ marginBottom: 14 }}>
      <Label style={{ marginBottom: 6, paddingLeft: 4 }}>{label}</Label>
      <div style={{ background: TT.surface, borderRadius: 12, border: '1px solid ' + TT.hairline, overflow: 'hidden' }}>
        {React.Children.map(children, (c, i) => (
          <div style={i > 0 ? { borderTop: '1px solid ' + TT.hairline } : {}}>{c}</div>
        ))}
      </div>
    </div>
  );
}

function SettingsRow({ icon, title, detail, badge }) {
  const I = IC[icon];
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 14px', cursor: 'pointer' }}>
      <div style={{ width: 28, height: 28, borderRadius: 7, background: TT.accentSoft, color: TT.accentInk, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}><I size={15}/></div>
      <div style={{ flex: 1, fontSize: 14, color: TT.ink, fontWeight: 500 }}>{title}</div>
      {badge && <span style={{ fontSize: 10.5, padding: '2px 8px', borderRadius: 999, background: TT.accentSoft, color: TT.accentInk, fontWeight: 600 }}>{badge}</span>}
      {detail && <span style={{ fontSize: 12.5, color: TT.muted }}>{detail}</span>}
      <IC.chev size={13} style={{ color: TT.muted, flexShrink: 0 }}/>
    </div>
  );
}

// ── Day drawer (shown when calendar day is tapped) ──────────────
function DayDrawer({ open, day, onClose }) {
  if (!open || !day) return null;
  const date = new Date(day.year, day.month, day.day);
  return (
    <Sheet open={open} onClose={onClose}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 14 }}>
        <div>
          <H2 style={{ fontSize: 22 }}>{date.toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric' })}</H2>
          <Muted size={12} style={{ marginTop: 2 }}>{day.entries.length} headache{day.entries.length > 1 ? 's' : ''}</Muted>
        </div>
        <button onClick={onClose} style={{ ...navBtn, borderRadius: 999 }}><IC.x size={14}/></button>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {day.entries.map((e) => (
          <Card key={e.id} pad={14}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <span style={{ fontFamily: TT.fontDisplay, fontSize: 17, fontWeight: 600 }}>{fmtClock(e.occurredAt)}</span>
              <SeverityBadge level={e.severity} size="sm"/>
            </div>
            {e.notes && <Muted size={12.5} style={{ marginTop: 8 }}>{e.notes}</Muted>}
            <div style={{ display: 'flex', gap: 6, marginTop: 8, flexWrap: 'wrap' }}>
              {(e.locations || []).map((l) => (
                <span key={l} style={{ fontSize: 11, color: TT.inkSoft, background: TT.surfaceAlt, padding: '3px 8px', borderRadius: 999, border: '1px solid ' + TT.hairline }}>{l}</span>
              ))}
            </div>
          </Card>
        ))}
      </div>
    </Sheet>
  );
}

// ───────────────── Sharing (in Settings) ─────────────────
function SharingSection({ shares, onChange, onSwitchViewAs, viewAs }) {
  const [inviteEmail, setInviteEmail] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');

  const submit = async () => {
    setErr('');
    const email = inviteEmail.trim().toLowerCase();
    if (!email || !email.includes('@')) { setErr('Enter a valid email.'); return; }
    setBusy(true);
    try {
      await StoreApi.createShare(email);
      setInviteEmail('');
      onChange && (await onChange());
    } catch (e) {
      setErr('Could not send invite. Try again.');
    } finally {
      setBusy(false);
    }
  };

  const revoke = async (id) => {
    await StoreApi.deleteShare(id);
    onChange && (await onChange());
  };
  const accept = async (id) => {
    await StoreApi.acceptShare(id);
    onChange && (await onChange());
  };
  const reject = async (id) => {
    await StoreApi.deleteShare(id);
    onChange && (await onChange());
  };

  const grantedToOthers = shares.grantedToOthers || [];
  const grantedToMe = shares.grantedToMe || [];

  return (
    <div style={{ marginBottom: 14 }}>
      <Label style={{ marginBottom: 6, paddingLeft: 4 }}>Sharing</Label>
      <div style={{ background: TT.surface, borderRadius: 12, border: '1px solid ' + TT.hairline, overflow: 'hidden' }}>

        <div style={{ padding: '12px 14px', borderBottom: '1px solid ' + TT.hairline }}>
          <div style={{ fontSize: 11, fontWeight: 600, letterSpacing: 0.5, textTransform: 'uppercase', color: TT.muted, marginBottom: 8 }}>Invite someone to view your data</div>
          <div style={{ display: 'flex', gap: 6 }}>
            <input type="email" autoCapitalize="none" autoCorrect="off" value={inviteEmail}
              onChange={(e) => setInviteEmail(e.target.value)}
              placeholder="their@email.com"
              style={{ flex: 1, height: 40, borderRadius: 10, border: '1px solid ' + TT.hairline, background: TT.surfaceAlt, padding: '0 12px', fontFamily: TT.font, fontSize: 13, color: TT.ink, outline: 'none', boxSizing: 'border-box' }}/>
            <button onClick={submit} disabled={busy} style={{
              height: 40, padding: '0 14px', borderRadius: 10, border: 'none',
              background: busy ? TT.subtle : TT.accent, color: '#fff',
              fontFamily: TT.font, fontWeight: 600, fontSize: 13, cursor: busy ? 'default' : 'pointer',
            }}>Invite</button>
          </div>
          {err && <Muted size={11} style={{ marginTop: 6, color: '#A03A3A' }}>{err}</Muted>}
        </div>

        {grantedToOthers.length > 0 && (
          <div style={{ padding: '12px 14px', borderBottom: grantedToMe.length > 0 ? '1px solid ' + TT.hairline : 'none' }}>
            <div style={{ fontSize: 11, fontWeight: 600, letterSpacing: 0.5, textTransform: 'uppercase', color: TT.muted, marginBottom: 8 }}>People who can view your data</div>
            {grantedToOthers.map((s) => (
              <GrantedRow key={s.id} share={s} onRevoke={() => revoke(s.id)} onReinvite={async () => {
                await StoreApi.createShare(s.viewerEmail); onChange && (await onChange());
              }}/>
            ))}
          </div>
        )}

        {grantedToMe.length > 0 && (
          <div style={{ padding: '12px 14px' }}>
            <div style={{ fontSize: 11, fontWeight: 600, letterSpacing: 0.5, textTransform: 'uppercase', color: TT.muted, marginBottom: 8 }}>Shared with you</div>
            {grantedToMe.map((s) => (
              <ReceivedRow key={s.id} share={s}
                onAccept={() => accept(s.id)}
                onReject={() => reject(s.id)}
                onView={() => onSwitchViewAs && onSwitchViewAs({ email: s.ownerEmail, name: s.ownerEmail })}
                isCurrent={viewAs && viewAs.email === s.ownerEmail}
              />
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

function StatusBadge({ status }) {
  const map = {
    pending:  { bg: '#F4E6CF', ink: '#7A5A22', label: 'Pending' },
    accepted: { bg: '#D8E8D8', ink: '#2F5C36', label: 'Active' },
    revoked:  { bg: '#E5ECEF', ink: '#3F5560', label: 'Revoked' },
  };
  const c = map[status] || map.pending;
  return (
    <span style={{
      display: 'inline-flex', height: 20, padding: '0 8px', borderRadius: 999,
      background: c.bg, color: c.ink,
      fontFamily: TT.font, fontSize: 10.5, fontWeight: 600, letterSpacing: 0.1,
      alignItems: 'center',
    }}>{c.label}</span>
  );
}

function GrantedRow({ share, onRevoke, onReinvite }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '6px 0' }}>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 13, color: TT.ink, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{share.viewerEmail}</div>
        <div style={{ marginTop: 2 }}><StatusBadge status={share.status}/></div>
      </div>
      {share.status === 'revoked'
        ? <button onClick={onReinvite} style={smallBtnGhost}>Re-invite</button>
        : <button onClick={onRevoke}   style={smallBtnGhost}>Revoke</button>}
    </div>
  );
}

function ReceivedRow({ share, onAccept, onReject, onView, isCurrent }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '6px 0' }}>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 13, color: TT.ink, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{share.ownerEmail}</div>
        <div style={{ marginTop: 2 }}><StatusBadge status={share.status}/></div>
      </div>
      {share.status === 'pending' && (
        <>
          <button onClick={onAccept} style={smallBtnPrimary}>Accept</button>
          <button onClick={onReject} style={smallBtnGhost}>Decline</button>
        </>
      )}
      {share.status === 'accepted' && (
        <button onClick={onView} style={smallBtnPrimary}>{isCurrent ? 'Viewing' : 'View'}</button>
      )}
    </div>
  );
}

const smallBtnPrimary = {
  height: 28, padding: '0 12px', borderRadius: 999, border: 'none',
  background: TT.accent, color: '#fff',
  fontFamily: TT.font, fontSize: 12, fontWeight: 600, cursor: 'pointer',
};
const smallBtnGhost = {
  height: 28, padding: '0 12px', borderRadius: 999,
  background: 'transparent', color: TT.inkSoft,
  border: '1px solid ' + TT.hairline,
  fontFamily: TT.font, fontSize: 12, fontWeight: 500, cursor: 'pointer',
};

Object.assign(window, {
  HomeScreen, LogForm, HistoryScreen, PatternsScreen, CalendarScreen, ExportScreen, SettingsScreen, DayDrawer,
});
