// Tablet screens — iPad-optimized NTP, Tabs, Chat (master-detail), Mesh

// ───── NTP — generous, centered, with shortcut grid + briefing rail ─────
function TScreenNTP({ greeting = 'on', name = '', onOpenSearch, landscape = true }) {
  const shortcuts = [
    { t: 'Linear', u: 'linear.app', bg: '#5E6AD2', l: 'L' },
    { t: 'GitHub', u: 'github.com', bg: '#24292F', l: 'G' },
    { t: 'Figma', u: 'figma.com', bg: '#000', l: 'F' },
    { t: 'Notion', u: 'notion.so', bg: '#FFF', c: '#000', l: 'N' },
    { t: 'Gmail', u: 'gmail.com', bg: '#EA4335', l: 'M' },
    { t: 'Slack', u: 'slack.com', bg: '#4A154B', l: 'S' },
    { t: 'YouTube', u: 'youtube.com', bg: '#FF0000', l: 'Y' },
    { t: 'Ajna', u: 'ajna.app', bg: 'linear-gradient(135deg,#6EE7B7,#60A5FA)', c: '#0B0C0F', l: 'A' },
  ];

  return (
    <div style={{
      flex: 1, minHeight: 0, overflow: 'auto',
      background: `radial-gradient(ellipse at 50% 20%, #15171c 0%, ${M_BG} 60%)`,
      display: 'flex', flexDirection: 'column',
    }}>
      <div style={{
        maxWidth: 900, margin: '0 auto', padding: landscape ? '56px 40px 40px' : '64px 28px 40px',
        width: '100%', boxSizing: 'border-box',
      }}>
        {greeting !== 'off' && (
          <div style={{ textAlign: 'center', marginBottom: 32 }}>
            <div style={{
              fontSize: 12, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace',
              letterSpacing: '0.15em', textTransform: 'uppercase',
            }}>Tuesday · April 23</div>
            <div style={{
              fontFamily: "'Instrument Serif', 'Geist', serif",
              fontSize: landscape ? 64 : 56, lineHeight: 1, letterSpacing: '-0.02em',
              marginTop: 10, color: M_FG, fontStyle: 'italic', fontWeight: 400,
            }}>
              Good afternoon{name ? <>, <span style={{
                background: 'linear-gradient(135deg,' + M_ACCENT + ',' + M_ACCENT_B + ')',
                WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', backgroundClip: 'text',
              }}>{name}</span></> : '.'}
            </div>
          </div>
        )}

        <div onClick={onOpenSearch} style={{
          display: 'flex', alignItems: 'center', gap: 12,
          padding: '16px 22px', marginBottom: 40,
          background: M_SURFACE, border: '1px solid ' + M_BORDER,
          borderRadius: 18, cursor: 'pointer',
          boxShadow: '0 12px 32px rgba(0,0,0,0.25)',
        }}>
          <span style={{ color: M_FG_DIM }}>{MIc.search({ s: 18 })}</span>
          <span style={{ flex: 1, fontSize: 15, color: M_FG_MUTED }}>Search the web, ask AI, or type a URL</span>
          <span style={{ fontSize: 10.5, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace', padding: '3px 8px', border: '1px solid ' + M_BORDER_SOFT, borderRadius: 5 }}>⌘K</span>
          <span style={{ color: M_FG_DIM }}>{MIc.mic({ s: 18 })}</span>
        </div>

        {/* Shortcuts grid */}
        <div style={{
          display: 'grid',
          gridTemplateColumns: landscape ? 'repeat(8, 1fr)' : 'repeat(4, 1fr)',
          gap: landscape ? 16 : 20,
          marginBottom: 44,
        }}>
          {shortcuts.map(s => (
            <a key={s.t} href="#" style={{
              display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 10,
              textDecoration: 'none', color: M_FG_MUTED, padding: '10px 4px',
              borderRadius: 12, transition: 'background 160ms',
            }}
            onMouseEnter={e => e.currentTarget.style.background = 'var(--m-tint)'}
            onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
              <div style={{
                width: 52, height: 52, borderRadius: 14,
                background: s.bg, color: s.c || '#fff',
                display: 'grid', placeItems: 'center',
                fontSize: 22, fontWeight: 700, fontFamily: 'Geist, Inter, sans-serif',
              }}>{s.l}</div>
              <span style={{ fontSize: 12, fontWeight: 500, color: M_FG }}>{s.t}</span>
            </a>
          ))}
        </div>

        {/* Briefing — sticky chips + infinite scroll */}
        <TBriefingFeed landscape={landscape}/>
      </div>
    </div>
  );
}

// ───── Tabs — bigger grid, more meta, with tab-group switcher (regular / private) ─────
function TScreenTabs({ landscape = true, onOpenPrivate }) {
  const [groupId, setGroupId] = React.useState('all');
  const groups = [
    { id: 'all',      label: 'Tabs',         count: 6, kind: 'normal' },
    { id: 'private',  label: 'Private',      count: 3, kind: 'private' },
    { id: 'work',     label: 'Work',         count: 4, kind: 'normal' },
    { id: 'reading',  label: 'Reading list', count: 2, kind: 'normal' },
  ];
  const tabsByGroup = {
    all: [
      { title: 'Linear — Inbox',            fav: 'L', bg: '#5E6AD2',          url: 'linear.app/ajna-inc/inbox',     hint: 'Active · 18m' },
      { title: 'Figma — Ajna iPad explor.', fav: 'F', bg: '#000',             url: 'figma.com/file/ajna-ipad',     hint: 'Edited 2h ago' },
      { title: 'GitHub · ajna-inc/browser', fav: 'G', bg: '#24292F',          url: 'github.com/ajna-inc/browser',  hint: 'PR #284 · 3 reviews' },
      { title: 'Notion · P2P Sync RFC',     fav: 'N', bg: '#FFF', c: '#000',  url: 'notion.so/p2p-sync',           hint: '5 comments' },
      { title: 'HN — News',                 fav: 'Y', bg: '#FF6600',          url: 'news.ycombinator.com',         hint: 'Updated' },
      { title: 'arXiv · DIDComm v2',        fav: 'A', bg: '#B31B1B',          url: 'arxiv.org/abs/2402.…',         hint: 'PDF' },
    ],
    work: [
      { title: 'Linear — Inbox',  fav: 'L', bg: '#5E6AD2', url: 'linear.app/ajna-inc/inbox', hint: 'Active' },
      { title: 'Figma — iPad',    fav: 'F', bg: '#000',    url: 'figma.com/file/ajna-ipad', hint: 'Editing' },
      { title: 'GitHub · #284',   fav: 'G', bg: '#24292F', url: 'github.com/ajna-inc',      hint: '3 reviews' },
      { title: 'Notion · RFC',    fav: 'N', bg: '#FFF', c: '#000', url: 'notion.so/p2p-sync', hint: 'Open' },
    ],
    reading: [
      { title: 'Designing for peer-to-peer browsers', fav: 'M', bg: '#0E0E0E', url: 'engineering.example.com',     hint: '8 min · saved' },
      { title: 'arXiv · DIDComm v2',                  fav: 'A', bg: '#B31B1B', url: 'arxiv.org/abs/2402.…',         hint: 'PDF · saved' },
    ],
  };
  const currentGroup = groups.find(g => g.id === groupId);
  const isPrivate = currentGroup.kind === 'private';

  // If user picks the Private group, hand off to the incognito window
  if (isPrivate) {
    return (
      <div style={{ flex: 1, overflow: 'auto', padding: landscape ? '28px 40px 80px' : '24px 24px 80px' }}>
        <TTabGroupSwitcher groups={groups} groupId={groupId} setGroupId={setGroupId}/>
        <TPrivateTabsHandoff onOpenPrivate={onOpenPrivate}/>
      </div>
    );
  }

  const tabs = tabsByGroup[groupId] || [];
  return (
    <div style={{ flex: 1, overflow: 'auto', padding: landscape ? '28px 40px 80px' : '24px 24px 80px' }}>
      <TTabGroupSwitcher groups={groups} groupId={groupId} setGroupId={setGroupId} onOpenPrivate={onOpenPrivate}/>
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', margin: '20px 0 18px' }}>
        <div style={{ fontSize: 28, fontWeight: 600, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.02em', color: M_FG }}>
          {currentGroup.label} <span style={{ color: M_FG_DIM, fontWeight: 400 }}>· {tabs.length}</span>
        </div>
        <div style={{ display: 'flex', gap: 8 }}>
          <button style={{ ...tIconBtn(false), width: 'auto', padding: '0 12px', height: 32, gap: 6, display: 'inline-flex', fontSize: 12, fontFamily: 'inherit' }}>
            <span style={{ display: 'grid', placeItems: 'center' }}>{MIc.plus({ s: 14 })}</span> New tab
          </button>
          <button style={{ ...tIconBtn(false), width: 'auto', padding: '0 12px', height: 32, fontSize: 12, fontFamily: 'inherit' }}>Close all</button>
        </div>
      </div>
      <div style={{
        display: 'grid',
        gridTemplateColumns: landscape ? 'repeat(3, 1fr)' : 'repeat(2, 1fr)',
        gap: 16,
      }}>
        {tabs.map((t, i) => (
          <div key={i} style={{
            aspectRatio: landscape ? '4/3' : '3/4',
            background: M_SURFACE, border: '1px solid ' + M_BORDER,
            borderRadius: 14, overflow: 'hidden', display: 'flex', flexDirection: 'column',
            cursor: 'pointer',
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '10px 12px', borderBottom: '1px solid ' + M_BORDER_SOFT }}>
              <MTile size={18} bg={t.bg} color={t.c||'#fff'} label={t.fav} radius={4}/>
              <div style={{ fontSize: 11, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', flex: 1 }}>{t.url}</div>
              <span style={{ color: M_FG_DIM, opacity: 0.6 }}>
                <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><path d="M18 6 6 18M6 6l12 12"/></svg>
              </span>
            </div>
            <div style={{ flex: 1, padding: 16, display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
              <div style={{ fontSize: 14, fontWeight: 500, color: M_FG, lineHeight: 1.3 }}>{t.title}</div>
              <div style={{ fontSize: 11, color: M_FG_MUTED, fontFamily: 'JetBrains Mono, monospace' }}>{t.hint}</div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// Tab-group switcher (segmented pill above the grid)
function TTabGroupSwitcher({ groups, groupId, setGroupId, onOpenPrivate }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap',
      padding: 4, background: M_SURFACE, border: '1px solid ' + M_BORDER_SOFT,
      borderRadius: 999, alignSelf: 'flex-start',
    }}>
      {groups.map(g => {
        const active = g.id === groupId;
        const isPriv = g.kind === 'private';
        return (
          <button key={g.id} onClick={() => {
            if (isPriv && onOpenPrivate) onOpenPrivate();
            else setGroupId(g.id);
          }} style={{
            display: 'inline-flex', alignItems: 'center', gap: 6,
            padding: '6px 12px', borderRadius: 999,
            background: active
              ? (isPriv ? 'rgba(167,139,250,0.18)' : 'var(--m-tint)')
              : 'transparent',
            color: active
              ? (isPriv ? '#C4B5FD' : M_FG)
              : (isPriv ? PRIV_ACCENT_2 : M_FG_MUTED),
            border: 0, cursor: 'pointer', fontFamily: 'inherit',
            fontSize: 12, fontWeight: 500, letterSpacing: '-0.005em',
          }}>
            {isPriv && <span style={{ display: 'grid', placeItems: 'center' }}><IcMask s={12}/></span>}
            {g.label}
            <span style={{
              fontSize: 10, fontFamily: 'JetBrains Mono, monospace',
              color: active ? (isPriv ? '#A78BFA' : M_FG_DIM) : M_FG_DIM,
              padding: '0 5px', borderRadius: 5,
              background: active ? 'rgba(0,0,0,0.25)' : 'transparent',
            }}>{g.count}</span>
          </button>
        );
      })}
    </div>
  );
}

// Handoff card shown when user picks the Private group from regular Tabs page
function TPrivateTabsHandoff({ onOpenPrivate }) {
  return (
    <div style={{
      marginTop: 28, padding: '32px 28px',
      background: 'radial-gradient(ellipse at 50% 0%, rgba(167,139,250,0.10), transparent 70%), ' + M_SURFACE,
      border: '1px solid rgba(167,139,250,0.20)', borderRadius: 18,
      display: 'flex', alignItems: 'center', gap: 24, flexWrap: 'wrap',
    }}>
      <div style={{
        width: 64, height: 64, borderRadius: 18,
        background: 'rgba(167,139,250,0.18)', color: '#C4B5FD',
        display: 'grid', placeItems: 'center', flexShrink: 0,
        boxShadow: '0 12px 36px -10px rgba(167,139,250,0.4)',
      }}><IcMask s={32}/></div>
      <div style={{ flex: 1, minWidth: 280 }}>
        <div style={{ fontSize: 12, color: '#C4B5FD', fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.12em', textTransform: 'uppercase', fontWeight: 600 }}>Private window</div>
        <div style={{ fontSize: 22, fontWeight: 600, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.02em', marginTop: 6, color: M_FG }}>
          Your 3 private tabs live in a separate window
        </div>
        <div style={{ fontSize: 13, color: M_FG_MUTED, marginTop: 8, lineHeight: 1.5, maxWidth: 540 }}>
          Private tabs are isolated from your regular session — they don't appear in history, don't share cookies, and aren't synced. Open the private window to see them.
        </div>
      </div>
      <button onClick={onOpenPrivate} style={{
        padding: '12px 18px', borderRadius: 12, border: 0,
        background: 'linear-gradient(135deg, #A78BFA, #7C3AED)',
        color: '#fff', fontSize: 13.5, fontWeight: 600,
        fontFamily: 'Geist, Inter, sans-serif', cursor: 'pointer',
        display: 'inline-flex', alignItems: 'center', gap: 8,
        boxShadow: '0 8px 24px -8px rgba(167,139,250,0.5)',
      }}>
        <IcMask s={15}/> Open private window
      </button>
    </div>
  );
}

// ───── Chat (master-detail) — iPad's killer pattern ─────
function TScreenChatSplit({ landscape = true, empty = false, threadEmpty = false, group = false, onAdd }) {
  if (empty) {
    return <TChatEmptySplit landscape={landscape} onAdd={onAdd}/>;
  }
  if (group) {
    return <TGroupChatSplit landscape={landscape} onAdd={onAdd}/>;
  }
  const chats = [
    { name: 'Aishwarya Iyer', initials: 'AI', bg: '#EF4444', avatar: 'https://i.pravatar.cc/120?img=49', preview: 'great, let’s do that', time: 'Apr 24', conn: 'internet', online: true },
    { name: 'Rohan Sharma',   initials: 'RS', bg: '#F472B6', avatar: 'https://i.pravatar.cc/120?img=12', preview: 'sent you the deck',   time: 'Mon',    conn: 'internet', online: true, unread: 3, active: true },
    { name: 'Priya Nair',     initials: 'PN', bg: '#22D3EE', avatar: 'https://i.pravatar.cc/120?img=47', preview: 'got the docs, thanks', time: 'Apr 18', conn: 'ble',    online: true, unread: 2 },
    { name: 'Arjun Mehta',    initials: 'AM', bg: '#6EE7B7', avatar: 'https://i.pravatar.cc/120?img=14', preview: 'on it 👍',             time: 'Apr 16', conn: 'internet', online: true },
    { name: 'Dimitri Volkov', initials: 'DV', bg: '#FBBF24', avatar: 'https://i.pravatar.cc/120?img=33', preview: 'merged the PR',       time: 'Apr 14', conn: 'internet', online: false },
    { name: 'Team · Mesh',    initials: 'TM', bg: '#A78BFA', preview: 'Bob joined the mesh',                                               time: 'Apr 12', conn: 'mesh',     online: false },
  ];
  const active = chats.find(c => c.active) || chats[1];
  const isThreadEmpty = threadEmpty;

  const ListPane = (
    <div style={{
      width: landscape ? 320 : '100%', flexShrink: 0,
      borderRight: landscape ? '1px solid ' + M_BORDER_SOFT : 0,
      display: 'flex', flexDirection: 'column', minHeight: 0, background: M_BG,
    }}>
      <div style={{ padding: '18px 18px 14px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        <div style={{ fontSize: 22, fontWeight: 600, fontFamily: 'Geist', letterSpacing: '-0.02em', color: M_FG }}>Chat</div>
        <div style={{ display: 'flex', gap: 6 }}>
          <button style={{ width: 30, height: 30, borderRadius: 8, background: M_SURFACE, border: '1px solid ' + M_BORDER_SOFT, color: M_FG_MUTED, display: 'grid', placeItems: 'center', cursor: 'pointer' }} aria-label="Search">{MIc.search({ s: 14 })}</button>
          <button onClick={() => onAdd && onAdd('overview')} style={{ width: 30, height: 30, borderRadius: 8, background: 'linear-gradient(135deg,' + M_ACCENT + ',' + M_ACCENT_B + ')', border: 0, color: '#0B0C0F', display: 'grid', placeItems: 'center', cursor: 'pointer' }} aria-label="Add connection">{MIc.plus({ s: 14 })}</button>
        </div>
      </div>
      <div style={{ padding: '0 10px 10px', overflow: 'auto', flex: 1 }}>
        {chats.map((c, i) => (
          <div key={i} style={{
            display: 'flex', alignItems: 'center', gap: 11,
            padding: '10px 10px', borderRadius: 10, cursor: 'pointer',
            background: c.active ? 'var(--m-tint)' : 'transparent',
          }}>
            <div style={{ position: 'relative', flexShrink: 0 }}>
              <MTile size={40} bg={c.bg} color="#fff" label={c.initials} img={c.avatar} radius={20}/>
              {c.online && <div style={{ position: 'absolute', bottom: 0, right: 0, width: 10, height: 10, borderRadius: 5, background: '#22D27A', border: '2px solid ' + M_BG }}/>}
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                <span style={{ fontSize: 13.5, fontWeight: 600, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.01em', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', flex: 1, color: M_FG }}>{c.name}</span>
                <MConnChip type={c.conn}/>
              </div>
              <div style={{ fontSize: 12, color: c.unread ? M_FG : M_FG_MUTED, marginTop: 3, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', fontWeight: c.unread ? 500 : 400 }}>{c.preview}</div>
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 4, flexShrink: 0 }}>
              <span style={{ fontSize: 10, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace' }}>{c.time}</span>
              {c.unread > 0 && <span style={{ minWidth: 16, height: 16, padding: '0 4px', borderRadius: 8, background: M_ACCENT_B, color: '#0B0C0F', fontSize: 9.5, fontWeight: 700, display: 'grid', placeItems: 'center' }}>{c.unread}</span>}
            </div>
          </div>
        ))}
      </div>
    </div>
  );

  const messages = [
    { from: 'them', text: 'hey — sent you the keynote deck for tomorrow', time: '9:32' },
    { from: 'me',   text: 'thanks! looking at it now', time: '9:34' },
    { from: 'them', text: 'slide 14 has the new architecture — that\'s the one I want to walk through first', time: '9:35' },
    { from: 'me',   text: 'got it. the DIDComm routing diagram looks much clearer than v1', time: '9:36' },
    { from: 'them', text: 'right? cleaning up the mediator nesting helped a lot', time: '9:36' },
    { from: 'me',   text: 'great, let’s do that', time: '9:38' },
  ];

  const ThreadPane = (
    <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minWidth: 0, background: M_BG }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '14px 20px', borderBottom: '1px solid ' + M_BORDER_SOFT }}>
        <MTile size={36} bg={active.bg} color="#fff" label={active.initials} img={active.avatar} radius={18}/>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 15, fontWeight: 600, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.01em' }}>{active.name}</div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 2 }}>
            <span style={{ width: 5, height: 5, borderRadius: 3, background: active.online ? '#22D27A' : M_FG_DIM }}/>
            <span style={{ fontSize: 11, color: M_FG_MUTED }}>{active.online ? 'Online' : 'Offline'}</span>
            <MConnChip type={active.conn}/>
            <span style={{ fontSize: 10, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace' }}>· did:peer:2.rs…7Mq</span>
          </div>
        </div>
        <button style={tIconBtn(false)} aria-label="Call">{MIc.calls({ s: 18 })}</button>
        <button style={tIconBtn(false)} aria-label="More">{MIc.more({ s: 18 })}</button>
      </div>

      <div style={{ flex: 1, overflow: 'auto', padding: '20px 24px', display: 'flex', flexDirection: 'column', gap: 10 }}>
        {isThreadEmpty ? (
          <TThreadEmpty active={active}/>
        ) : (
          <>
            <div style={{ textAlign: 'center', fontSize: 10, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.1em', margin: '0 0 6px' }}>
              MONDAY · DIDCOMM END-TO-END ENCRYPTED
            </div>
            {messages.map((m, i) => (
              <div key={i} style={{
                alignSelf: m.from === 'me' ? 'flex-end' : 'flex-start',
                maxWidth: '64%',
                background: m.from === 'me'
                  ? 'linear-gradient(135deg,' + M_ACCENT + ',' + M_ACCENT_B + ')'
                  : M_SURFACE,
                color: m.from === 'me' ? '#0B0C0F' : M_FG,
                padding: '9px 14px', borderRadius: m.from === 'me' ? '16px 16px 4px 16px' : '16px 16px 16px 4px',
                fontSize: 14, fontWeight: m.from === 'me' ? 500 : 400, lineHeight: 1.4,
              }}>{m.text}</div>
            ))}
            <div style={{ alignSelf: 'flex-end', fontSize: 10, color: M_FG_DIM, marginRight: 4 }}>Delivered · 9:38</div>
            <div style={{ alignSelf: 'flex-start', fontSize: 11, color: M_FG_MUTED, fontStyle: 'italic', marginTop: 2 }}>typing…</div>
          </>
        )}
      </div>

      <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '12px 18px 18px', borderTop: '1px solid ' + M_BORDER_SOFT }}>
        <button style={{ width: 36, height: 36, borderRadius: 18, background: M_SURFACE, border: 0, color: M_FG, display: 'grid', placeItems: 'center', flexShrink: 0, cursor: 'pointer' }}>{MIc.plus({ s: 18 })}</button>
        <div style={{ flex: 1, display: 'flex', alignItems: 'center', gap: 10, padding: '9px 16px', background: M_SURFACE, border: '1px solid ' + M_BORDER_SOFT, borderRadius: 20 }}>
          <span style={{ flex: 1, fontSize: 13.5, color: M_FG_MUTED }}>Message {active.name.split(' ')[0]}…</span>
          <span style={{ color: M_FG_DIM }}>{MIc.mic({ s: 16 })}</span>
        </div>
      </div>
    </div>
  );

  if (!landscape) {
    return <TChatPortraitStack ListPane={ListPane} ThreadPane={ThreadPane} headerName={active.name}/>;
  }
  return (
    <div style={{ flex: 1, display: 'flex', minHeight: 0 }}>
      {ListPane}
      {ThreadPane}
    </div>
  );
}

// ───── Mesh / Network ─────
function TScreenMesh({ landscape = true }) {
  const peers = [
    { name: 'iPad Pro (this)',   initials: 'ME', bg: '#6EE7B7', conn: 'mesh',     hint: 'this device' },
    { name: 'Aishwarya · iPhone',initials: 'AI', bg: '#EF4444', conn: 'ble',      hint: '12 m · BLE' },
    { name: 'Maya · MacBook',    initials: 'MC', bg: '#A78BFA', conn: 'internet', hint: 'online · mediator' },
    { name: 'Rohan · Pixel',     initials: 'RS', bg: '#F472B6', conn: 'mesh',     hint: '8 m · BLE' },
  ];
  return (
    <div style={{ flex: 1, overflow: 'auto', padding: landscape ? '28px 40px 80px' : '24px 24px 80px' }}>
      <div style={{ fontSize: 28, fontWeight: 600, fontFamily: 'Geist', letterSpacing: '-0.02em', marginBottom: 20, color: M_FG }}>Mesh</div>
      <div style={{
        padding: 24, borderRadius: 18,
        background: 'linear-gradient(135deg, rgba(110,231,183,0.12), rgba(96,165,250,0.10))',
        border: '1px solid ' + M_BORDER, marginBottom: 28,
        display: 'grid', gridTemplateColumns: landscape ? '1.2fr 1fr 1fr 1fr' : '1fr 1fr',
        gap: 24, alignItems: 'center',
      }}>
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 6 }}>
            <span style={{ width: 8, height: 8, borderRadius: 4, background: '#22D27A', boxShadow: '0 0 12px #22D27A' }}/>
            <span style={{ fontSize: 11, color: M_FG_MUTED, fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.1em', textTransform: 'uppercase' }}>All systems connected</span>
          </div>
          <div style={{ fontSize: 11, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace' }}>did:key:z6Mk…9kTp</div>
        </div>
        {[{l: 'Mesh peers', v: '3', h: 'BLE'}, {l: 'Mediators', v: '1', h: 'online'}, {l: 'Throughput', v: '24 KB/s', h: 'last 1m'}].map((s, i) => (
          <div key={i} style={{ padding: 14, background: 'rgba(0,0,0,0.28)', borderRadius: 12 }}>
            <div style={{ fontSize: 9.5, color: M_FG_DIM, letterSpacing: '0.08em', textTransform: 'uppercase', fontWeight: 600 }}>{s.l}</div>
            <div style={{ fontSize: 24, fontFamily: 'Geist', fontWeight: 600, marginTop: 4, letterSpacing: '-0.02em', color: M_FG }}>{s.v}</div>
            <div style={{ fontSize: 10, color: M_FG_MUTED, marginTop: 2 }}>{s.h}</div>
          </div>
        ))}
      </div>

      <div style={{ fontSize: 10, fontWeight: 600, color: M_FG_DIM, letterSpacing: '0.12em', textTransform: 'uppercase', marginBottom: 10 }}>Devices in range</div>
      <div style={{ background: M_SURFACE, borderRadius: 14, border: '1px solid ' + M_BORDER_SOFT, overflow: 'hidden' }}>
        {peers.map((p, i) => (
          <div key={i} style={{
            display: 'flex', alignItems: 'center', gap: 14, padding: '14px 18px',
            borderBottom: i < peers.length - 1 ? '1px solid ' + M_BORDER_SOFT : 'none',
          }}>
            <MTile size={36} bg={p.bg} color="#fff" label={p.initials} radius={18}/>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 14, fontWeight: 500, color: M_FG }}>{p.name}</div>
              <div style={{ fontSize: 11.5, color: M_FG_MUTED, marginTop: 2, fontFamily: 'JetBrains Mono, monospace' }}>{p.hint}</div>
            </div>
            <MConnChip type={p.conn}/>
          </div>
        ))}
      </div>
    </div>
  );
}

// ───── Chat list empty (no peers yet) + select-a-conversation placeholder ─────
function TChatEmptySplit({ landscape = true, onAdd }) {
  const ListPane = (
    <div style={{
      width: landscape ? 320 : '100%', flexShrink: 0,
      borderRight: landscape ? '1px solid ' + M_BORDER_SOFT : 0,
      display: 'flex', flexDirection: 'column', minHeight: 0, background: M_BG,
    }}>
      <div style={{ padding: '18px 18px 14px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        <div style={{ fontSize: 22, fontWeight: 600, fontFamily: 'Geist', letterSpacing: '-0.02em', color: M_FG }}>Chat</div>
        <button onClick={() => onAdd && onAdd('overview')} style={{
          width: 30, height: 30, borderRadius: 8,
          background: 'linear-gradient(135deg,' + M_ACCENT + ',' + M_ACCENT_B + ')',
          border: 0, color: '#0B0C0F', display: 'grid', placeItems: 'center', cursor: 'pointer',
        }} aria-label="Add">{MIc.plus({ s: 14 })}</button>
      </div>
      <div style={{ flex: 1, padding: '0 18px', display: 'flex', flexDirection: 'column', justifyContent: 'center', textAlign: 'center' }}>
        {/* concentric rings */}
        <div style={{ display: 'grid', placeItems: 'center', marginBottom: 18 }}>
          <div style={{ position: 'relative', width: 140, height: 140 }}>
            {[140, 108, 78, 50].map((d, i) => (
              <div key={i} style={{
                position: 'absolute', inset: '50% 0 0 50%',
                width: d, height: d, marginLeft: -d/2, marginTop: -d/2,
                borderRadius: '50%',
                border: '1px solid rgba(110,231,183,' + (0.05 + i * 0.06) + ')',
                background: i === 3 ? 'radial-gradient(circle, rgba(110,231,183,0.18) 0%, rgba(96,165,250,0.06) 70%, transparent 100%)' : 'transparent',
              }}/>
            ))}
            <div style={{
              position: 'absolute', inset: '50% 0 0 50%',
              width: 34, height: 34, marginLeft: -17, marginTop: -17,
              borderRadius: '50%',
              background: 'linear-gradient(135deg,' + M_ACCENT + ',' + M_ACCENT_B + ')',
              display: 'grid', placeItems: 'center', color: '#0B0C0F',
              boxShadow: '0 6px 18px rgba(110,231,183,0.25)',
            }}>{MIc.chat({ s: 16 })}</div>
          </div>
        </div>
        <div style={{ fontSize: 16, fontWeight: 600, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.02em', color: M_FG }}>No conversations yet</div>
        <div style={{ fontSize: 12.5, color: M_FG_MUTED, marginTop: 6, lineHeight: 1.45 }}>
          Add a peer to start your first conversation. Everything is end-to-end encrypted over DIDComm.
        </div>
        <button onClick={() => onAdd && onAdd('overview')} style={{
          marginTop: 18, padding: '10px 14px', borderRadius: 10,
          background: 'linear-gradient(135deg,' + M_ACCENT + ',' + M_ACCENT_B + ')',
          border: 0, color: '#0B0C0F', fontSize: 13, fontWeight: 600,
          fontFamily: 'Geist, Inter, sans-serif', cursor: 'pointer',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6,
          alignSelf: 'center',
        }}>
          {MIc.plus({ s: 14 })} Add a connection
        </button>
      </div>
      <div style={{ padding: '14px 18px', borderTop: '1px solid ' + M_BORDER_SOFT, display: 'flex', alignItems: 'center', gap: 10 }}>
        <span style={{ color: M_ACCENT }}>{MIc.shield({ s: 13 })}</span>
        <div style={{ fontSize: 10.5, color: M_FG_MUTED, lineHeight: 1.35 }}>
          Your identity <span style={{ color: M_FG, fontFamily: 'JetBrains Mono, monospace' }}>did:key:…9kTp</span> is ready.
        </div>
      </div>
    </div>
  );

  const RightPane = (
    <div style={{ flex: 1, display: 'grid', placeItems: 'center', color: M_FG_MUTED, padding: 40, textAlign: 'center', background: `radial-gradient(ellipse at 50% 30%, #14171c 0%, ${M_BG} 70%)` }}>
      <div style={{ maxWidth: 340 }}>
        <div style={{ opacity: 0.5, marginBottom: 14, display: 'grid', placeItems: 'center' }}>
          <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" style={{ color: M_FG_DIM }}>
            <path d="M3 6a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3h-5l-5 4v-4H6a3 3 0 0 1-3-3z"/>
          </svg>
        </div>
        <div style={{ fontSize: 18, fontFamily: 'Geist, Inter, sans-serif', fontWeight: 600, color: M_FG, letterSpacing: '-0.02em' }}>Select a conversation</div>
        <div style={{ fontSize: 13, color: M_FG_MUTED, marginTop: 8, lineHeight: 1.5 }}>
          Pick someone from the list to open a thread, or add a new connection to get started.
        </div>
        <button onClick={() => onAdd && onAdd('handle')} style={{
          marginTop: 18, padding: '10px 14px', borderRadius: 10,
          background: M_SURFACE, border: '1px solid ' + M_BORDER_SOFT,
          color: M_FG, fontSize: 13, fontWeight: 500,
          fontFamily: 'inherit', cursor: 'pointer',
          display: 'inline-flex', alignItems: 'center', gap: 8,
        }}>
          {MIc.search({ s: 14 })} Find by handle
        </button>
      </div>
    </div>
  );

  if (!landscape) return <div style={{ flex: 1, display: 'flex', minHeight: 0 }}>{ListPane}</div>;
  return (
    <div style={{ flex: 1, display: 'flex', minHeight: 0 }}>
      {ListPane}
      {RightPane}
    </div>
  );
}

// Thread-empty body — peer just connected, no messages yet
function TThreadEmpty({ active }) {
  return (
    <>
      <div style={{
        margin: '12px auto 0', padding: '24px 22px',
        background: 'linear-gradient(180deg, rgba(110,231,183,0.06), rgba(96,165,250,0.04))',
        border: '1px solid ' + M_BORDER, borderRadius: 18,
        width: '100%', maxWidth: 360, textAlign: 'center', boxSizing: 'border-box',
      }}>
        <div style={{ display: 'grid', placeItems: 'center', marginBottom: 12 }}>
          <div style={{ position: 'relative' }}>
            <MTile size={72} bg={active.bg} color="#fff" label={active.initials} img={active.avatar} radius={36}/>
            <div style={{
              position: 'absolute', bottom: -2, right: -2,
              width: 24, height: 24, borderRadius: 12,
              background: M_BG, display: 'grid', placeItems: 'center',
              border: '2px solid ' + M_BG,
            }}>
              <div style={{ width: 18, height: 18, borderRadius: 9, background: M_ACCENT, display: 'grid', placeItems: 'center', color: '#0B0C0F' }}>
                <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round"><path d="M20 6 9 17l-5-5"/></svg>
              </div>
            </div>
          </div>
        </div>
        <div style={{ fontSize: 17, fontWeight: 600, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.02em' }}>{active.name}</div>
        <div style={{ fontSize: 11, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace', marginTop: 4 }}>did:peer:2.rs…7Mq</div>
        <div style={{ display: 'inline-flex', alignItems: 'center', gap: 5, marginTop: 12, padding: '4px 10px', borderRadius: 999, background: 'rgba(110,231,183,0.12)', color: M_ACCENT, fontSize: 10.5, fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.06em', textTransform: 'uppercase', fontWeight: 600 }}>
          {MIc.shield({ s: 11 })} Verified · DIDComm 2
        </div>
        <div style={{ fontSize: 12, color: M_FG_MUTED, marginTop: 14, lineHeight: 1.45 }}>
          Connected 2 min ago · no messages yet
        </div>
      </div>
      <div style={{
        margin: '18px auto 0', maxWidth: 360, width: '100%',
        padding: '12px 14px',
        background: M_SURFACE, border: '1px solid ' + M_BORDER_SOFT,
        borderRadius: 12, display: 'flex', alignItems: 'flex-start', gap: 10, boxSizing: 'border-box',
      }}>
        <span style={{ color: M_ACCENT_B, marginTop: 1 }}>{MIc.shield({ s: 16 })}</span>
        <div style={{ flex: 1, fontSize: 11.5, color: M_FG_MUTED, lineHeight: 1.45 }}>
          Messages are end-to-end encrypted. Only you and <span style={{ color: M_FG }}>{active.name.split(' ')[0]}</span> can read them — not even Ajna.
        </div>
      </div>
      <div style={{ margin: '20px auto 0', maxWidth: 360, width: '100%' }}>
        <div style={{ fontSize: 10, fontWeight: 600, color: M_FG_DIM, letterSpacing: '0.12em', textTransform: 'uppercase', marginBottom: 10 }}>Break the ice</div>
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
          {[
            { e: '👋', t: 'Say hi' },
            { e: '✨', t: 'Nice to connect' },
            { e: '📎', t: 'Send a file' },
            { e: '📞', t: 'Start a call' },
          ].map(s => (
            <button key={s.t} style={{
              display: 'inline-flex', alignItems: 'center', gap: 6,
              padding: '8px 12px', background: M_SURFACE,
              border: '1px solid ' + M_BORDER_SOFT, borderRadius: 999,
              color: M_FG, fontSize: 12.5, fontFamily: 'inherit', cursor: 'pointer',
            }}>
              <span style={{ fontSize: 13 }}>{s.e}</span>{s.t}
            </button>
          ))}
        </div>
      </div>
      <div style={{ flex: 1, minHeight: 20 }}/>
      <div style={{ textAlign: 'center', fontSize: 10, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.1em', marginTop: 12 }}>
        ── BEGINNING OF CONVERSATION ──
      </div>
    </>
  );
}

Object.assign(window, { TChatEmptySplit, TThreadEmpty });

// iPad portrait push-stack — list slides left, thread comes in with a back-to-list nav bar.
// Lets the user actually see threads in portrait without breaking the master-detail mental model.
function TChatPortraitStack({ ListPane, ThreadPane, headerName }) {
  const [showThread, setShowThread] = React.useState(false);
  // Intercept clicks on list items: any click inside the list slides the thread in.
  return (
    <div style={{ flex: 1, position: 'relative', minHeight: 0, overflow: 'hidden' }}>
      <div onClickCapture={() => setShowThread(true)} style={{ position: 'absolute', inset: 0, display: 'flex' }}>
        {ListPane}
      </div>
      {showThread && (
        <div style={{
          position: 'absolute', inset: 0, background: M_BG,
          display: 'flex', flexDirection: 'column',
          animation: 'tPortraitSlide 220ms cubic-bezier(0.2,0.85,0.3,1)',
          zIndex: 5,
        }}>
          <style>{`@keyframes tPortraitSlide { from { transform: translateX(100%); } to { transform: translateX(0); } }`}</style>
          <div style={{
            display: 'flex', alignItems: 'center', gap: 4,
            padding: '10px 14px 0', flexShrink: 0,
          }}>
            <button onClick={() => setShowThread(false)} aria-label="Back to chats" style={{
              display: 'inline-flex', alignItems: 'center', gap: 4,
              padding: '6px 6px 6px 0',
              background: 'transparent', border: 0,
              color: M_ACCENT_B, fontFamily: 'inherit', fontSize: 14, fontWeight: 500,
              cursor: 'pointer',
            }}>
              <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m15 18-6-6 6-6"/></svg>
              Chats
            </button>
          </div>
          <div style={{ flex: 1, minHeight: 0, display: 'flex' }}>{ThreadPane}</div>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { TChatPortraitStack });
Object.assign(window, {
  TScreenNTP, TScreenTabs, TScreenChatSplit, TScreenMesh,
});

// ───── Group chat (master-detail with 3rd column member list in landscape) ─────
function TGroupChatSplit({ landscape = true, onAdd }) {
  // sidebar list shows chats, with the group highlighted
  const chats = [
    { name: 'Aishwarya Iyer',    initials: 'AI', bg: '#EF4444', avatar: 'https://i.pravatar.cc/120?img=49', preview: 'great, let’s do that', time: 'Apr 24', conn: 'internet', online: true },
    { name: 'Ajna · iPad team',  initials: 'AT', bg: 'linear-gradient(135deg,#6EE7B7,#60A5FA)', isGroup: true, members: 5,
      preview: 'Rohan: pushed v0.4.2 to TestFlight',                                        time: '12:04', conn: 'mesh',     online: true,  unread: 7, active: true },
    { name: 'Rohan Sharma',      initials: 'RS', bg: '#F472B6', avatar: 'https://i.pravatar.cc/120?img=12', preview: 'sent you the deck',   time: 'Mon',    conn: 'internet', online: true, unread: 3 },
    { name: 'Priya Nair',        initials: 'PN', bg: '#22D3EE', avatar: 'https://i.pravatar.cc/120?img=47', preview: 'got the docs, thanks', time: 'Apr 18', conn: 'ble',    online: true, unread: 2 },
    { name: 'Berlin · Mesh',     initials: 'BM', bg: '#A78BFA', isGroup: true, members: 12, preview: 'Bob joined the mesh', time: 'Apr 12', conn: 'mesh',     online: false },
  ];
  const active = chats.find(c => c.active);

  const members = [
    { initials: 'MC', name: 'Maya Chen',          role: 'Admin · you', bg: '#A78BFA', online: true,  conn: 'internet' },
    { initials: 'RS', name: 'Rohan Sharma',       role: 'Admin',        bg: '#F472B6', online: true,  conn: 'internet', avatar: 'https://i.pravatar.cc/120?img=12' },
    { initials: 'AI', name: 'Aishwarya Iyer',     role: 'Member',       bg: '#EF4444', online: true,  conn: 'internet', avatar: 'https://i.pravatar.cc/120?img=49' },
    { initials: 'PN', name: 'Priya Nair',         role: 'Member',       bg: '#22D3EE', online: false, conn: 'ble',      avatar: 'https://i.pravatar.cc/120?img=47' },
    { initials: 'AM', name: 'Arjun Mehta',        role: 'Member',       bg: '#6EE7B7', online: true,  conn: 'mesh',     avatar: 'https://i.pravatar.cc/120?img=14' },
  ];

  // group messages with sender labels & avatars
  const messages = [
    { kind: 'system', text: 'Maya created the group "Ajna · iPad team"' },
    { kind: 'msg', who: 'rs', name: 'Rohan',     bg: '#F472B6', text: 'morning all — pushed v0.4.2 to TestFlight', time: '11:42' },
    { kind: 'msg', who: 'pn', name: 'Priya',     bg: '#22D3EE', text: 'will install in 5', time: '11:43' },
    { kind: 'msg', who: 'me', name: 'You',                     text: 'I tested split-view on the 11" and the 13" — chrome collapse works on both', time: '11:50' },
    { kind: 'msg', who: 'ai', name: 'Aishwarya', bg: '#EF4444', text: 'the master-detail in landscape feels right. portrait pushing the thread on tap?', time: '11:52' },
    { kind: 'msg', who: 'me', name: 'You',                     text: 'yeah, that\'s the plan', time: '11:53' },
    { kind: 'msg', who: 'rs', name: 'Rohan',     bg: '#F472B6', text: 'screenshot:', time: '12:01', attachment: { kind: 'image', label: 'IMG_0418.png · 1.2 MB' } },
    { kind: 'msg', who: 'rs', name: 'Rohan',     bg: '#F472B6', text: 'one issue — pull-to-refresh fights the scroll-collapse. opening a ticket', time: '12:04' },
    { kind: 'system', text: 'Arjun joined the group' },
  ];

  const ListPane = (
    <div style={{
      width: landscape ? 300 : '100%', flexShrink: 0,
      borderRight: landscape ? '1px solid ' + M_BORDER_SOFT : 0,
      display: 'flex', flexDirection: 'column', minHeight: 0, background: M_BG,
    }}>
      <div style={{ padding: '18px 18px 14px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        <div style={{ fontSize: 22, fontWeight: 600, fontFamily: 'Geist', letterSpacing: '-0.02em', color: M_FG }}>Chat</div>
        <div style={{ display: 'flex', gap: 6 }}>
          <button style={{ width: 30, height: 30, borderRadius: 8, background: M_SURFACE, border: '1px solid ' + M_BORDER_SOFT, color: M_FG_MUTED, display: 'grid', placeItems: 'center', cursor: 'pointer' }} aria-label="Search">{MIc.search({ s: 14 })}</button>
          <button onClick={() => onAdd && onAdd('overview')} style={{ width: 30, height: 30, borderRadius: 8, background: 'linear-gradient(135deg,' + M_ACCENT + ',' + M_ACCENT_B + ')', border: 0, color: '#0B0C0F', display: 'grid', placeItems: 'center', cursor: 'pointer' }} aria-label="Add">{MIc.plus({ s: 14 })}</button>
        </div>
      </div>
      <div style={{ padding: '0 10px 10px', overflow: 'auto', flex: 1 }}>
        {chats.map((c, i) => (
          <div key={i} style={{
            display: 'flex', alignItems: 'center', gap: 11,
            padding: '10px 10px', borderRadius: 10, cursor: 'pointer',
            background: c.active ? 'var(--m-tint)' : 'transparent',
          }}>
            <div style={{ position: 'relative', flexShrink: 0 }}>
              {c.isGroup ? (
                <div style={{
                  width: 40, height: 40, borderRadius: 20, background: c.bg,
                  display: 'grid', placeItems: 'center', color: '#0B0C0F',
                  fontWeight: 700, fontSize: 11, fontFamily: 'Geist',
                }}>{c.members}</div>
              ) : (
                <MTile size={40} bg={c.bg} color="#fff" label={c.initials} img={c.avatar} radius={20}/>
              )}
              {c.online && <div style={{ position: 'absolute', bottom: 0, right: 0, width: 10, height: 10, borderRadius: 5, background: '#22D27A', border: '2px solid ' + M_BG }}/>}
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                <span style={{ fontSize: 13.5, fontWeight: 600, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.01em', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', flex: 1, color: M_FG }}>{c.name}</span>
                {c.isGroup && (
                  <span style={{
                    display: 'inline-flex', alignItems: 'center', gap: 2,
                    padding: '1px 5px', borderRadius: 4,
                    background: 'rgba(167,139,250,0.16)', color: '#C4B5FD',
                    fontSize: 9, fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.06em', fontWeight: 600,
                  }}>GROUP</span>
                )}
                <MConnChip type={c.conn}/>
              </div>
              <div style={{ fontSize: 12, color: c.unread ? M_FG : M_FG_MUTED, marginTop: 3, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', fontWeight: c.unread ? 500 : 400 }}>{c.preview}</div>
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 4, flexShrink: 0 }}>
              <span style={{ fontSize: 10, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace' }}>{c.time}</span>
              {c.unread > 0 && <span style={{ minWidth: 16, height: 16, padding: '0 4px', borderRadius: 8, background: M_ACCENT_B, color: '#0B0C0F', fontSize: 9.5, fontWeight: 700, display: 'grid', placeItems: 'center' }}>{c.unread}</span>}
            </div>
          </div>
        ))}
      </div>
    </div>
  );

  // Stacked avatar cluster for the group header
  const AvatarCluster = ({ size = 36 }) => (
    <div style={{ display: 'inline-flex', position: 'relative', width: size + 16, height: size, flexShrink: 0 }}>
      {members.slice(0, 3).map((m, i) => (
        <div key={i} style={{
          position: 'absolute', left: i * 12, top: 0,
          width: size, height: size, borderRadius: size/2,
          background: m.bg, color: '#fff',
          display: 'grid', placeItems: 'center',
          fontSize: size * 0.32, fontWeight: 700, fontFamily: 'Geist',
          border: '2px solid ' + M_BG,
          backgroundImage: m.avatar ? `url(${m.avatar})` : 'none',
          backgroundSize: 'cover',
        }}>{m.avatar ? '' : m.initials}</div>
      ))}
    </div>
  );

  const ThreadPane = (
    <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minWidth: 0, background: M_BG }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 20px', borderBottom: '1px solid ' + M_BORDER_SOFT }}>
        <AvatarCluster size={34}/>
        <div style={{ flex: 1, minWidth: 0, marginLeft: -4 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <span style={{ fontSize: 15, fontWeight: 600, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.01em' }}>{active.name}</span>
            <span style={{
              display: 'inline-flex', alignItems: 'center', gap: 3,
              padding: '1px 6px', borderRadius: 4,
              background: 'rgba(167,139,250,0.16)', color: '#C4B5FD',
              fontSize: 9, fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.06em', fontWeight: 600,
            }}>GROUP · {active.members}</span>
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 2 }}>
            <span style={{ width: 5, height: 5, borderRadius: 3, background: '#22D27A' }}/>
            <span style={{ fontSize: 11, color: M_FG_MUTED }}>3 online</span>
            <MConnChip type="mesh"/>
            <span style={{ fontSize: 10, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace' }}>· did:peer:grp:…7Mq</span>
          </div>
        </div>
        <button style={tIconBtn(false)} aria-label="Call">{MIc.calls({ s: 18 })}</button>
        <button style={tIconBtn(false)} aria-label="Add member">{MIc.plus({ s: 18 })}</button>
        <button style={tIconBtn(false)} aria-label="More">{MIc.more({ s: 18 })}</button>
      </div>

      <div style={{ flex: 1, overflow: 'auto', padding: '18px 24px', display: 'flex', flexDirection: 'column', gap: 8 }}>
        <div style={{ textAlign: 'center', fontSize: 10, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.1em', margin: '0 0 4px' }}>
          TODAY · GROUP MESSAGES ARE ENCRYPTED PER-MEMBER
        </div>
        {messages.map((m, i) => {
          if (m.kind === 'system') return (
            <div key={i} style={{ alignSelf: 'center', fontSize: 10.5, color: M_FG_DIM, padding: '6px 12px', borderRadius: 999, background: M_SURFACE, border: '1px solid ' + M_BORDER_SOFT, margin: '8px 0' }}>
              {m.text}
            </div>
          );
          const me = m.who === 'me';
          // group same sender consecutively
          const prev = messages[i - 1];
          const samePrev = prev && prev.kind === 'msg' && prev.who === m.who;
          return (
            <div key={i} style={{
              display: 'flex', alignSelf: me ? 'flex-end' : 'flex-start',
              flexDirection: me ? 'row-reverse' : 'row',
              alignItems: 'flex-end', gap: 8, maxWidth: '72%',
              marginTop: samePrev ? -2 : 4,
            }}>
              {!me && (
                <div style={{ width: 24, flexShrink: 0 }}>
                  {!samePrev && (
                    <div style={{ width: 24, height: 24, borderRadius: 12, background: m.bg, color: '#fff', display: 'grid', placeItems: 'center', fontSize: 9, fontWeight: 700, fontFamily: 'Geist' }}>
                      {m.name[0]}
                    </div>
                  )}
                </div>
              )}
              <div style={{ display: 'flex', flexDirection: 'column', alignItems: me ? 'flex-end' : 'flex-start', minWidth: 0 }}>
                {!me && !samePrev && (
                  <span style={{ fontSize: 11, fontWeight: 600, color: M_FG_MUTED, marginBottom: 2, paddingLeft: 2 }}>{m.name}</span>
                )}
                <div style={{
                  background: me ? 'linear-gradient(135deg,' + M_ACCENT + ',' + M_ACCENT_B + ')' : M_SURFACE,
                  color: me ? '#0B0C0F' : M_FG,
                  padding: '9px 13px',
                  borderRadius: me
                    ? (samePrev ? '16px 4px 4px 16px' : '16px 16px 4px 16px')
                    : (samePrev ? '4px 16px 16px 4px' : '16px 16px 16px 4px'),
                  fontSize: 14, fontWeight: me ? 500 : 400, lineHeight: 1.4,
                }}>{m.text}</div>
                {m.attachment && (
                  <div style={{
                    marginTop: 4, padding: '10px 12px', borderRadius: 10,
                    background: M_SURFACE_2, border: '1px solid ' + M_BORDER_SOFT,
                    display: 'flex', alignItems: 'center', gap: 10, minWidth: 220,
                  }}>
                    <div style={{ width: 32, height: 32, borderRadius: 6, background: 'linear-gradient(135deg,#60A5FA,#A78BFA)', display: 'grid', placeItems: 'center', color: '#0B0C0F' }}>
                      <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-5-5L5 21"/></svg>
                    </div>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: 12, fontWeight: 500, color: M_FG, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{m.attachment.label}</div>
                      <div style={{ fontSize: 10.5, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace' }}>tap to preview</div>
                    </div>
                  </div>
                )}
              </div>
            </div>
          );
        })}
        <div style={{ alignSelf: 'flex-start', fontSize: 11, color: M_FG_MUTED, fontStyle: 'italic', marginLeft: 32, marginTop: 4 }}>Priya is typing…</div>
      </div>

      <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '12px 18px 18px', borderTop: '1px solid ' + M_BORDER_SOFT }}>
        <button style={{ width: 36, height: 36, borderRadius: 18, background: M_SURFACE, border: 0, color: M_FG, display: 'grid', placeItems: 'center', flexShrink: 0, cursor: 'pointer' }}>{MIc.plus({ s: 18 })}</button>
        <div style={{ flex: 1, display: 'flex', alignItems: 'center', gap: 10, padding: '9px 16px', background: M_SURFACE, border: '1px solid ' + M_BORDER_SOFT, borderRadius: 20 }}>
          <span style={{ flex: 1, fontSize: 13.5, color: M_FG_MUTED }}>Message the group…</span>
          <span style={{ fontSize: 10, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace' }}>@</span>
          <span style={{ color: M_FG_DIM }}>{MIc.mic({ s: 16 })}</span>
        </div>
      </div>
    </div>
  );

  const MemberPane = (
    <div style={{
      width: 260, flexShrink: 0,
      borderLeft: '1px solid ' + M_BORDER_SOFT,
      background: M_SURFACE, display: 'flex', flexDirection: 'column', minHeight: 0,
    }}>
      <div style={{ padding: '14px 16px', borderBottom: '1px solid ' + M_BORDER_SOFT }}>
        <div style={{ fontSize: 10, fontWeight: 600, color: M_FG_DIM, letterSpacing: '0.12em', textTransform: 'uppercase' }}>About</div>
        <div style={{ fontSize: 15, fontWeight: 600, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.01em', marginTop: 6 }}>Ajna · iPad team</div>
        <div style={{ fontSize: 11.5, color: M_FG_MUTED, marginTop: 4, lineHeight: 1.4 }}>
          Coordinating the iPad shell, master-detail split, and scroll-collapsing chrome.
        </div>
        <div style={{ display: 'flex', gap: 6, marginTop: 10 }}>
          <button style={{ flex: 1, padding: '7px 10px', borderRadius: 8, background: M_SURFACE, border: '1px solid ' + M_BORDER_SOFT, color: M_FG, fontSize: 11.5, fontFamily: 'inherit', cursor: 'pointer' }}>Mute</button>
          <button style={{ flex: 1, padding: '7px 10px', borderRadius: 8, background: M_SURFACE, border: '1px solid ' + M_BORDER_SOFT, color: M_FG, fontSize: 11.5, fontFamily: 'inherit', cursor: 'pointer' }}>Pin</button>
        </div>
      </div>

      <div style={{ padding: '12px 16px 8px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        <div style={{ fontSize: 10, fontWeight: 600, color: M_FG_DIM, letterSpacing: '0.12em', textTransform: 'uppercase' }}>Members · {members.length}</div>
        <button style={{ background: 'transparent', border: 0, color: M_ACCENT_B, fontSize: 11, cursor: 'pointer', fontFamily: 'inherit' }}>+ Add</button>
      </div>
      <div style={{ flex: 1, overflow: 'auto', padding: '0 8px 12px' }}>
        {members.map((m, i) => (
          <div key={i} style={{
            display: 'flex', alignItems: 'center', gap: 10,
            padding: '8px 8px', borderRadius: 8,
          }}>
            <div style={{ position: 'relative', flexShrink: 0 }}>
              <MTile size={30} bg={m.bg} color="#fff" label={m.initials} img={m.avatar} radius={15}/>
              {m.online && <div style={{ position: 'absolute', bottom: 0, right: 0, width: 8, height: 8, borderRadius: 4, background: '#22D27A', border: '2px solid #0d0e11' }}/>}
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 12.5, fontWeight: 500, color: M_FG, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{m.name}</div>
              <div style={{ fontSize: 10.5, color: M_FG_DIM }}>{m.role}</div>
            </div>
            <MConnChip type={m.conn}/>
          </div>
        ))}
      </div>

      <div style={{ padding: '12px 16px', borderTop: '1px solid ' + M_BORDER_SOFT, display: 'flex', alignItems: 'flex-start', gap: 10 }}>
        <span style={{ color: M_ACCENT_B, marginTop: 1 }}>{MIc.shield({ s: 14 })}</span>
        <div style={{ flex: 1, fontSize: 10.5, color: M_FG_MUTED, lineHeight: 1.4 }}>
          Encrypted per-member with sender keys. New joiners see history from the moment they're added.
        </div>
      </div>
    </div>
  );

  if (!landscape) return <div style={{ flex: 1, display: 'flex', minHeight: 0 }}>{ListPane}</div>;
  return (
    <div style={{ flex: 1, display: 'flex', minHeight: 0 }}>
      {ListPane}
      {ThreadPane}
      {MemberPane}
    </div>
  );
}

Object.assign(window, { TGroupChatSplit });
