// homepages.jsx — Sunrise homepage (Variation A) wired to real chat data.
// Other variations removed; user picked A.

const PALETTES = {
  sunrise: {
    name: 'Sunrise',
    bg: '#FFF6EE',
    surface: '#FFFFFF',
    ink: '#2A1810',
    inkSoft: '#7A5A48',
    accent1: '#FF7B54',  // coral
    accent2: '#FFC857',  // peach-yellow
    accent3: '#F2545B',  // warm red
    accent4: '#7BAFD4',  // sky
    accent5: '#A8C686',  // sage
    accent6: '#C490D1',  // soft violet
    chip:    '#FFE4D2',
  },
};

const SYSTEM_ACCENT = {
  cardio: 'accent3', pulm: 'accent4', gi: 'accent2', nephro: 'accent6',
  neuro: 'accent4', endo: 'accent5', hema: 'accent3', trauma: 'accent1', emerg: 'accent3', other: 'accent5',
};

// ── Tiny SVG illustrations ──────────────────────────────────────

function HeartIcon({ size = 36, color = '#F2545B', stroke = '#2A1810' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 40 40" fill="none">
      <path d="M20 33 C 6 24, 4 12, 12 9 C 16 7, 19 10, 20 13 C 21 10, 24 7, 28 9 C 36 12, 34 24, 20 33 Z"
            fill={color} stroke={stroke} strokeWidth="1.5" strokeLinejoin="round"/>
      <path d="M11 18 L 14 18 L 16 14 L 19 22 L 21 18 L 24 18" stroke={stroke} strokeWidth="1.4" fill="none" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  );
}

function LungsIcon({ size = 36, color = '#7BAFD4', stroke = '#2A1810' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 40 40" fill="none">
      <path d="M20 8 V 22" stroke={stroke} strokeWidth="1.5" strokeLinecap="round"/>
      <path d="M20 22 C 14 22, 9 26, 9 32 C 9 34, 11 35, 13 34 C 16 33, 18 28, 18 24" fill={color} stroke={stroke} strokeWidth="1.5" strokeLinejoin="round"/>
      <path d="M20 22 C 26 22, 31 26, 31 32 C 31 34, 29 35, 27 34 C 24 33, 22 28, 22 24" fill={color} stroke={stroke} strokeWidth="1.5" strokeLinejoin="round"/>
    </svg>
  );
}

function PillIcon({ size = 36, color = '#FFC857', stroke = '#2A1810' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 40 40" fill="none">
      <rect x="6" y="14" width="28" height="12" rx="6" transform="rotate(-15 20 20)" fill={color} stroke={stroke} strokeWidth="1.5"/>
      <line x1="20" y1="11" x2="20" y2="29" stroke={stroke} strokeWidth="1.5" transform="rotate(-15 20 20)"/>
    </svg>
  );
}

function KidneyIcon({ size = 36, color = '#C490D1', stroke = '#2A1810' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 40 40" fill="none">
      <path d="M14 8 C 8 10, 6 18, 8 26 C 10 33, 18 35, 22 32 C 26 29, 24 25, 26 22 C 28 19, 30 14, 26 10 C 22 6, 18 6, 14 8 Z"
            fill={color} stroke={stroke} strokeWidth="1.5" strokeLinejoin="round"/>
      <circle cx="18" cy="20" r="2" fill={stroke}/>
    </svg>
  );
}

function BrainIcon({ size = 36, color = '#7BAFD4', stroke = '#2A1810' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 40 40" fill="none">
      <path d="M14 10 C 10 10, 8 14, 10 17 C 7 19, 8 24, 12 25 C 12 29, 16 31, 20 29 C 24 31, 28 29, 28 25 C 32 24, 33 19, 30 17 C 32 14, 30 10, 26 10 C 24 7, 16 7, 14 10 Z"
            fill={color} stroke={stroke} strokeWidth="1.5" strokeLinejoin="round"/>
      <path d="M20 11 V 29 M14 16 C 16 16, 17 18, 16 20 M26 16 C 24 16, 23 18, 24 20" stroke={stroke} strokeWidth="1.2" fill="none" strokeLinecap="round"/>
    </svg>
  );
}

function DropIcon({ size = 36, color = '#F2545B', stroke = '#2A1810' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 40 40" fill="none">
      <path d="M20 6 C 26 14, 30 20, 30 26 C 30 32, 26 35, 20 35 C 14 35, 10 32, 10 26 C 10 20, 14 14, 20 6 Z"
            fill={color} stroke={stroke} strokeWidth="1.5" strokeLinejoin="round"/>
    </svg>
  );
}

function BoneIcon({ size = 36, color = '#FF7B54', stroke = '#2A1810' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 40 40" fill="none">
      <path d="M10 12 C 8 8, 12 6, 14 9 C 16 7, 20 9, 18 13 L 26 21 C 30 19, 33 23, 31 26 C 33 28, 31 32, 27 31 C 26 33, 22 33, 23 28 L 15 20 C 12 22, 8 19, 10 16 C 8 14, 8 12, 10 12 Z"
            fill={color} stroke={stroke} strokeWidth="1.5" strokeLinejoin="round"/>
    </svg>
  );
}

function ECGLine({ width = 200, height = 40, color = '#F2545B', stroke = 2 }) {
  return (
    <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`} fill="none" preserveAspectRatio="none">
      <path d={`M0 ${height/2} L${width*0.2} ${height/2} L${width*0.25} ${height/2-2} L${width*0.3} ${height/2+3} L${width*0.34} ${height/2-15} L${width*0.38} ${height/2+8} L${width*0.42} ${height/2} L${width*0.6} ${height/2} L${width*0.65} ${height/2-4} L${width*0.7} ${height/2} L${width} ${height/2}`}
            stroke={color} strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" fill="none"/>
    </svg>
  );
}

const SYSTEM_ICONS = {
  cardio: HeartIcon, pulm: LungsIcon, gi: PillIcon, nephro: KidneyIcon,
  neuro: BrainIcon, endo: PillIcon, hema: DropIcon, trauma: BoneIcon, emerg: HeartIcon, other: PillIcon,
};

function Squiggle({ color, style }) {
  return (
    <svg viewBox="0 0 200 40" style={style} preserveAspectRatio="none">
      <path d="M0 20 Q 25 5, 50 20 T 100 20 T 150 20 T 200 20" stroke={color} strokeWidth="2.5" fill="none" strokeLinecap="round"/>
    </svg>
  );
}

// ── Shared chrome ──────────────────────────────────────────────

function StreakBadge({ streak, accent, ink }) {
  return (
    <div style={{
      display: 'inline-flex', alignItems: 'center', gap: 6, padding: '6px 12px',
      background: '#fff', borderRadius: 999, border: `1.5px solid ${accent}`,
      fontWeight: 600, fontSize: 13, color: ink,
    }}>
      <span style={{ fontSize: 14 }}>🔥</span>
      <span>{streak} day streak</span>
    </div>
  );
}

function GoalRing({ pct, size = 64, color, track = '#0001', label }) {
  const r = (size - 8) / 2;
  const c = 2 * Math.PI * r;
  return (
    <div style={{ position: 'relative', width: size, height: size, flexShrink: 0 }}>
      <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
        <circle cx={size/2} cy={size/2} r={r} stroke={track} strokeWidth="6" fill="none"/>
        <circle cx={size/2} cy={size/2} r={r} stroke={color} strokeWidth="6" fill="none"
                strokeDasharray={c} strokeDashoffset={c * (1 - pct)} strokeLinecap="round"
                style={{ transition: 'stroke-dashoffset .6s cubic-bezier(.3,.7,.3,1)' }}/>
      </svg>
      {label && (
        <div style={{ position: 'absolute', inset: 0, display: 'grid', placeItems: 'center',
                      fontSize: 11, fontWeight: 600 }}>{label}</div>
      )}
    </div>
  );
}

// ── Favorites hook (localStorage-backed) ───────────────────────

const FAV_KEY = 'med-hub-favorites-v1';
function useFavorites() {
  const [favs, setFavs] = React.useState(() => {
    try { return new Set(JSON.parse(localStorage.getItem(FAV_KEY) || '[]')); } catch { return new Set(); }
  });
  const persist = (next) => { try { localStorage.setItem(FAV_KEY, JSON.stringify([...next])); } catch {} };
  const toggle = (id) => setFavs(prev => {
    const next = new Set(prev);
    if (next.has(id)) next.delete(id); else next.add(id);
    persist(next);
    return next;
  });
  return [favs, toggle];
}

// ── Responsive hook ─────────────────────────────────────────────
function useIsMobile(breakpoint = 768) {
  const [isMobile, setIsMobile] = React.useState(() =>
    typeof window !== 'undefined' && window.matchMedia(`(max-width: ${breakpoint - 1}px)`).matches
  );
  React.useEffect(() => {
    const mq = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);
    const handler = e => setIsMobile(e.matches);
    if (mq.addEventListener) mq.addEventListener('change', handler);
    else mq.addListener(handler);
    return () => {
      if (mq.removeEventListener) mq.removeEventListener('change', handler);
      else mq.removeListener(handler);
    };
  }, [breakpoint]);
  return isMobile;
}

function FavStar({ active, onClick, size = 16, palette }) {
  return (
    <button onClick={(e) => { e.stopPropagation(); onClick(); }} aria-label={active ? 'Unfavorite' : 'Favorite'}
            style={{
              background: 'transparent', border: 0, padding: 4, cursor: 'pointer',
              display: 'grid', placeItems: 'center', borderRadius: 6, lineHeight: 0,
              color: active ? palette.accent2 : palette.inkSoft + '80',
            }}>
      <svg width={size} height={size} viewBox="0 0 24 24" fill={active ? 'currentColor' : 'none'} stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
        <polygon points="12 2 15 8.5 22 9.3 17 14.1 18.2 21 12 17.8 5.8 21 7 14.1 2 9.3 9 8.5 12 2"/>
      </svg>
    </button>
  );
}

// ── Sunrise Home (real data) ───────────────────────────────────

// ── Live date / countdown helpers ──────────────────────────────
function useLiveDate() {
  const [now, setNow] = React.useState(() => new Date());
  React.useEffect(() => {
    // Tick at next minute boundary, then every minute
    const ms = 60000 - (Date.now() % 60000);
    let interval;
    const t = setTimeout(() => {
      setNow(new Date());
      interval = setInterval(() => setNow(new Date()), 60000);
    }, ms);
    return () => { clearTimeout(t); if (interval) clearInterval(interval); };
  }, []);
  return now;
}

function daysUntil(target, now) {
  // Compare midnight-to-midnight in local time so we get whole-day counts
  const a = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  const b = new Date(target.getFullYear(), target.getMonth(), target.getDate());
  return Math.round((b - a) / (24*60*60*1000));
}

function greeting(h) {
  if (h < 5) return 'Good night';
  if (h < 12) return 'Good morning';
  if (h < 17) return 'Good afternoon';
  if (h < 21) return 'Good evening';
  return 'Good night';
}

const M2_LABEL = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
const MONTHS_LONG = ['January','February','March','April','May','June','July','August','September','October','November','December'];
const DAYS_LONG = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
const MONTHS_SHORT = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];

function HomeSunrise({ nav, palette = PALETTES.sunrise }) {
  const d = window.MED_DATA;
  const fontHead = `'Instrument Serif', 'Cormorant Garamond', Georgia, serif`;
  const fontBody = `'Geist', 'Inter', system-ui, sans-serif`;
  const [search, setSearch] = React.useState('');
  const [activeSystem, setActiveSystem] = React.useState('all');
  const [sortMode, setSortMode] = React.useState(() => {
    try { return localStorage.getItem('med-hub-sort') || 'recent'; } catch { return 'recent'; }
  });
  React.useEffect(() => { try { localStorage.setItem('med-hub-sort', sortMode); } catch {} }, [sortMode]);
  const [page, setPage] = React.useState(1);
  const [perPage, setPerPage] = React.useState(() => {
    try { return parseInt(localStorage.getItem('med-hub-perpage') || '20', 10) || 20; } catch { return 20; }
  });
  React.useEffect(() => { try { localStorage.setItem('med-hub-perpage', String(perPage)); } catch {} }, [perPage]);
  const [favs, toggleFav] = useFavorites();
  const isMobile = useIsMobile();

  // Live date — re-renders every minute
  const now = useLiveDate();
  const examDate = new Date(2026, 9, 18);   // Oct 18 2026 (month is 0-indexed)
  const nextStudyDate = new Date(2026, 5, 29); // Jun 29 2026
  const daysToExam = daysUntil(examDate, now);
  const daysToNext = daysUntil(nextStudyDate, now);
  const dateLabel = `${DAYS_LONG[now.getDay()]} · ${MONTHS_SHORT[now.getMonth()]} ${now.getDate()}`;

  // Sort & pin newest as recents
  const allByRecent = React.useMemo(() =>
    [...d.chats].sort((a, b) => (b.uploadedAt || 0) - (a.uploadedAt || 0)),
    [d.chats]);
  const pinned = allByRecent.slice(0, 3);

  // Live system counts from data
  const liveSystemCounts = React.useMemo(() => {
    const m = {};
    for (const c of d.chats) m[c.system] = (m[c.system] || 0) + 1;
    return m;
  }, [d.chats]);

  const filtered = React.useMemo(() => {
    let xs = d.chats;
    if (activeSystem !== 'all') xs = xs.filter(c => c.system === activeSystem);
    if (search.trim()) {
      const q = search.toLowerCase();
      xs = xs.filter(c => c.title.toLowerCase().includes(q));
    }
    if (sortMode === 'recent') {
      xs = [...xs].sort((a, b) => (b.uploadedAt || 0) - (a.uploadedAt || 0));
    } else if (sortMode === 'oldest') {
      xs = [...xs].sort((a, b) => (a.uploadedAt || 0) - (b.uploadedAt || 0));
    } else if (sortMode === 'az') {
      xs = [...xs].sort((a, b) => a.title.localeCompare(b.title));
    } else if (sortMode === 'za') {
      xs = [...xs].sort((a, b) => b.title.localeCompare(a.title));
    } else if (sortMode === 'progress') {
      xs = [...xs].sort((a, b) => (b.progress || 0) - (a.progress || 0));
    }
    return xs;
  }, [d.chats, activeSystem, search, sortMode]);

  // Reset page when filters change
  React.useEffect(() => { setPage(1); }, [search, activeSystem, perPage, sortMode]);

  const totalPages = Math.max(1, Math.ceil(filtered.length / perPage));
  const safePage = Math.min(page, totalPages);
  const pageStart = (safePage - 1) * perPage;
  const pageItems = filtered.slice(pageStart, pageStart + perPage);

  return (
    <div style={{ background: palette.bg, color: palette.ink, minHeight: '100%',
                  fontFamily: fontBody, padding: isMobile ? '20px 16px 80px' : '32px 36px 60px', position: 'relative', overflow: 'hidden' }}>
      {/* decorative sun */}
      <div style={{ position: 'absolute', top: -120, right: -80, width: 320, height: 320, borderRadius: '50%',
                    background: `radial-gradient(circle, ${palette.accent2}66, transparent 70%)`, pointerEvents: 'none' }}/>
      <div style={{ position: 'absolute', top: 30, right: 60, opacity: .35 }}>
        <Squiggle color={palette.accent1} style={{ width: 140, height: 24 }}/>
      </div>

      {/* Header */}
      <header style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start',
                       marginBottom: isMobile ? 22 : 32, position: 'relative', zIndex: 1, gap: 12 }}>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: isMobile ? 10 : 12, fontWeight: 600, letterSpacing: '.12em', textTransform: 'uppercase', color: palette.inkSoft, marginBottom: 6 }}>
            {dateLabel}
          </div>
          <h1 style={{ fontFamily: fontHead, fontSize: isMobile ? 34 : 52, fontWeight: 400, margin: 0, lineHeight: 1.15, letterSpacing: '-0.02em', paddingBottom: 6 }}>
            {greeting(now.getHours())}, <em style={{ color: palette.accent1, fontStyle: 'italic' }}>{d.user.name}</em>
          </h1>
          {!isMobile && (
            <p style={{ marginTop: 10, color: palette.inkSoft, fontSize: 15, maxWidth: 560 }}>
              {d.chats.length} interactive references in your library — pick a topic and dive in.
            </p>
          )}
        </div>
        <div style={{ display: 'flex', gap: isMobile ? 6 : 10, alignItems: 'center', flexShrink: 0 }}>
          {!isMobile && <StreakBadge streak={d.user.streak} accent={palette.accent1} ink={palette.ink}/>}
          <div style={{ width: isMobile ? 32 : 36, height: isMobile ? 32 : 36, borderRadius: '50%', background: palette.accent1, color: '#fff',
                        display: 'grid', placeItems: 'center', fontWeight: 700, fontSize: 14 }}>{d.user.name.split(/\s+/).map(s => s[0]).slice(0,2).join('')}</div>
        </div>
      </header>

      {/* Hero stats row — countdowns + library */}
      <section style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '1.4fr 1fr 1fr',
                        gap: isMobile ? 10 : 14, marginBottom: isMobile ? 22 : 28, position: 'relative', zIndex: 1 }}>
        {/* EXAM countdown — primary */}
        <div style={{ background: palette.accent1, color: '#fff', borderRadius: 18, padding: isMobile ? 16 : 20, position: 'relative', overflow: 'hidden' }}>
          <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', opacity: .85 }}>Exam day · 18 Oct 2026</div>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, marginTop: 10, flexWrap: 'wrap' }}>
            <div style={{ fontFamily: fontHead, fontSize: isMobile ? 64 : 88, lineHeight: 1, fontVariantNumeric: 'tabular-nums' }}>
              {Math.max(0, daysToExam)}
            </div>
            <div style={{ fontFamily: fontHead, fontSize: isMobile ? 22 : 28, opacity: .9 }}>
              {daysToExam === 1 ? 'day' : 'days'} to go
            </div>
          </div>
          <div style={{ marginTop: 14, fontSize: 13, opacity: .9 }}>
            {daysToExam <= 0 ? 'You\'ve got this — exam day is here ✦' :
             daysToExam <= 7 ? 'Final stretch — trust your prep ✦' :
             daysToExam <= 30 ? 'One month out — focus on weak spots ✦' :
             `~${Math.ceil(daysToExam/7)} weeks to keep building momentum ✦`}
          </div>
          <div style={{ position: 'absolute', bottom: -10, right: -10, opacity: .15 }}>
            <HeartIcon size={120} color="#fff" stroke="#fff"/>
          </div>
        </div>

        {/* Next study milestone */}
        {!isMobile && (
          <div style={{ background: palette.surface, borderRadius: 18, padding: 18, border: `1px solid ${palette.ink}10`, position: 'relative', overflow: 'hidden' }}>
            <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: palette.inkSoft }}>Next milestone · 29 Jun 2026</div>
            <div style={{ fontFamily: fontHead, fontSize: 56, lineHeight: 1, marginTop: 8, fontVariantNumeric: 'tabular-nums', color: palette.accent3 }}>
              {Math.max(0, daysToNext)}
            </div>
            <div style={{ fontSize: 13, color: palette.inkSoft, marginTop: 4 }}>
              {daysToNext === 1 ? 'day' : 'days'} away
            </div>
            <div style={{ display: 'flex', gap: 3, marginTop: 12, alignItems: 'flex-end', height: 28 }}>
              {Array.from({length: 14}).map((_, i) => {
                const filled = daysToNext > 0 && i >= 14 - Math.min(14, daysToNext);
                return <div key={i} style={{ flex: 1, height: '100%', background: filled ? palette.accent3 : palette.chip, borderRadius: 2 }}/>;
              })}
            </div>
          </div>
        )}

        {/* Library card */}
        {!isMobile && (
          <div style={{ background: palette.surface, borderRadius: 18, padding: 18, border: `1px solid ${palette.ink}10` }}>
            <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: palette.inkSoft }}>Library</div>
            <div style={{ fontFamily: fontHead, fontSize: 56, lineHeight: 1, marginTop: 8, fontVariantNumeric: 'tabular-nums' }}>{d.chats.length}</div>
            <div style={{ fontSize: 12, color: palette.inkSoft, marginTop: 4 }}>chats across {d.systems.filter(s => liveSystemCounts[s.id]).length} systems</div>
            <div style={{ display: 'flex', gap: 4, marginTop: 10, flexWrap: 'wrap' }}>
              {d.systems.filter(s => liveSystemCounts[s.id]).slice(0, 6).map(s => (
                <div key={s.id} title={`${s.label} — ${liveSystemCounts[s.id]}`} style={{ width: 8, height: 16, background: palette[SYSTEM_ACCENT[s.id]] || palette.accent1, borderRadius: 2 }}/>
              ))}
            </div>
          </div>
        )}

        {/* Mobile-only compact second card combining milestone + library */}
        {isMobile && (
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
            <div style={{ background: palette.surface, borderRadius: 18, padding: 14, border: `1px solid ${palette.ink}10` }}>
              <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '.08em', textTransform: 'uppercase', color: palette.inkSoft }}>29 Jun</div>
              <div style={{ fontFamily: fontHead, fontSize: 36, lineHeight: 1, marginTop: 6, color: palette.accent3, fontVariantNumeric: 'tabular-nums' }}>{Math.max(0, daysToNext)}</div>
              <div style={{ fontSize: 11, color: palette.inkSoft, marginTop: 2 }}>days away</div>
            </div>
            <div style={{ background: palette.surface, borderRadius: 18, padding: 14, border: `1px solid ${palette.ink}10` }}>
              <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '.08em', textTransform: 'uppercase', color: palette.inkSoft }}>Library</div>
              <div style={{ fontFamily: fontHead, fontSize: 36, lineHeight: 1, marginTop: 6, fontVariantNumeric: 'tabular-nums' }}>{d.chats.length}</div>
              <div style={{ fontSize: 11, color: palette.inkSoft, marginTop: 2 }}>chats</div>
            </div>
          </div>
        )}
      </section>

      {/* Recently uploaded */}
      <section style={{ marginBottom: 24, position: 'relative', zIndex: 1 }}>
        <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 12 }}>
          <h2 style={{ fontFamily: fontHead, fontSize: isMobile ? 22 : 26, fontWeight: 400, margin: 0, lineHeight: 1.6, paddingBottom: 8 }}>Recently <em style={{ color: palette.accent1 }}>uploaded</em></h2>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : 'repeat(3, 1fr)', gap: isMobile ? 10 : 12 }}>
          {pinned.map(c => {
            const Icon = SYSTEM_ICONS[c.system] || PillIcon;
            return (
              <button key={c.id} onClick={() => nav('chat', c.id)} style={{
                background: palette.surface, border: `1px solid ${palette.ink}10`, borderRadius: 18,
                padding: 16, textAlign: 'left', cursor: 'pointer', display: 'flex', flexDirection: 'column', gap: 10,
                font: 'inherit', color: 'inherit', minHeight: 150,
                transition: 'transform .15s, box-shadow .15s',
              }} onMouseEnter={e => e.currentTarget.style.transform = 'translateY(-2px)'} onMouseLeave={e => e.currentTarget.style.transform = ''}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 10 }}>
                  <div style={{ width: 44, height: 44, borderRadius: 12, background: palette.chip, display: 'grid', placeItems: 'center', flexShrink: 0 }}>
                    <Icon size={28} color={palette[SYSTEM_ACCENT[c.system]]} stroke={palette.ink}/>
                  </div>
                  <span style={{ fontSize: 10, fontWeight: 700, letterSpacing: '.08em', textTransform: 'uppercase', color: palette.inkSoft }}>{c.lastStudied}</span>
                </div>
                <div style={{ fontWeight: 600, fontSize: 15, lineHeight: 1.3,
                              display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden' }}>{c.title}</div>
                <div style={{ marginTop: 'auto', display: 'flex', alignItems: 'center', gap: 8 }}>
                  <div style={{ flex: 1, height: 4, background: palette.chip, borderRadius: 2, overflow: 'hidden' }}>
                    <div style={{ width: `${c.progress*100}%`, height: '100%', background: palette.accent1 }}/>
                  </div>
                  <span style={{ fontSize: 11, color: palette.inkSoft, fontVariantNumeric: 'tabular-nums' }}>{Math.round(c.progress*100)}%</span>
                </div>
              </button>
            );
          })}
        </div>
      </section>

      {/* Quick actions */}
      <section style={{ marginBottom: 28, position: 'relative', zIndex: 1 }}>
        <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : 'repeat(3, 1fr)', gap: isMobile ? 8 : 12 }}>
          {[
            { label: 'Random topic', sub: 'Surprise me with a chat', accent: palette.accent2, action: () => nav('chat', d.chats[Math.floor(Math.random()*d.chats.length)].id), icon: '◐' },
            { label: 'Favorites', sub: favs.size ? `${favs.size} saved chat${favs.size===1?'':'s'}` : 'Star chats to save them here', accent: palette.accent3, action: () => nav('favorites'), icon: '★' },
            { label: 'Last opened', sub: pinned[0]?.title || '—', accent: palette.accent4, action: () => nav('chat', pinned[0]?.id), icon: '✦' },
          ].map(a => (
            <button key={a.label} onClick={a.action} style={{
              background: palette.surface, border: `1px solid ${palette.ink}10`, borderRadius: 16,
              padding: 14, textAlign: 'left', cursor: 'pointer', font: 'inherit', color: 'inherit',
              display: 'flex', gap: 12, alignItems: 'center',
            }}>
              <div style={{ width: 40, height: 40, borderRadius: 10, background: a.accent, color: '#fff',
                            display: 'grid', placeItems: 'center', fontSize: 18, fontWeight: 700 }}>{a.icon}</div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontWeight: 600, fontSize: 14 }}>{a.label}</div>
                <div style={{ fontSize: 12, color: palette.inkSoft, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{a.sub}</div>
              </div>
              <div style={{ color: palette.inkSoft }}>→</div>
            </button>
          ))}
        </div>
      </section>

      {/* Library: search + filter + list */}
      <section style={{ position: 'relative', zIndex: 1 }}>
        <div style={{ display: isMobile ? 'block' : 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 12, gap: 12 }}>
          <h2 style={{ fontFamily: fontHead, fontSize: isMobile ? 22 : 26, fontWeight: 400, margin: 0, lineHeight: 1.6, paddingBottom: 8 }}>Your <em style={{ color: palette.accent1 }}>library</em> <span style={{ fontFamily: fontBody, fontSize: 13, color: palette.inkSoft, fontWeight: 500, marginLeft: 6 }}>{d.chats.length} chats</span></h2>
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginTop: isMobile ? 6 : 0 }}>
            <select value={sortMode} onChange={e => setSortMode(e.target.value)}
              aria-label="Sort chats"
              style={{ padding: '10px 14px', paddingRight: 32, borderRadius: 999, border: `1px solid ${palette.ink}20`,
                       background: palette.surface, font: 'inherit', color: palette.ink, outline: 'none', fontSize: 14,
                       appearance: 'none', cursor: 'pointer',
                       backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M2 4l4 4 4-4' stroke='${encodeURIComponent(palette.ink)}' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")`,
                       backgroundRepeat: 'no-repeat', backgroundPosition: 'right 12px center' }}>
              <option value="recent">Recently uploaded</option>
              <option value="oldest">Oldest first</option>
              <option value="az">A → Z</option>
              <option value="za">Z → A</option>
              <option value="progress">Most progress</option>
            </select>
            <input value={search} onChange={e => setSearch(e.target.value)} placeholder={`Search ${d.chats.length} chats…`}
              style={{ flex: isMobile ? '1 1 100%' : '0 0 240px', width: isMobile ? '100%' : undefined, padding: '10px 14px', borderRadius: 999, border: `1px solid ${palette.ink}20`,
                       background: palette.surface, font: 'inherit', color: palette.ink, outline: 'none', fontSize: 14 }}/>
          </div>
        </div>

        {/* System chips */}
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 14 }}>
          <SystemChip active={activeSystem === 'all'} onClick={() => setActiveSystem('all')} palette={palette}
                      label="All" count={d.chats.length} accent={palette.ink}/>
          {d.systems.filter(s => liveSystemCounts[s.id]).map(s => (
            <SystemChip key={s.id} active={activeSystem === s.id} onClick={() => setActiveSystem(s.id)} palette={palette}
                        label={s.label} count={liveSystemCounts[s.id]} accent={palette[SYSTEM_ACCENT[s.id]]}/>
          ))}
        </div>

        {/* Chat list — denser */}
        <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : 'repeat(2, 1fr)', gap: 8 }}>
          {pageItems.map(c => {
            const Icon = SYSTEM_ICONS[c.system] || PillIcon;
            const isFav = favs.has(c.id);
            return (
              <button key={c.id} onClick={() => nav('chat', c.id)} style={{
                background: palette.surface, border: `1px solid ${palette.ink}10`, borderRadius: 12,
                padding: '12px 14px', textAlign: 'left', cursor: 'pointer', font: 'inherit', color: 'inherit',
                display: 'flex', gap: 12, alignItems: 'center',
              }}>
                <div style={{ width: 32, height: 32, borderRadius: 8, background: palette.chip, display: 'grid', placeItems: 'center', flexShrink: 0 }}>
                  <Icon size={20} color={palette[SYSTEM_ACCENT[c.system]]} stroke={palette.ink}/>
                </div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontWeight: 500, fontSize: 14, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{c.title}</div>
                  <div style={{ fontSize: 11, color: palette.inkSoft, marginTop: 2 }}>
                    {(d.systems.find(s => s.id === c.system)?.label) || 'Other'} · {c.lastStudied}
                  </div>
                </div>
                <FavStar active={isFav} onClick={() => toggleFav(c.id)} palette={palette}/>
                <div style={{ width: 26, height: 4, background: palette.chip, borderRadius: 2, overflow: 'hidden' }}>
                  <div style={{ width: `${c.progress*100}%`, height: '100%', background: palette.accent1 }}/>
                </div>
              </button>
            );
          })}
        </div>

        {filtered.length === 0 && (
          <div style={{ textAlign: 'center', padding: 32, color: palette.inkSoft, fontSize: 14 }}>No chats match.</div>
        )}

        {filtered.length > 0 && (
          <Pagination palette={palette} page={safePage} setPage={setPage} totalPages={totalPages}
                      perPage={perPage} setPerPage={setPerPage} total={filtered.length}
                      pageStart={pageStart} pageEnd={Math.min(pageStart + perPage, filtered.length)}/>
        )}
      </section>
    </div>
  );
}

function Pagination({ palette, page, setPage, totalPages, perPage, setPerPage, total, pageStart, pageEnd }) {
  const isMobile = useIsMobile();
  const btnStyle = (disabled) => ({
    background: palette.surface, color: disabled ? palette.inkSoft + '60' : palette.ink,
    border: `1px solid ${palette.ink}15`, borderRadius: 8, padding: '6px 12px',
    cursor: disabled ? 'default' : 'pointer', font: 'inherit', fontSize: 13,
    minWidth: 36, display: 'inline-grid', placeItems: 'center',
  });
  const numStyle = (active) => ({
    background: active ? palette.accent1 : palette.surface,
    color: active ? '#fff' : palette.ink,
    border: `1px solid ${active ? palette.accent1 : palette.ink + '15'}`,
    borderRadius: 8, padding: '6px 0', cursor: 'pointer', font: 'inherit', fontSize: 13,
    fontWeight: active ? 600 : 500, minWidth: 36, fontVariantNumeric: 'tabular-nums',
  });

  // Build page numbers with windowing: 1 … (p-1) p (p+1) … last
  const nums = [];
  const window = 1;
  const add = (n) => nums.push(n);
  if (totalPages <= 7) {
    for (let i = 1; i <= totalPages; i++) add(i);
  } else {
    add(1);
    if (page - window > 2) add('…');
    for (let i = Math.max(2, page - window); i <= Math.min(totalPages - 1, page + window); i++) add(i);
    if (page + window < totalPages - 1) add('…');
    add(totalPages);
  }

  return (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: isMobile ? 'center' : 'space-between', gap: 12, marginTop: 16, flexWrap: 'wrap' }}>
      <div style={{ fontSize: 12, color: palette.inkSoft, fontVariantNumeric: 'tabular-nums', order: isMobile ? 3 : 1, width: isMobile ? '100%' : 'auto', textAlign: isMobile ? 'center' : 'left' }}>
        Showing <strong>{pageStart + 1}–{pageEnd}</strong> of <strong>{total}</strong>
      </div>

      <div style={{ display: 'flex', alignItems: 'center', gap: 6, order: isMobile ? 1 : 2, flexWrap: 'wrap', justifyContent: 'center' }}>
        <button onClick={() => setPage(p => Math.max(1, p - 1))} disabled={page === 1} style={btnStyle(page === 1)}>‹</button>
        {nums.map((n, i) =>
          n === '…' ?
            <span key={'e'+i} style={{ padding: '0 4px', color: palette.inkSoft, fontSize: 13 }}>…</span> :
            <button key={n} onClick={() => setPage(n)} style={numStyle(n === page)}>{n}</button>
        )}
        <button onClick={() => setPage(p => Math.min(totalPages, p + 1))} disabled={page === totalPages} style={btnStyle(page === totalPages)}>›</button>
      </div>

      <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12, color: palette.inkSoft, order: isMobile ? 2 : 3 }}>
        <span>Per page</span>
        <select value={perPage} onChange={e => setPerPage(parseInt(e.target.value, 10))} style={{
          background: palette.surface, border: `1px solid ${palette.ink}20`, borderRadius: 8,
          padding: '6px 8px', font: 'inherit', fontSize: 13, color: palette.ink, cursor: 'pointer',
        }}>
          {[10, 20, 30, 50, 100].map(n => <option key={n} value={n}>{n}</option>)}
        </select>
      </div>
    </div>
  );
}

function SystemChip({ active, onClick, palette, label, count, accent }) {
  return (
    <button onClick={onClick} style={{
      background: active ? palette.ink : palette.surface,
      color: active ? '#fff' : palette.ink,
      border: `1px solid ${active ? palette.ink : palette.ink + '20'}`,
      borderRadius: 999, padding: '6px 12px', cursor: 'pointer', font: 'inherit',
      fontSize: 12, fontWeight: 500, display: 'flex', alignItems: 'center', gap: 6,
    }}>
      <span style={{ width: 6, height: 6, borderRadius: '50%', background: accent }}/>
      {label}
      <span style={{ opacity: .55, fontVariantNumeric: 'tabular-nums' }}>{count}</span>
    </button>
  );
}

Object.assign(window, {
  PALETTES, SYSTEM_ICONS, SYSTEM_ACCENT,
  HeartIcon, LungsIcon, PillIcon, KidneyIcon, BrainIcon, DropIcon, BoneIcon,
  ECGLine, Squiggle, StreakBadge, GoalRing, HomeSunrise,
  useFavorites, FavStar, FAV_KEY, Pagination, useIsMobile,
});
