// CredNX dashboard — Phase 1 enhancements.
// Adds: Home, Sessions (filtered), Insights, Settings, Command Palette, Notifications.
// All visual; no new API endpoints required. Mock data is marked NEEDS BACKEND.

// ============================================================
//  Time-aware greeting
// ============================================================
function greeting(name) {
  const h = new Date().getHours();
  const w = h < 5 ? 'Working late' : h < 12 ? 'Good morning' : h < 17 ? 'Good afternoon' : h < 22 ? 'Good evening' : 'Working late';
  return `${w}, ${(name || '').split(' ')[0] || 'there'}`;
}
function todayLabel() {
  const d = new Date();
  return d.toLocaleDateString('en-GB', { weekday:'long', day:'numeric', month:'long' });
}

// ============================================================
//  Sparkline (small line for KPI tiles)
// ============================================================
const Sparkline = ({ data, w = 100, h = 28, color = 'hsl(var(--primary))', fill = 'hsl(var(--accent-soft))' }) => {
  if (!data || data.length < 2) return <div style={{ width: w, height: h }}/>;
  const max = Math.max(...data), min = Math.min(...data);
  const span = max - min || 1;
  const pts = data.map((d, i) => [
    (i / (data.length - 1)) * w,
    h - 2 - ((d - min) / span) * (h - 4),
  ]);
  const dstr = 'M' + pts.map(p => p.join(',')).join(' L');
  const area = dstr + ` L${w},${h} L0,${h} Z`;
  return (
    <svg width={w} height={h} style={{ display: 'block' }}>
      <path d={area} fill={fill}/>
      <path d={dstr} stroke={color} strokeWidth="1.75" fill="none" strokeLinecap="round" strokeLinejoin="round"/>
      <circle cx={pts[pts.length - 1][0]} cy={pts[pts.length - 1][1]} r="2" fill={color}/>
    </svg>
  );
};

// ============================================================
//  Stat tile (richer KPI used on Home)
// ============================================================
function StatTile({ label, value, delta, deltaTone = 'success', icon, accent = 'brand', spark }) {
  const accentMap = {
    brand:   { bg:'hsl(var(--accent-soft))',   fg:'hsl(var(--primary))',   line:'hsl(var(--primary))',  fill:'hsl(var(--accent-soft))' },
    success: { bg:'hsl(var(--success-bg))',    fg:'hsl(var(--success-fg))', line:'hsl(var(--success))',  fill:'hsl(var(--success-bg))' },
    warning: { bg:'hsl(var(--warning-bg))',    fg:'hsl(var(--warning-fg))', line:'hsl(var(--warning))',  fill:'hsl(var(--warning-bg))' },
    info:    { bg:'hsl(var(--accent-soft))',   fg:'hsl(var(--accent))',     line:'hsl(var(--accent))',   fill:'hsl(var(--accent-soft))' },
  };
  const a = accentMap[accent] || accentMap.brand;
  const deltaColor = deltaTone === 'danger' ? 'hsl(var(--danger))' : deltaTone === 'warning' ? 'hsl(var(--warning-fg))' : 'hsl(var(--success-fg))';
  return (
    <Card padding={20} className="cx-hover-lift">
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:14 }}>
        <div style={{ width:34, height:34, borderRadius:10, background:a.bg, color:a.fg, display:'inline-flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
          {icon}
        </div>
        {delta && <span style={{ fontSize:12, fontWeight:600, color:deltaColor, padding:'2px 8px', background:`${deltaColor}/0.1`, borderRadius:999, border:`1px solid ${deltaColor}30` }}>{delta}</span>}
      </div>
      <div style={{ fontSize:12, color:'hsl(var(--fg-muted))', fontWeight:500, marginBottom:6, letterSpacing:'0.01em' }}>{label}</div>
      <div style={{ display:'flex', alignItems:'flex-end', justifyContent:'space-between', gap:10 }}>
        <div style={{ fontFamily:'var(--font-serif)', fontSize:36, fontWeight:400, color:'hsl(var(--fg))', letterSpacing:'-0.025em', lineHeight:1 }}>{value}</div>
        {spark && <Sparkline data={spark} w={88} h={28} color={a.line} fill={a.fill}/>}
      </div>
    </Card>
  );
}

// ============================================================
//  Activity feed
// ============================================================
// NEEDS BACKEND: replace this with /api/v1/activity feed of org-wide events.
const ACTIVITY_FALLBACK = [
  { kind:'session_completed', who:'Aditya Rahman', target:'BRW-2847', detail:'Bank statement analysis finished', when:'2 min ago' },
  { kind:'session_started',   who:'Siti Nuraini',  target:'BRW-3104', detail:'Started credit bureau analysis', when:'18 min ago' },
  { kind:'decision_approved', who:'Fina Lestari',  target:'BRW-2931', detail:'Approved facility · Rp 5.2B at 11.5% p.a.', when:'42 min ago' },
  { kind:'session_failed',    who:'system',         target:'BRW-3104', detail:'Analysis failed — file unreadable', when:'1 hour ago' },
  { kind:'team_invited',      who:'Fina Lestari',   target:'rendra.p@bankx.id', detail:'Invited as Viewer', when:'3 hours ago' },
  { kind:'session_completed', who:'Aditya Rahman',  target:'BRW-3012', detail:'Bank statement analysis finished', when:'4 hours ago' },
];
const KIND_META = {
  session_completed: { tone:'success', icon:<I.checkCircle/>, verb:'completed analysis for' },
  session_started:   { tone:'brand',   icon:<I.upload/>,      verb:'started analysing' },
  session_failed:    { tone:'danger',  icon:<I.alert/>,       verb:'failed analysis for' },
  decision_approved: { tone:'success', icon:<I.zap/>,         verb:'approved' },
  team_invited:      { tone:'brand',   icon:<I.users/>,       verb:'invited' },
};
function ActivityFeed({ events }) {
  const list = events || ACTIVITY_FALLBACK;
  return (
    <div style={{ display:'flex', flexDirection:'column' }}>
      {list.map((e, i) => {
        const m = KIND_META[e.kind] || { tone:'neutral', icon:<I.activity/>, verb:'updated' };
        const bg     = `hsl(var(--${m.tone}-bg))`;
        const border = `hsl(var(--${m.tone}) / 0.3)`;
        const fg     = `hsl(var(--${m.tone}-fg))`;
        return (
          <div key={i} style={{ display:'flex', gap:12, padding:'14px 0', borderTop: i === 0 ? 'none' : '1px solid hsl(var(--border))' }}>
            <div style={{ width:36, height:36, borderRadius:10, background:bg, color:fg, border:`1px solid ${border}`, display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
              {m.icon}
            </div>
            <div style={{ flex:1, minWidth:0 }}>
              <div style={{ fontSize:13, color:'hsl(var(--fg))', lineHeight:1.45 }}>
                <b style={{ fontWeight:600 }}>{e.who}</b> {m.verb}{' '}
                <span style={{ fontFamily:'var(--font-mono)', fontSize:12, padding:'1px 5px', background:'hsl(var(--surface-2))', borderRadius:4, color:'hsl(var(--fg))' }}>{e.target}</span>
              </div>
              <div style={{ fontSize:12, color:'hsl(var(--fg-muted))', marginTop:3 }}>{e.detail}</div>
            </div>
            <div style={{ fontSize:11, color:'hsl(var(--fg-subtle))', flexShrink:0, whiteSpace:'nowrap', alignSelf:'center' }}>{e.when}</div>
          </div>
        );
      })}
    </div>
  );
}

// ============================================================
//  Home page
// ============================================================
function HomePage({ user, borrowers, onNavigate }) {
  // Derive stats from borrowers / sessions
  const allSessions = React.useMemo(() => {
    return (borrowers || []).flatMap(b => b.sessions || []);
  }, [borrowers]);

  const today = React.useMemo(() => {
    const start = new Date(); start.setHours(0,0,0,0);
    return allSessions.filter(s => s._raw?.created_at && new Date(s._raw.created_at) >= start);
  }, [allSessions]);

  const completedToday = today.filter(s => s.status === 'completed').length;
  const processing     = allSessions.filter(s => s.status === 'processing').length;
  const failed         = allSessions.filter(s => s.status === 'failed').length;
  const total          = allSessions.length;
  const completedAll   = allSessions.filter(s => s.status === 'completed').length;
  const approvalRate   = total > 0 ? Math.round((completedAll / total) * 100) : 0;
  const pending        = (borrowers || []).reduce((sum, b) => sum + ((b.total_sessions || 0) - (b.completed_sessions || 0)), 0);

  // Synthetic 7-day spark (NEEDS BACKEND: replace with real timeseries)
  const sevenDay     = [3, 5, 4, 7, 6, 9, today.length || 1];
  const approvalTrend = [62, 68, 65, 72, 70, 76, approvalRate || 78];
  const queueTrend    = [2, 4, 3, 5, 4, 6, pending];
  const timeTrend     = [5.2, 4.8, 4.5, 4.4, 4.0, 3.9, 4.2];

  const recentBorrowers = (borrowers || []).slice(0, 5);

  return (
    <div style={{ padding:'24px 32px 48px', maxWidth:1320, margin:'0 auto' }}>
      {/* Greeting strip */}
      <div className="cx-fadein" style={{ marginBottom:22 }}>
        <div style={{ display:'flex', alignItems:'baseline', gap:14, flexWrap:'wrap', marginBottom:6 }}>
          <div style={{ fontFamily:'var(--font-serif)', fontSize:36, fontWeight:400, letterSpacing:'-0.025em', color:'hsl(var(--fg))' }}>
            {greeting(user?.name)}<span style={{ fontStyle:'italic', color:'hsl(var(--primary))' }}>.</span>
          </div>
          <div style={{ fontSize:13, color:'hsl(var(--fg-muted))' }}><I.calendar style={{ verticalAlign:'middle', marginRight:6 }}/>{todayLabel()}</div>
        </div>
        <div style={{ fontSize:14, color:'hsl(var(--fg-muted))' }}>
          {processing > 0 ? <><b style={{ color:'hsl(var(--fg))' }}>{processing}</b> session{processing === 1 ? '' : 's'} in progress · </> : null}
          <b style={{ color:'hsl(var(--fg))' }}>{completedToday}</b> completed today · <b style={{ color:'hsl(var(--fg))' }}>{pending}</b> pending review
        </div>
      </div>

      {/* KPI tiles */}
      <div style={{ display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:14, marginBottom:18 }}>
        <StatTile label="Sessions today" value={today.length} delta={today.length ? '+' + today.length : '—'} icon={<I.upload/>} accent="brand" spark={sevenDay}/>
        <StatTile label="Pending review" value={pending} delta={pending > 0 ? `${pending} to action` : 'Inbox zero'} deltaTone={pending > 0 ? 'warning' : 'success'} icon={<I.clock/>} accent="warning" spark={queueTrend}/>
        <StatTile label="Approval rate (7d)" value={`${approvalRate}%`} delta={approvalRate >= 70 ? '+5pp WoW' : '−2pp'} deltaTone={approvalRate >= 70 ? 'success' : 'danger'} icon={<I.zap/>} accent="success" spark={approvalTrend}/>
        <StatTile label="Avg analysis time" value="4.2m" delta="−18% WoW" deltaTone="success" icon={<I.activity/>} accent="info" spark={timeTrend}/>
      </div>

      {/* Two-column row: Activity + Quick actions */}
      <div style={{ display:'grid', gridTemplateColumns:'2fr 1fr', gap:14, marginBottom:18 }}>
        <Card padding={20}>
          <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:6 }}>
            <div style={{ display:'flex', alignItems:'center', gap:8 }}>
              <I.activity style={{ color:'hsl(var(--accent))' }}/>
              <div style={{ fontSize:15, fontWeight:600, color:'hsl(var(--fg))' }}>Recent activity</div>
            </div>
            <a href="#" className="cx-link" style={{ fontSize:13 }} onClick={e => { e.preventDefault(); onNavigate && onNavigate('sessions'); }}>View all sessions →</a>
          </div>
          <ActivityFeed/>
        </Card>
        <Card padding={20}>
          <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:14 }}>
            <I.zap style={{ color:'hsl(var(--accent))' }}/>
            <div style={{ fontSize:15, fontWeight:600, color:'hsl(var(--fg))' }}>Quick actions</div>
          </div>
          <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
            <Button variant="primary" full size="md" icon={<I.upload/>} onClick={() => onNavigate && onNavigate('underwrite')}>Start new session</Button>
            <Button variant="secondary" full size="md" icon={<I.layers/>} onClick={() => onNavigate && onNavigate('sessions')}>View all sessions {pending > 0 ? <Badge tone="warning" size="sm" style={{ marginLeft:6 }}>{pending}</Badge> : null}</Button>
            <Button variant="secondary" full size="md" icon={<I.users/>} onClick={() => onNavigate && onNavigate('borrowers')}>Browse borrowers</Button>
            <Button variant="ghost" full size="md" icon={<I.chart/>} onClick={() => onNavigate && onNavigate('insights')}>View insights</Button>
          </div>
          <div style={{ marginTop:16, padding:14, background:'var(--gradient-deep)', color:'hsl(var(--surface-deep-fg))', borderRadius:14 }}>
            <div style={{ display:'flex', alignItems:'center', gap:6, fontSize:11, fontWeight:600, color:'hsl(var(--accent))', textTransform:'uppercase', letterSpacing:'0.06em', marginBottom:6 }}>
              <I.command/> Tip
            </div>
            <div style={{ fontSize:12, color:'hsl(var(--surface-deep-fg) / 0.85)', lineHeight:1.55 }}>
              Press <kbd style={{ padding:'2px 6px', borderRadius:4, background:'hsl(var(--surface-deep-fg) / 0.16)', fontFamily:'var(--font-mono)', fontSize:11 }}>⌘ K</kbd> anywhere to jump to borrowers, sessions, or run a quick action.
            </div>
          </div>
        </Card>
      </div>

      {/* Recent borrowers */}
      <Card padding={0}>
        <div style={{ padding:'16px 20px', borderBottom:'1px solid hsl(var(--border))', display:'flex', alignItems:'center', gap:8 }}>
          <I.users style={{ color:'hsl(var(--accent))' }}/>
          <div style={{ fontSize:15, fontWeight:600, color:'hsl(var(--fg))', flex:1 }}>Recent borrowers</div>
          <a href="#" className="cx-link" style={{ fontSize:13 }} onClick={e => { e.preventDefault(); onNavigate && onNavigate('borrowers'); }}>See all →</a>
        </div>
        {borrowers === undefined ? (
          <div style={{ padding:'48px 20px', textAlign:'center', color:'hsl(var(--fg-muted))', display:'flex', alignItems:'center', justifyContent:'center', gap:10 }}>
            <Spinner size={16}/> Loading borrowers…
          </div>
        ) : recentBorrowers.length === 0 ? (
          <div style={{ padding:'40px 20px', textAlign:'center' }}>
            <div style={{ width:48, height:48, margin:'0 auto 14px', borderRadius:14, background:'hsl(var(--accent-soft))', display:'flex', alignItems:'center', justifyContent:'center', color:'hsl(var(--primary))', border:'1px solid hsl(var(--accent) / 0.25)' }}><I.users/></div>
            <div style={{ fontFamily:'var(--font-serif)', fontSize:22, fontWeight:400, color:'hsl(var(--fg))', letterSpacing:'-0.02em', marginBottom:6 }}>No borrowers <span style={{ fontStyle:'italic' }}>yet</span></div>
            <div style={{ fontSize:13, color:'hsl(var(--fg-muted))', marginBottom:16, maxWidth:380, margin:'0 auto 16px' }}>Once you start your first analysis, borrowers will appear here.</div>
            <Button variant="primary" icon={<I.upload/>} onClick={() => onNavigate && onNavigate('underwrite')}>Start first session</Button>
          </div>
        ) : (
          <div>
            {recentBorrowers.map((b, i) => (
              <div key={b.customer_id} className="cx-row" style={{ display:'flex', alignItems:'center', gap:14, padding:'14px 20px', borderTop: i === 0 ? 'none' : '1px solid hsl(var(--border))', cursor:'pointer' }}
                onClick={() => onNavigate && onNavigate('borrowers')}>
                <Avatar name={b.customer_id} size={36}/>
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ fontSize:14, fontWeight:600, color:'hsl(var(--fg))' }}>{b.customer_id}</div>
                  <div style={{ fontSize:12, color:'hsl(var(--fg-muted))', marginTop:2 }}>{b.total_sessions ?? 0} sessions · {b.completed_sessions ?? 0} completed</div>
                </div>
                {(b.total_sessions || 0) > (b.completed_sessions || 0) && (
                  <Badge tone="warning" size="sm">{(b.total_sessions || 0) - (b.completed_sessions || 0)} pending</Badge>
                )}
                <I.chevronRight style={{ color:'hsl(var(--fg-subtle))' }}/>
              </div>
            ))}
          </div>
        )}
      </Card>
    </div>
  );
}

// ============================================================
//  Sessions (filtered) — flat across borrowers
// ============================================================
function SessionsTable({ borrowers, onOpenSession }) {
  const [statusFilter, setStatusFilter] = React.useState('all');
  const [docFilter, setDocFilter]       = React.useState('all');
  const [rangeFilter, setRangeFilter]   = React.useState('all');
  const [search, setSearch]             = React.useState('');
  const [sortKey, setSortKey]           = React.useState('created');
  const [sortDir, setSortDir]           = React.useState('desc');

  const allSessions = React.useMemo(() => (borrowers || []).flatMap(b => b.sessions || []), [borrowers]);

  const filtered = React.useMemo(() => {
    const now = Date.now();
    const cutoff = rangeFilter === '7d' ? 7*86400000 : rangeFilter === '30d' ? 30*86400000 : rangeFilter === '24h' ? 86400000 : null;
    return allSessions.filter(s => {
      if (statusFilter !== 'all' && s.status !== statusFilter) return false;
      if (docFilter !== 'all' && s.type !== docFilter) return false;
      if (cutoff && s._raw?.created_at && (now - new Date(s._raw.created_at).getTime()) > cutoff) return false;
      if (search) {
        const q = search.toLowerCase();
        if (!(s.id.toLowerCase().includes(q) || s.borrower.toLowerCase().includes(q) || (s.borrowerName||'').toLowerCase().includes(q))) return false;
      }
      return true;
    });
  }, [allSessions, statusFilter, docFilter, rangeFilter, search]);

  const sorted = React.useMemo(() => {
    const arr = [...filtered];
    arr.sort((a, b) => {
      let av, bv;
      if (sortKey === 'created') { av = new Date(a._raw?.created_at || 0).getTime(); bv = new Date(b._raw?.created_at || 0).getTime(); }
      else if (sortKey === 'borrower') { av = a.borrower; bv = b.borrower; }
      else if (sortKey === 'type') { av = a.type; bv = b.type; }
      else if (sortKey === 'docs') { av = a.docs; bv = b.docs; }
      else if (sortKey === 'status') { av = a.status; bv = b.status; }
      if (av < bv) return sortDir === 'asc' ? -1 : 1;
      if (av > bv) return sortDir === 'asc' ? 1 : -1;
      return 0;
    });
    return arr;
  }, [filtered, sortKey, sortDir]);

  const docTypes = React.useMemo(() => Array.from(new Set(allSessions.map(s => s.type))).sort(), [allSessions]);

  const counts = {
    all:        allSessions.length,
    completed:  allSessions.filter(s => s.status === 'completed').length,
    processing: allSessions.filter(s => s.status === 'processing').length,
    failed:     allSessions.filter(s => s.status === 'failed').length,
  };

  const setSort = (k) => {
    if (sortKey === k) setSortDir(d => d === 'asc' ? 'desc' : 'asc');
    else { setSortKey(k); setSortDir('desc'); }
  };
  const sortGlyph = (k) => sortKey === k ? (sortDir === 'asc' ? ' ↑' : ' ↓') : '';

  if (borrowers === undefined) {
    return (
      <div style={{ padding:'40px 32px', display:'flex', alignItems:'center', justifyContent:'center', gap:12, color:'hsl(var(--fg-muted))' }}>
        <Spinner size={18}/><span style={{ fontSize:14 }}>Loading sessions…</span>
      </div>
    );
  }

  return (
    <div style={{ padding:'24px 32px' }}>
      <Card padding={0}>
        {/* Filter bar */}
        <div style={{ padding:'14px 18px', borderBottom:'1px solid hsl(var(--border))', display:'flex', flexDirection:'column', gap:12 }}>
          <div style={{ display:'flex', alignItems:'center', gap:8, flexWrap:'wrap' }}>
            {[
              ['all','All',counts.all],
              ['completed','Completed',counts.completed,'success'],
              ['processing','Processing',counts.processing,'warning'],
              ['failed','Failed',counts.failed,'danger'],
            ].map(([key,label,n,tone]) => {
              const active = statusFilter === key;
              const accent = tone || 'brand';
              return (
                <button key={key} onClick={() => setStatusFilter(key)}
                  style={{
                    display:'inline-flex', alignItems:'center', gap:6,
                    height:32, padding:'0 12px', borderRadius:999, border:'1px solid',
                    fontFamily:'inherit', fontSize:13, fontWeight:500, cursor:'pointer',
                    color: active ? `hsl(var(--${accent === 'brand' ? 'primary' : accent + '-fg'}))` : 'hsl(var(--fg-muted))',
                    background: active ? `hsl(var(--${accent === 'brand' ? 'accent-soft' : accent + '-bg'}))` : 'hsl(var(--surface))',
                    borderColor: active ? `hsl(var(--${accent === 'brand' ? 'primary' : accent}) / 0.4)` : 'hsl(var(--border))',
                    transition: 'background 150ms, color 150ms, border-color 150ms',
                  }}>
                  {label}
                  <span style={{ minWidth:18, height:18, padding:'0 5px', borderRadius:9, background: active ? 'hsl(var(--surface) / 0.5)' : 'hsl(var(--surface-2))', color:'inherit', fontSize:11, fontWeight:600, display:'inline-flex', alignItems:'center', justifyContent:'center' }}>{n}</span>
                </button>
              );
            })}
          </div>
          <div style={{ display:'flex', alignItems:'center', gap:8, flexWrap:'wrap' }}>
            <div style={{ display:'flex', alignItems:'center', gap:8, height:36, padding:'0 12px', borderRadius:10, border:'1px solid hsl(var(--border))', flex:'1 1 220px', maxWidth:340, background:'hsl(var(--surface))' }}>
              <I.search style={{ color:'hsl(var(--fg-subtle))', flexShrink:0 }}/>
              <input value={search} onChange={e => setSearch(e.target.value)} placeholder="Search by session ID or borrower"
                style={{ flex:1, border:'none', outline:'none', fontSize:13, fontFamily:'inherit', color:'hsl(var(--fg))', background:'transparent' }}/>
              {search && <button onClick={() => setSearch('')} style={{ width:20, height:20, border:'none', background:'transparent', cursor:'pointer', color:'hsl(var(--fg-subtle))', display:'inline-flex', alignItems:'center', justifyContent:'center' }}><I.x/></button>}
            </div>
            <select value={docFilter} onChange={e => setDocFilter(e.target.value)}
              style={{ height:36, padding:'0 10px', borderRadius:10, border:'1px solid hsl(var(--border))', fontSize:13, fontFamily:'inherit', color:'hsl(var(--fg))', background:'hsl(var(--surface))', cursor:'pointer' }}>
              <option value="all">All document types</option>
              {docTypes.map(t => <option key={t} value={t}>{t}</option>)}
            </select>
            <div style={{ display:'inline-flex', height:36, borderRadius:10, border:'1px solid hsl(var(--border))', overflow:'hidden', background:'hsl(var(--surface))' }}>
              {[['24h','24h'],['7d','7d'],['30d','30d'],['all','All']].map(([k,l],i) => {
                const active = rangeFilter === k;
                return (
                  <button key={k} onClick={() => setRangeFilter(k)}
                    style={{ padding:'0 12px', border:'none', background: active ? 'hsl(var(--accent-soft))' : 'transparent', color: active ? 'hsl(var(--primary))' : 'hsl(var(--fg-muted))', fontFamily:'inherit', fontSize:13, fontWeight:500, cursor:'pointer', borderLeft: i === 0 ? 'none' : '1px solid hsl(var(--border))' }}>{l}</button>
                );
              })}
            </div>
            <div style={{ flex:1 }}/>
            <span style={{ fontSize:12, color:'hsl(var(--fg-muted))' }}>Showing <b style={{ color:'hsl(var(--fg))' }}>{sorted.length}</b> of {allSessions.length}</span>
          </div>
        </div>

        {sorted.length === 0 ? (
          <div style={{ padding:'48px 20px', textAlign:'center' }}>
            <div style={{ width:48, height:48, margin:'0 auto 14px', borderRadius:14, background:'hsl(var(--surface-2))', display:'flex', alignItems:'center', justifyContent:'center', color:'hsl(var(--fg-subtle))' }}><I.filter/></div>
            <div style={{ fontFamily:'var(--font-serif)', fontSize:22, fontWeight:400, color:'hsl(var(--fg))', letterSpacing:'-0.02em', marginBottom:4 }}>No sessions match</div>
            <div style={{ fontSize:13, color:'hsl(var(--fg-muted))' }}>Try clearing filters or broadening your date range.</div>
          </div>
        ) : (
          <div style={{ overflowX:'auto' }}>
            <table style={{ width:'100%', borderCollapse:'collapse', fontSize:13 }}>
              <thead>
                <tr style={{ background:'hsl(var(--surface-2))', fontSize:11, color:'hsl(var(--fg-muted))', textTransform:'uppercase', letterSpacing:'0.05em' }}>
                  {[
                    ['borrower','Borrower'],
                    ['type','Document type'],
                    ['docs','Files'],
                    ['created','Created'],
                    ['status','Status'],
                  ].map(([k,l]) => (
                    <th key={k} style={{ textAlign:'left', padding:'10px 16px', fontWeight:600, cursor:'pointer', userSelect:'none' }} onClick={() => setSort(k)}>{l}{sortGlyph(k)}</th>
                  ))}
                  <th style={{ padding:'10px 16px' }}></th>
                </tr>
              </thead>
              <tbody>
                {sorted.map((s, i) => (
                  <tr key={s.id} className="cx-row" style={{ borderTop:'1px solid hsl(var(--border))', cursor:'pointer' }} onClick={() => onOpenSession && onOpenSession(s)}>
                    <td style={{ padding:'12px 16px' }}>
                      <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                        <Avatar name={s.borrower} size={28}/>
                        <div>
                          <div style={{ fontWeight:600, color:'hsl(var(--fg))' }}>{s.borrower}</div>
                          <div style={{ fontSize:11, color:'hsl(var(--fg-subtle))', fontFamily:'var(--font-mono)' }}>{s.id}</div>
                        </div>
                      </div>
                    </td>
                    <td style={{ padding:'12px 16px', color:'hsl(var(--fg))' }}>{s.type}</td>
                    <td style={{ padding:'12px 16px', color:'hsl(var(--fg))' }}>{s.docs}</td>
                    <td style={{ padding:'12px 16px', color:'hsl(var(--fg-muted))', whiteSpace:'nowrap' }}>{s.created}</td>
                    <td style={{ padding:'12px 16px' }}>
                      {s.status === 'processing' && <Badge tone="warning" size="sm"><Spinner size={10}/>Processing</Badge>}
                      {s.status === 'completed'  && <Badge tone="success" size="sm"><I.check/>Completed</Badge>}
                      {s.status === 'failed'     && <Badge tone="danger" size="sm"><I.alert/>Failed</Badge>}
                    </td>
                    <td style={{ padding:'12px 16px', textAlign:'right' }}><I.chevronRight style={{ color:'hsl(var(--fg-subtle))' }}/></td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </Card>
    </div>
  );
}

// ============================================================
//  Insights page
// ============================================================
function InsightsPage({ borrowers }) {
  const [range, setRange] = React.useState('30d');
  const allSessions = (borrowers || []).flatMap(b => b.sessions || []);

  const docMix = React.useMemo(() => {
    const m = {};
    allSessions.forEach(s => { m[s.type] = (m[s.type] || 0) + 1; });
    return Object.entries(m).map(([k, v]) => ({ name: k, count: v }));
  }, [allSessions]);
  const total = docMix.reduce((s, x) => s + x.count, 0) || 1;

  const colors = ['hsl(var(--primary))', 'hsl(var(--accent))', 'hsl(var(--gold))', 'hsl(var(--border-strong))'];

  // NEEDS BACKEND: replace with real timeseries
  const approvalTrend = [62, 68, 65, 72, 70, 76, 74, 78, 82, 80, 84, 82, 86, 84];
  const volumeTrend   = [3, 5, 4, 6, 8, 7, 9, 11, 10, 13, 12, 14, 16, 15];

  return (
    <div style={{ padding:'24px 32px 48px', maxWidth:1320, margin:'0 auto' }}>
      <div style={{ display:'flex', alignItems:'center', gap:12, marginBottom:20, flexWrap:'wrap' }}>
        <div style={{ flex:1 }}>
          <div style={{ fontFamily:'var(--font-serif)', fontSize:32, fontWeight:400, color:'hsl(var(--fg))', letterSpacing:'-0.025em' }}>Portfolio <span style={{ fontStyle:'italic' }}>insights</span></div>
          <div style={{ fontSize:13, color:'hsl(var(--fg-muted))', marginTop:4 }}>Cross-session analytics across {(borrowers || []).length} borrowers · derived live</div>
        </div>
        <div style={{ display:'inline-flex', height:36, borderRadius:10, border:'1px solid hsl(var(--border))', overflow:'hidden', background:'hsl(var(--surface))' }}>
          {[['7d','7d'],['30d','30d'],['90d','90d'],['ytd','YTD']].map(([k,l],i) => {
            const active = range === k;
            return (
              <button key={k} onClick={() => setRange(k)}
                style={{ padding:'0 14px', border:'none', background: active ? 'hsl(var(--accent-soft))' : 'transparent', color: active ? 'hsl(var(--primary))' : 'hsl(var(--fg-muted))', fontFamily:'inherit', fontSize:13, fontWeight:500, cursor:'pointer', borderLeft: i === 0 ? 'none' : '1px solid hsl(var(--border))' }}>{l}</button>
            );
          })}
        </div>
      </div>

      {/* KPI row */}
      <div style={{ display:'grid', gridTemplateColumns:'repeat(4,1fr)', gap:14, marginBottom:18 }}>
        <StatTile label="Volume" value={allSessions.length} delta="+18% vs prior" icon={<I.layers/>} accent="brand" spark={volumeTrend}/>
        <StatTile label="Approval rate" value="78%" delta="+4pp" icon={<I.zap/>} accent="success" spark={approvalTrend}/>
        <StatTile label="Avg cycle time" value="4.2m" delta="−18%" deltaTone="success" icon={<I.clock/>} accent="info" spark={[5.2,4.8,4.5,4.4,4.0,3.9,4.2]}/>
        <StatTile label="Failure rate" value="3.2%" delta="−1.1pp" deltaTone="success" icon={<I.alert/>} accent="warning" spark={[5.2,4.8,4.4,4.0,3.6,3.4,3.2]}/>
      </div>

      {/* Big trend */}
      <Card style={{ marginBottom:14 }}>
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:12 }}>
          <div style={{ fontSize:15, fontWeight:600, color:'hsl(var(--fg))' }}>Approval rate · 14 days</div>
          <div style={{ display:'flex', gap:14, fontSize:12, color:'hsl(var(--fg-muted))' }}>
            <div style={{ display:'flex', alignItems:'center', gap:6 }}><span style={{ width:10, height:2, background:'hsl(var(--primary))' }}/> Approval rate</div>
            <div style={{ display:'flex', alignItems:'center', gap:6 }}><span style={{ width:10, height:2, background:'hsl(var(--gold))' }}/> Volume</div>
          </div>
        </div>
        <Line data={approvalTrend} w={1180} h={260}/>
      </Card>

      <div style={{ display:'grid', gridTemplateColumns:'1fr 1.3fr', gap:14 }}>
        {/* Doc mix */}
        <Card>
          <div style={{ fontSize:15, fontWeight:600, color:'hsl(var(--fg))', marginBottom:14 }}>Document mix</div>
          {total > 0 ? (
            <div style={{ display:'flex', alignItems:'center', gap:18 }}>
              <Donut value={Math.round((docMix[0]?.count || 0) / total * 100)} size={120} stroke={14} label={docMix[0]?.name || ''}/>
              <div style={{ flex:1, display:'flex', flexDirection:'column', gap:10 }}>
                {docMix.map((d, i) => (
                  <div key={d.name} style={{ display:'flex', alignItems:'center', gap:10, fontSize:13 }}>
                    <span style={{ width:10, height:10, borderRadius:3, background:colors[i % colors.length] }}/>
                    <div style={{ flex:1, color:'hsl(var(--fg))' }}>{d.name}</div>
                    <div style={{ color:'hsl(var(--fg-muted))', fontVariantNumeric:'tabular-nums' }}>{d.count}</div>
                    <div style={{ color:'hsl(var(--fg))', fontWeight:600, fontVariantNumeric:'tabular-nums', minWidth:40, textAlign:'right' }}>{Math.round(d.count / total * 100)}%</div>
                  </div>
                ))}
              </div>
            </div>
          ) : (
            <div style={{ padding:'24px 0', textAlign:'center', color:'hsl(var(--fg-muted))', fontSize:13 }}>No sessions yet — start one to see the mix.</div>
          )}
        </Card>

        {/* Top counterparties — NEEDS BACKEND for real cross-session aggregation */}
        <Card>
          <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:14 }}>
            <div style={{ fontSize:15, fontWeight:600, color:'hsl(var(--fg))' }}>Top counterparties (across portfolio)</div>
            <Badge tone="neutral" size="sm">Sample · backend pending</Badge>
          </div>
          <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
            {[
              { name:'PT BUMI RESOURCES', dir:'in',  vol:'Rp 4.8B', cnt:42 },
              { name:'PT KARYA MANUFAKTUR', dir:'out', vol:'Rp 1.9B', cnt:28 },
              { name:'CV KARYA JAYA',      dir:'out', vol:'Rp 1.3B', cnt:24 },
              { name:'PT SINAR MAS AGRO',  dir:'in',  vol:'Rp 962M', cnt:18 },
              { name:'BCA CREDIT CARD',    dir:'out', vol:'Rp 754M', cnt:32 },
            ].map((r, i) => (
              <div key={i} style={{ display:'flex', alignItems:'center', gap:10, padding:'10px 0', borderTop: i === 0 ? 'none' : '1px solid hsl(var(--border))' }}>
                <Avatar name={r.name} size={28} color={r.dir === 'in' ? 'hsl(var(--success))' : 'hsl(var(--primary))'}/>
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ fontSize:13, fontWeight:600, color:'hsl(var(--fg))', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{r.name}</div>
                  <div style={{ fontSize:11, color:'hsl(var(--fg-muted))' }}>{r.cnt} transactions</div>
                </div>
                <div style={{ fontSize:13, fontWeight:600, color: r.dir === 'in' ? 'hsl(var(--success-fg))' : 'hsl(var(--fg))', fontVariantNumeric:'tabular-nums' }}>{r.dir === 'in' ? '+' : '−'}{r.vol}</div>
              </div>
            ))}
          </div>
        </Card>
      </div>
    </div>
  );
}

// ============================================================
//  Settings page
// ============================================================
function SettingsPage({ user }) {
  const [section, setSection] = React.useState('profile');
  const [keyVisible, setKeyVisible] = React.useState(false);
  const apiKey = (typeof sessionStorage !== 'undefined' && sessionStorage.getItem('crednx_auth_key')) || 'crednx_pk_••••••••••••••';
  const masked = apiKey.length > 10 ? apiKey.slice(0, 8) + '•'.repeat(Math.max(8, apiKey.length - 12)) + apiKey.slice(-4) : '••••••••';
  const [copied, setCopied] = React.useState(false);

  const sections = [
    { id:'profile',  label:'Profile',  icon:<I.user/> },
    { id:'apikeys',  label:'API keys', icon:<I.key/> },
    { id:'webhooks', label:'Webhooks', icon:<I.webhook/> },
    { id:'theme',    label:'Theme',    icon:<I.sparkles/> },
  ];

  function copy() {
    try { navigator.clipboard.writeText(apiKey); setCopied(true); setTimeout(() => setCopied(false), 1800); } catch {}
  }

  return (
    <div style={{ padding:'24px 32px 48px', maxWidth:1100, margin:'0 auto' }}>
      <div style={{ fontFamily:'var(--font-serif)', fontSize:32, fontWeight:400, color:'hsl(var(--fg))', letterSpacing:'-0.025em', marginBottom:4 }}>Settings</div>
      <div style={{ fontSize:13, color:'hsl(var(--fg-muted))', marginBottom:24 }}>Manage your account, API access and preferences.</div>

      <div style={{ display:'grid', gridTemplateColumns:'220px 1fr', gap:18 }}>
        <nav style={{ display:'flex', flexDirection:'column', gap:4, position:'sticky', top:20, alignSelf:'start' }}>
          {sections.map(s => {
            const active = section === s.id;
            return (
              <button key={s.id} onClick={() => setSection(s.id)}
                style={{
                  display:'flex', alignItems:'center', gap:10, padding:'10px 12px',
                  border:'none', borderRadius:10, cursor:'pointer', fontFamily:'inherit',
                  fontSize:14, fontWeight:500, textAlign:'left',
                  color: active ? 'hsl(var(--primary))' : 'hsl(var(--fg))',
                  background: active ? 'hsl(var(--accent-soft))' : 'transparent',
                }}
                onMouseEnter={e => { if (!active) e.currentTarget.style.background = 'hsl(var(--surface-2))'; }}
                onMouseLeave={e => { if (!active) e.currentTarget.style.background = 'transparent'; }}>
                <span style={{ color: active ? 'hsl(var(--primary))' : 'hsl(var(--fg-muted))', display:'flex' }}>{s.icon}</span>
                {s.label}
              </button>
            );
          })}
        </nav>

        <div>
          {section === 'profile' && (
            <Card>
              <div style={{ fontSize:16, fontWeight:600, color:'hsl(var(--fg))', marginBottom:18 }}>Profile</div>
              <div style={{ display:'flex', alignItems:'center', gap:14, marginBottom:20, padding:14, background:'hsl(var(--accent-soft))', borderRadius:14, border:'1px solid hsl(var(--accent) / 0.25)' }}>
                <Avatar name={user?.name || ''} size={48}/>
                <div style={{ flex:1 }}>
                  <div style={{ fontSize:15, fontWeight:600, color:'hsl(var(--fg))' }}>{user?.name || 'Unknown'}</div>
                  <div style={{ fontSize:12, color:'hsl(var(--fg-muted))' }}>{user?.email}</div>
                </div>
                <Badge tone="brand">{user?.role || 'Member'}</Badge>
              </div>
              <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:14 }}>
                <Input label="Display name" value={user?.name || ''} onChange={()=>{}}/>
                <Input label="Work email" value={user?.email || ''} onChange={()=>{}}/>
                <Input label="Organisation" value={user?.organisation_name || 'CredNX'} onChange={()=>{}}/>
                <Input label="Time zone" value="Asia/Jakarta · GMT+7" onChange={()=>{}}/>
              </div>
              <div style={{ display:'flex', gap:10, justifyContent:'flex-end', marginTop:18 }}>
                <Button variant="secondary">Cancel</Button>
                <Button variant="primary">Save changes</Button>
              </div>
            </Card>
          )}

          {section === 'apikeys' && (
            <Card>
              <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:14 }}>
                <div style={{ fontSize:16, fontWeight:600, color:'hsl(var(--fg))' }}>API keys</div>
                <Button variant="primary" size="sm" icon={<I.plus/>}>New key</Button>
              </div>
              <div style={{ padding:14, border:'1px solid hsl(var(--border))', borderRadius:12, marginBottom:14 }}>
                <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:8 }}>
                  <I.key style={{ color:'hsl(var(--accent))' }}/>
                  <div style={{ fontSize:13, fontWeight:600, color:'hsl(var(--fg))' }}>Default key</div>
                  <Badge tone="success" size="sm">Active</Badge>
                </div>
                <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                  <code style={{ flex:1, padding:'8px 12px', background:'hsl(var(--code-bg))', color:'hsl(var(--code-fg))', borderRadius:8, fontSize:12, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{keyVisible ? apiKey : masked}</code>
                  <Button variant="secondary" size="sm" onClick={() => setKeyVisible(v => !v)}>{keyVisible ? 'Hide' : 'Reveal'}</Button>
                  <Button variant="secondary" size="sm" onClick={copy}>{copied ? 'Copied' : 'Copy'}</Button>
                </div>
                <div style={{ fontSize:11, color:'hsl(var(--fg-subtle))', marginTop:8 }}>Created May 2024 · Last used 2 hours ago</div>
              </div>
              <div style={{ padding:14, background:'hsl(var(--warning-bg))', border:'1px solid hsl(var(--warning) / 0.3)', borderRadius:12, fontSize:12, color:'hsl(var(--warning-fg))', display:'flex', gap:10 }}>
                <I.alert style={{ flexShrink:0, marginTop:1 }}/>
                <div>Treat your API keys like passwords. Anyone with this key can access your CredNX workspace.</div>
              </div>
            </Card>
          )}

          {section === 'webhooks' && (
            <Card>
              <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:14 }}>
                <div style={{ fontSize:16, fontWeight:600, color:'hsl(var(--fg))' }}>Webhooks</div>
                <Button variant="primary" size="sm" icon={<I.plus/>}>Add endpoint</Button>
              </div>
              <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
                {[
                  { url:'https://crm.bankofsoutheast.id/webhooks/crednx', events:['session.completed','decision.approved'], active:true },
                  { url:'https://ops.bankofsoutheast.id/alerts',          events:['session.failed'],                      active:true },
                ].map((w, i) => (
                  <div key={i} style={{ display:'flex', alignItems:'center', gap:14, padding:14, border:'1px solid hsl(var(--border))', borderRadius:12 }}>
                    <div style={{ width:36, height:36, borderRadius:10, background:'hsl(var(--accent-soft))', color:'hsl(var(--primary))', display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}><I.webhook/></div>
                    <div style={{ flex:1, minWidth:0 }}>
                      <code style={{ fontSize:12, color:'hsl(var(--fg))', fontWeight:500, padding:0, background:'transparent', display:'block', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{w.url}</code>
                      <div style={{ display:'flex', gap:6, marginTop:6 }}>
                        {w.events.map(e => <Badge key={e} tone="neutral" size="sm">{e}</Badge>)}
                      </div>
                    </div>
                    <Badge tone={w.active ? 'success' : 'neutral'} size="sm">{w.active ? 'Active' : 'Paused'}</Badge>
                    <button style={{ width:30, height:30, border:'none', background:'transparent', borderRadius:8, cursor:'pointer', color:'hsl(var(--fg-subtle))', display:'inline-flex', alignItems:'center', justifyContent:'center' }}><I.moreH/></button>
                  </div>
                ))}
              </div>
              <div style={{ marginTop:14, fontSize:12, color:'hsl(var(--fg-subtle))' }}>Receive HTTP POSTs when sessions complete, fail, or get a decision. <a href="#" className="cx-link">View payload schema →</a></div>
            </Card>
          )}

          {section === 'theme' && (
            <Card>
              <div style={{ fontSize:16, fontWeight:600, color:'hsl(var(--fg))', marginBottom:6 }}>Appearance</div>
              <div style={{ fontSize:13, color:'hsl(var(--fg-muted))', marginBottom:18 }}>Switch between light and dark — your choice is remembered on this device.</div>
              <div style={{ display:'flex', gap:14 }}>
                {[
                  { id:'light', label:'Light', preview:'linear-gradient(135deg, hsl(42 30% 96%), hsl(42 22% 93%))' },
                  { id:'dark',  label:'Dark',  preview:'linear-gradient(135deg, hsl(155 42% 5%), hsl(155 36% 8%))' },
                ].map(t => {
                  const current = (typeof document !== 'undefined' && document.documentElement.getAttribute('data-theme')) || 'light';
                  const active = current === t.id;
                  return (
                    <button key={t.id} onClick={() => {
                      document.documentElement.classList.add('theme-transition');
                      document.documentElement.setAttribute('data-theme', t.id);
                      try { localStorage.setItem('crednx_theme', t.id); } catch {}
                      setTimeout(() => document.documentElement.classList.remove('theme-transition'), 360);
                    }} style={{
                      flex:1, padding:14, border: active ? '2px solid hsl(var(--primary))' : '1.5px solid hsl(var(--border))',
                      borderRadius:14, background:'hsl(var(--surface))', cursor:'pointer', fontFamily:'inherit', textAlign:'left'
                    }}>
                      <div style={{ height:88, borderRadius:10, background:t.preview, marginBottom:10, border:'1px solid hsl(var(--border))' }}/>
                      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between' }}>
                        <span style={{ fontSize:14, fontWeight:600, color:'hsl(var(--fg))' }}>{t.label}</span>
                        {active && <Badge tone="brand" size="sm">Current</Badge>}
                      </div>
                    </button>
                  );
                })}
              </div>
            </Card>
          )}
        </div>
      </div>
    </div>
  );
}

// ============================================================
//  Notifications drawer  (NEEDS BACKEND for real notifications)
// ============================================================
const NOTIF_FALLBACK = [
  { id:1, kind:'session_completed', title:'Bank statement analysis completed', body:'BRW-2847 · 3 documents processed in 4.2 min', when:'2 min ago', unread:true,  goto:{ page:'sessions' } },
  { id:2, kind:'decision_approved', title:'Approval issued',                   body:'BRW-2931 · Rp 5.2B at 11.5% p.a.',           when:'42 min ago', unread:true,  goto:{ page:'sessions' } },
  { id:3, kind:'session_failed',    title:'Analysis failed',                   body:'BRW-3104 · Bank statement file unreadable',  when:'1 hour ago', unread:false, goto:{ page:'sessions' } },
  { id:4, kind:'team_invited',      title:'rendra.p@bankx.id joined',          body:'Invited by Fina Lestari · Viewer',           when:'3 hours ago', unread:false, goto:{ page:'team' } },
  { id:5, kind:'system',            title:'Weekly report is ready',            body:'78% approval rate (+5pp WoW) · 14 sessions', when:'Yesterday', unread:false, goto:{ page:'insights' } },
];

function NotificationsDrawer({ open, onClose, onNavigate, notifications, setNotifications }) {
  const list = notifications;
  const unread = list.filter(n => n.unread).length;
  const markAllRead = () => setNotifications(list.map(n => ({ ...n, unread:false })));

  return (
    <>
      {/* Backdrop */}
      <div onClick={onClose} style={{
        position:'fixed', inset:0, background:'hsl(var(--surface-deep) / 0.4)', backdropFilter:'blur(2px)',
        opacity: open ? 1 : 0, pointerEvents: open ? 'auto' : 'none',
        transition:'opacity 240ms', zIndex:80,
      }}/>
      {/* Drawer */}
      <aside style={{
        position:'fixed', top:0, right:0, bottom:0, width:380,
        background:'hsl(var(--surface))', borderLeft:'1px solid hsl(var(--border))',
        boxShadow: open ? 'var(--shadow-xl)' : 'none',
        transform: open ? 'translateX(0)' : 'translateX(100%)',
        transition:'transform 280ms cubic-bezier(0.22, 1, 0.36, 1)',
        zIndex:90, display:'flex', flexDirection:'column',
      }}>
        <div style={{ height:72, padding:'0 18px', borderBottom:'1px solid hsl(var(--border))', display:'flex', alignItems:'center', gap:10, flexShrink:0 }}>
          <I.bell style={{ color:'hsl(var(--accent))' }}/>
          <div style={{ flex:1 }}>
            <div style={{ fontFamily:'var(--font-serif)', fontSize:20, fontWeight:400, color:'hsl(var(--fg))', letterSpacing:'-0.02em' }}>Notifications</div>
            <div style={{ fontSize:12, color:'hsl(var(--fg-muted))' }}>{unread > 0 ? `${unread} unread` : 'All caught up'}</div>
          </div>
          {unread > 0 && <button onClick={markAllRead} style={{ border:'none', background:'transparent', cursor:'pointer', fontSize:12, color:'hsl(var(--accent))', fontWeight:600, fontFamily:'inherit' }}>Mark all read</button>}
          <button onClick={onClose} aria-label="Close" style={{ width:32, height:32, border:'none', background:'transparent', cursor:'pointer', color:'hsl(var(--fg-muted))', borderRadius:8, display:'inline-flex', alignItems:'center', justifyContent:'center' }}><I.x/></button>
        </div>
        <div style={{ flex:1, overflow:'auto' }}>
          {list.length === 0 ? (
            <div style={{ padding:40, textAlign:'center', color:'hsl(var(--fg-muted))', fontSize:13 }}>You have no notifications.</div>
          ) : list.map((n) => {
            const m = KIND_META[n.kind] || { tone:'neutral', icon:<I.bell/> };
            const bg     = `hsl(var(--${m.tone}-bg))`;
            const fg     = `hsl(var(--${m.tone}-fg))`;
            const border = `hsl(var(--${m.tone}) / 0.3)`;
            return (
              <button key={n.id} onClick={() => {
                  setNotifications(list.map(x => x.id === n.id ? { ...x, unread:false } : x));
                  if (n.goto) onNavigate(n.goto.page);
                  onClose();
                }}
                style={{
                  display:'flex', gap:12, padding:'14px 18px', width:'100%',
                  border:'none', borderTop:'1px solid hsl(var(--border))',
                  background: n.unread ? 'hsl(var(--accent-soft) / 0.4)' : 'transparent',
                  cursor:'pointer', textAlign:'left', fontFamily:'inherit', position:'relative',
                  transition:'background 150ms',
                }}
                onMouseEnter={e => { e.currentTarget.style.background = n.unread ? 'hsl(var(--accent-soft) / 0.7)' : 'hsl(var(--surface-2))'; }}
                onMouseLeave={e => { e.currentTarget.style.background = n.unread ? 'hsl(var(--accent-soft) / 0.4)' : 'transparent'; }}>
                {n.unread && <span style={{ position:'absolute', left:6, top:'50%', width:6, height:6, borderRadius:3, background:'hsl(var(--accent))', transform:'translateY(-50%)', boxShadow:'0 0 8px hsl(var(--accent))' }}/>}
                <div style={{ width:34, height:34, borderRadius:10, background:bg, color:fg, border:`1px solid ${border}`, display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>{m.icon}</div>
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ fontSize:13, fontWeight:600, color:'hsl(var(--fg))', marginBottom:2 }}>{n.title}</div>
                  <div style={{ fontSize:12, color:'hsl(var(--fg-muted))', lineHeight:1.45 }}>{n.body}</div>
                  <div style={{ fontSize:11, color:'hsl(var(--fg-subtle))', marginTop:4 }}>{n.when}</div>
                </div>
              </button>
            );
          })}
        </div>
      </aside>
    </>
  );
}

function NotificationBell({ unread, onClick }) {
  return (
    <button onClick={onClick} aria-label="Notifications"
      style={{
        position:'relative', width:36, height:36, borderRadius:18,
        border:'1px solid hsl(var(--border))', background:'hsl(var(--surface))',
        cursor:'pointer', color:'hsl(var(--fg))',
        display:'inline-flex', alignItems:'center', justifyContent:'center',
        transition:'background 150ms, border-color 150ms',
      }}
      onMouseEnter={e => e.currentTarget.style.background = 'hsl(var(--surface-2))'}
      onMouseLeave={e => e.currentTarget.style.background = 'hsl(var(--surface))'}>
      <I.bell/>
      {unread > 0 && (
        <span style={{
          position:'absolute', top:6, right:6, minWidth:14, height:14,
          padding:'0 4px', borderRadius:7, background:'hsl(var(--accent))',
          color:'hsl(var(--accent-fg))', fontSize:9, fontWeight:700,
          display:'flex', alignItems:'center', justifyContent:'center', lineHeight:1,
          border:'2px solid hsl(var(--surface))',
        }}>{unread > 9 ? '9+' : unread}</span>
      )}
    </button>
  );
}

// ============================================================
//  Command palette  (⌘K / Ctrl+K)
// ============================================================
function CommandPalette({ open, onClose, borrowers, onNavigate, onLogout }) {
  const [query, setQuery] = React.useState('');
  const [activeIdx, setActiveIdx] = React.useState(0);
  const inputRef = React.useRef(null);

  React.useEffect(() => {
    if (open) { setQuery(''); setActiveIdx(0); setTimeout(() => inputRef.current?.focus(), 30); }
  }, [open]);

  const allSessions = React.useMemo(() => (borrowers || []).flatMap(b => b.sessions || []), [borrowers]);

  const groups = React.useMemo(() => {
    const q = query.trim().toLowerCase();
    const matches = (s) => !q || s.toLowerCase().includes(q);

    const pages = [
      { kind:'page', label:'Home',        icon:<I.home/>,      action:() => onNavigate('home'),       hint:'Go' },
      { kind:'page', label:'Underwrite',  icon:<I.upload/>,    action:() => onNavigate('underwrite'), hint:'Go' },
      { kind:'page', label:'Sessions',    icon:<I.layers/>,    action:() => onNavigate('sessions'),   hint:'Go' },
      { kind:'page', label:'Borrowers',   icon:<I.users/>,     action:() => onNavigate('borrowers'),  hint:'Go' },
      { kind:'page', label:'Insights',    icon:<I.chart/>,     action:() => onNavigate('insights'),   hint:'Go' },
      { kind:'page', label:'Settings',    icon:<I.settings/>,  action:() => onNavigate('settings'),   hint:'Go' },
    ].filter(p => matches(p.label));

    const actions = [
      { kind:'action', label:'New session',          icon:<I.upload/>,  action:() => onNavigate('underwrite'),                 hint:'Action' },
      { kind:'action', label:'Toggle dark mode',     icon:<I.moon/>,    action:() => {
          const cur = document.documentElement.getAttribute('data-theme') || 'light';
          const next = cur === 'dark' ? 'light' : 'dark';
          document.documentElement.classList.add('theme-transition');
          document.documentElement.setAttribute('data-theme', next);
          try { localStorage.setItem('crednx_theme', next); } catch {}
          setTimeout(() => document.documentElement.classList.remove('theme-transition'), 360);
        }, hint:'Action' },
      { kind:'action', label:'Log out',              icon:<I.logout/>,  action:() => onLogout && onLogout(), hint:'Action' },
    ].filter(a => matches(a.label));

    const borrowerHits = (borrowers || []).filter(b => matches(b.customer_id))
      .slice(0, 8)
      .map(b => ({ kind:'borrower', label:b.customer_id, icon:<Avatar name={b.customer_id} size={22}/>, hint:`${b.total_sessions || 0} sessions`, action:() => onNavigate('borrowers') }));

    const sessionHits = q
      ? allSessions.filter(s => matches(s.id) || matches(s.borrower) || matches(s.type)).slice(0, 8)
        .map(s => ({ kind:'session', label:s.id, sub:`${s.borrower} · ${s.type}`, icon:<I.layers/>, hint:s.status, action:() => onNavigate('sessions') }))
      : [];

    const out = [];
    if (pages.length)         out.push({ title:'Pages',     items:pages });
    if (actions.length)       out.push({ title:'Actions',   items:actions });
    if (borrowerHits.length)  out.push({ title:'Borrowers', items:borrowerHits });
    if (sessionHits.length)   out.push({ title:'Sessions',  items:sessionHits });
    return out;
  }, [query, borrowers, allSessions, onNavigate, onLogout]);

  const flatItems = React.useMemo(() => groups.flatMap(g => g.items), [groups]);

  React.useEffect(() => {
    if (!open) return;
    const handler = (e) => {
      if (e.key === 'ArrowDown') { e.preventDefault(); setActiveIdx(i => Math.min(flatItems.length - 1, i + 1)); }
      else if (e.key === 'ArrowUp') { e.preventDefault(); setActiveIdx(i => Math.max(0, i - 1)); }
      else if (e.key === 'Enter') { e.preventDefault(); const it = flatItems[activeIdx]; if (it) { it.action(); onClose(); } }
    };
    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  }, [open, flatItems, activeIdx, onClose]);

  if (!open) return null;

  let runIdx = -1;
  return (
    <>
      <div onClick={onClose} className="cx-fadein" style={{
        position:'fixed', inset:0, background:'hsl(var(--surface-deep) / 0.55)', backdropFilter:'blur(8px)',
        zIndex:200, display:'flex', alignItems:'flex-start', justifyContent:'center', paddingTop:'10vh', paddingLeft:16, paddingRight:16,
      }}>
        <div onClick={e => e.stopPropagation()} className="cx-fadein"
          style={{
            width:'100%', maxWidth:600, background:'hsl(var(--surface))',
            border:'1px solid hsl(var(--border))', borderRadius:18, boxShadow:'var(--shadow-xl)',
            overflow:'hidden',
          }}>
          <div style={{ display:'flex', alignItems:'center', gap:10, padding:'14px 16px', borderBottom:'1px solid hsl(var(--border))' }}>
            <I.search style={{ color:'hsl(var(--fg-muted))' }}/>
            <input ref={inputRef} value={query} onChange={e => { setQuery(e.target.value); setActiveIdx(0); }}
              placeholder="Search borrowers, sessions, pages…"
              style={{ flex:1, border:'none', outline:'none', fontFamily:'inherit', fontSize:15, color:'hsl(var(--fg))', background:'transparent' }}/>
            <kbd style={{ padding:'2px 6px', borderRadius:4, background:'hsl(var(--surface-2))', fontFamily:'var(--font-mono)', fontSize:10, color:'hsl(var(--fg-muted))', border:'1px solid hsl(var(--border))' }}>Esc</kbd>
          </div>
          <div style={{ maxHeight:'60vh', overflow:'auto', padding:'8px 0' }}>
            {flatItems.length === 0 ? (
              <div style={{ padding:'30px 18px', textAlign:'center', color:'hsl(var(--fg-muted))', fontSize:13 }}>
                No matches for "<b style={{ color:'hsl(var(--fg))' }}>{query}</b>"
              </div>
            ) : groups.map(g => (
              <div key={g.title} style={{ marginBottom:6 }}>
                <div style={{ fontSize:10, color:'hsl(var(--fg-subtle))', textTransform:'uppercase', letterSpacing:'0.08em', padding:'6px 16px 4px', fontWeight:700 }}>{g.title}</div>
                {g.items.map(it => {
                  runIdx++;
                  const active = runIdx === activeIdx;
                  return (
                    <button key={`${g.title}-${it.label}-${runIdx}`}
                      onMouseEnter={() => setActiveIdx(runIdx)}
                      onClick={() => { it.action(); onClose(); }}
                      style={{
                        width:'100%', display:'flex', alignItems:'center', gap:12, padding:'10px 16px',
                        border:'none', cursor:'pointer', fontFamily:'inherit', fontSize:14, textAlign:'left',
                        color:'hsl(var(--fg))', background: active ? 'hsl(var(--accent-soft))' : 'transparent',
                        borderLeft: active ? '3px solid hsl(var(--accent))' : '3px solid transparent',
                      }}>
                      <span style={{ width:22, display:'inline-flex', justifyContent:'center', color: active ? 'hsl(var(--primary))' : 'hsl(var(--fg-muted))' }}>{it.icon}</span>
                      <span style={{ flex:1, fontWeight: active ? 600 : 500 }}>
                        {it.label}
                        {it.sub && <span style={{ display:'block', fontSize:11, color:'hsl(var(--fg-muted))', fontWeight:400, marginTop:1 }}>{it.sub}</span>}
                      </span>
                      <span style={{ fontSize:11, color:'hsl(var(--fg-subtle))', textTransform:'capitalize' }}>{it.hint}</span>
                    </button>
                  );
                })}
              </div>
            ))}
          </div>
          <div style={{ padding:'10px 16px', borderTop:'1px solid hsl(var(--border))', background:'hsl(var(--surface-2))', display:'flex', alignItems:'center', gap:14, fontSize:11, color:'hsl(var(--fg-muted))' }}>
            <span><kbd style={kbdStyle}>↑</kbd><kbd style={kbdStyle}>↓</kbd> Navigate</span>
            <span><kbd style={kbdStyle}>↵</kbd> Open</span>
            <span style={{ flex:1 }}/>
            <span><I.command style={{ verticalAlign:'middle' }}/> CredNX</span>
          </div>
        </div>
      </div>
    </>
  );
}
const kbdStyle = { padding:'2px 6px', borderRadius:4, background:'hsl(var(--surface))', fontFamily:'var(--font-mono)', fontSize:10, color:'hsl(var(--fg-muted))', border:'1px solid hsl(var(--border))', marginRight:4 };

Object.assign(window, {
  HomePage, SessionsTable, InsightsPage, SettingsPage,
  NotificationsDrawer, NotificationBell, NOTIF_FALLBACK,
  CommandPalette, ActivityFeed, StatTile, Sparkline,
  greeting, todayLabel,
});
