// Mobile navigation variants — three options for Chat/Mesh access without modal dead-ends
// Each variant wraps the screens and provides nav chrome.

const NAV_OPTIONS = [
  { id: 'drawer',  label: 'Right-edge drawer',    sub: 'Peek rail overlay' },
  { id: 'superTab', label: 'Super-tabs',          sub: 'Apps live as tabs' },
  { id: 'command',  label: 'Bottom command',      sub: 'Arc-style pill' },
];

// ═══════════════════════════════════════════════════════════
// OPTION 1 — Right-edge drawer
// Bottom nav = browser-only. Persistent right edge handle.
// Swipe/tap opens drawer with Chat/Calls/Files/Mesh/Settings.
// ═══════════════════════════════════════════════════════════
function NavOptionDrawer({ screen, setScreen, activePeer, setActivePeer, showAdd, setShowAdd }) {
  const [drawerOpen, setDrawerOpen] = React.useState(false);
  const addOpen = !!showAdd;
  const setAddOpen = (v) => setShowAdd && setShowAdd(v);
  const [peekHint, setPeekHint] = React.useState(true);
  const [focus, setFocus] = React.useState(screen === 'typing');
  React.useEffect(() => { if (screen === 'typing') setFocus(true); }, [screen]);

  React.useEffect(() => {
    const t = setTimeout(() => setPeekHint(false), 3000);
    return () => clearTimeout(t);
  }, []);

  const drawerItems = [
    { id: 'chat',   label: 'Chat',   icon: MIc.chat,   badge: 3 },
    { id: 'calls',  label: 'Calls',  icon: MIc.calls },
    { id: 'files',  label: 'Files',  icon: MIc.files },
    { id: 'mesh',   label: 'Mesh',   icon: MIc.mesh, hint: '3 peers' },
    { id: 'settings', label: 'Settings', icon: MIc.settings },
  ];

  const openApp = (id) => { setScreen(id); setDrawerOpen(false); };

  return (
    <MobileScreen>
      <MStatusBar/>

      {/* screen body */}
      <div style={{ flex: 1, position: 'relative', overflow: 'hidden' }}>
        {focus && <MCommandFocus onClose={() => { setFocus(false); if (screen === 'typing') setScreen('ntp'); }} onNavigate={(id) => { if (['chat','mesh','files','calls','settings'].includes(id)) setScreen(id); setFocus(false); }}/>}
        {(screen === 'ntp' || screen === 'typing') && <MScreenNTP onOpenSearch={() => setFocus(true)} topOffset={0} bottomOffset={70}/>}
        {screen === 'tabs' && <MScreenTabs/>}
        {screen === 'chat' && <MScreenChatList onOpen={(p) => { setActivePeer(p); setScreen('thread'); }} onAdd={() => setAddOpen('handle')}/>}
        {screen === 'chat-empty' && <MScreenChatListEmpty onAdd={(mode) => setAddOpen(mode || 'handle')}/>}
        {screen === 'thread' && <MScreenChat peer={activePeer} onBack={() => setScreen('chat')}/>}
        {screen === 'thread-empty' && <MScreenChat peer={activePeer} empty onBack={() => setScreen('chat-empty')}/>}
        {addOpen && <MScreenAddConnection mode={showAdd} onClose={() => setAddOpen(null)}/>}
        {screen === 'calls' && <MEmpty icon={MIc.calls} title="No recent calls"/>}
        {screen === 'files' && <MEmpty icon={MIc.files} title="Files"/>}
        {screen === 'mesh' && <MEmpty icon={MIc.mesh} title="Mesh · 3 peers nearby"/>}
        {screen === 'settings' && <MScreenSettings/>}

        {/* right-edge peek handle */}
        <div onClick={() => setDrawerOpen(true)} style={{
          position: 'absolute', right: 0, top: '50%', transform: 'translateY(-50%)',
          width: 18, height: 88, borderRadius: '10px 0 0 10px',
          background: peekHint ? 'linear-gradient(135deg, rgba(110,231,183,0.25), rgba(96,165,250,0.25))' : 'var(--m-tint)',
          border: '1px solid ' + M_BORDER, borderRight: 0,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          backdropFilter: 'blur(10px)', zIndex: 40,
          transition: 'background 400ms',
        }}>
          <div style={{ width: 3, height: 36, borderRadius: 2, background: peekHint ? '#6EE7B7' : M_FG_DIM }}/>
        </div>

        {/* drawer overlay */}
        {drawerOpen && (
          <>
            <div onClick={() => setDrawerOpen(false)} style={{
              position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.55)',
              backdropFilter: 'blur(4px)', zIndex: 50,
            }}/>
            <div style={{
              position: 'absolute', right: 0, top: 0, bottom: 0, width: 250,
              background: M_SURFACE, borderLeft: '1px solid ' + M_BORDER,
              padding: '24px 14px', boxSizing: 'border-box',
              zIndex: 51, display: 'flex', flexDirection: 'column', gap: 4,
              animation: 'slideIn 220ms ease',
            }}>
              <style>{`@keyframes slideIn{from{transform:translateX(100%)}to{transform:translateX(0)}}`}</style>
              <div style={{ fontSize: 10, color: M_FG_DIM, letterSpacing: '0.12em', textTransform: 'uppercase', fontWeight: 600, padding: '2px 12px 10px' }}>Ajna apps</div>
              {drawerItems.map(it => (
                <button key={it.id} onClick={() => openApp(it.id)} style={{
                  display: 'flex', alignItems: 'center', gap: 12,
                  padding: '11px 12px', borderRadius: 10,
                  background: screen === it.id ? 'var(--m-tint)' : 'transparent',
                  border: 0, color: M_FG, cursor: 'pointer', textAlign: 'left',
                }}>
                  <span style={{ color: M_FG_MUTED }}>{it.icon({ s: 20 })}</span>
                  <span style={{ flex: 1, fontSize: 14, fontWeight: 500 }}>{it.label}</span>
                  {it.badge && <span style={{ minWidth: 18, padding: '0 5px', height: 18, borderRadius: 9, background: M_ACCENT_B, color: '#0B0C0F', fontSize: 10, fontWeight: 700, display: 'grid', placeItems: 'center' }}>{it.badge}</span>}
                  {it.hint && <span style={{ fontSize: 10, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace' }}>{it.hint}</span>}
                </button>
              ))}
              <div style={{ marginTop: 'auto', padding: '12px', borderTop: '1px solid ' + M_BORDER_SOFT, fontSize: 10, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace' }}>Swipe from right edge anywhere</div>
            </div>
          </>
        )}
      </div>

      {/* browser-only bottom bar */}
      {screen !== 'thread' && screen !== 'thread-empty' && !focus && (
        <div style={{ padding: '8px 16px', display: 'flex', gap: 8, alignItems: 'center', borderTop: '1px solid ' + M_BORDER_SOFT }}>
          <button onClick={() => setScreen('ntp')} style={iconBtn(screen === 'ntp')}>{MIc.home({ s: 20 })}</button>
          <div style={{ flex: 1 }} onClick={() => setFocus(true)}><MAddressBar url={screen === 'ntp' ? 'ajna://newtab' : 'ajna://' + screen}/></div>
          <button onClick={() => setScreen('tabs')} style={iconBtn(screen === 'tabs')}>
            <div style={{ position: 'relative' }}>
              {MIc.tabs({ s: 20 })}
              <span style={{ position: 'absolute', top: -2, right: -6, minWidth: 12, height: 12, borderRadius: 6, background: M_FG, color: '#0B0C0F', fontSize: 8, fontWeight: 700, display: 'grid', placeItems: 'center', padding: '0 3px' }}>5</span>
            </div>
          </button>
          <button style={iconBtn(false)}>{MIc.more({ s: 20 })}</button>
        </div>
      )}
      <MHomeIndicator/>
    </MobileScreen>
  );
}

// ═══════════════════════════════════════════════════════════
// OPTION 2 — Super-tabs
// Chat/Mesh live as PINNED tabs alongside web tabs.
// Tab switcher becomes the universal navigation.
// ═══════════════════════════════════════════════════════════
function NavOptionSuperTab({ screen, setScreen, activePeer, setActivePeer, showAdd, setShowAdd }) {
  const [switcher, setSwitcher] = React.useState(false);
  const addOpen = !!showAdd;
  const setAddOpen = (v) => setShowAdd && setShowAdd(v);
  const [focus, setFocus] = React.useState(screen === 'typing');
  React.useEffect(() => { if (screen === 'typing') setFocus(true); }, [screen]);

  const pinnedTabs = [
    { id: 'ntp',    label: 'New tab',     icon: MIc.home,   bg: '#14161B' },
    { id: 'chat',   label: 'Chat',        icon: MIc.chat,   bg: '#1E293B', badge: 3 },
    { id: 'mesh',   label: 'Mesh',        icon: MIc.mesh,   bg: '#1F1F2A' },
  ];
  const webTabs = [
    { id: 'linear', label: 'Linear — Inbox', fav: 'L', bg: '#5E6AD2', url: 'linear.app' },
    { id: 'gh',     label: 'GitHub · ajna-inc', fav: 'G', bg: '#24292F', url: 'github.com' },
    { id: 'figma',  label: 'Figma — Ajna UI', fav: 'F', bg: '#000', url: 'figma.com' },
  ];

  const choose = (id) => { setScreen(id); setSwitcher(false); };

  return (
    <MobileScreen>
      <MStatusBar/>

      {/* top chrome — shows current tab identity */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '10px 14px', borderBottom: '1px solid ' + M_BORDER_SOFT }}>
        <button onClick={() => setSwitcher(true)} style={{ display: 'flex', alignItems: 'center', gap: 8, background: M_SURFACE, border: '1px solid ' + M_BORDER_SOFT, borderRadius: 10, padding: '6px 10px', color: M_FG, flex: 1 }}>
          <span style={{ color: M_ACCENT_B }}>
            {screen === 'chat' ? MIc.chat({ s: 15 }) : screen === 'mesh' ? MIc.mesh({ s: 15 }) : MIc.home({ s: 15 })}
          </span>
          <span style={{ fontSize: 12.5, fontWeight: 500, flex: 1, textAlign: 'left' }}>
            {screen === 'chat' ? 'Chat' : screen === 'mesh' ? 'Mesh' : screen === 'tabs' ? 'Tabs' : 'New tab'}
          </span>
          <span style={{ fontSize: 10, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace' }}>tap to switch</span>
        </button>
        <button style={iconBtn(false)}>{MIc.more({ s: 20 })}</button>
      </div>

      <div style={{ flex: 1, overflow: 'hidden', position: 'relative' }}>
        {focus && <MCommandFocus onClose={() => { setFocus(false); if (screen === 'typing') setScreen('ntp'); }} onNavigate={(id) => { if (['chat','mesh'].includes(id)) setScreen(id); setFocus(false); }}/>}
        {(screen === 'ntp' || screen === 'typing') && <MScreenNTP onOpenSearch={() => setFocus(true)} bottomOffset={70}/>}
        {screen === 'tabs' && <MScreenTabs/>}
        {screen === 'chat' && <MScreenChatList onOpen={(p) => { setActivePeer(p); setScreen('thread'); }} onAdd={() => setAddOpen('handle')}/>}
        {screen === 'chat-empty' && <MScreenChatListEmpty onAdd={(mode) => setAddOpen(mode || 'handle')}/>}
        {screen === 'thread' && <MScreenChat peer={activePeer} onBack={() => setScreen('chat')}/>}
        {screen === 'thread-empty' && <MScreenChat peer={activePeer} empty onBack={() => setScreen('chat-empty')}/>}
        {screen === 'mesh' && <MEmpty icon={MIc.mesh} title="Mesh · 3 peers nearby"/>}
        {addOpen && <MScreenAddConnection mode={showAdd} onClose={() => setAddOpen(null)}/>}

        {switcher && (
          <div onClick={() => setSwitcher(false)} style={{
            position: 'absolute', inset: 0, background: 'rgba(11,12,15,0.92)',
            backdropFilter: 'blur(14px)', zIndex: 60, padding: 18, overflowY: 'auto', boxSizing: 'border-box',
          }}>
            <div style={{ fontSize: 10, color: M_FG_DIM, letterSpacing: '0.12em', textTransform: 'uppercase', fontWeight: 600, marginBottom: 10 }}>Pinned · Ajna apps</div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 20 }}>
              {pinnedTabs.map(t => (
                <div key={t.id} onClick={(e) => { e.stopPropagation(); choose(t.id); }} style={{ padding: 14, background: t.bg, border: '1px solid ' + M_BORDER, borderRadius: 14, position: 'relative' }}>
                  <span style={{ color: M_ACCENT_B }}>{t.icon({ s: 22 })}</span>
                  <div style={{ fontSize: 13, fontWeight: 600, marginTop: 10 }}>{t.label}</div>
                  <div style={{ fontSize: 10, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace', marginTop: 2 }}>ajna://{t.id}</div>
                  {t.badge && <span style={{ position: 'absolute', top: 10, right: 10, minWidth: 18, height: 18, padding: '0 5px', borderRadius: 9, background: M_ACCENT_B, color: '#0B0C0F', fontSize: 10, fontWeight: 700, display: 'grid', placeItems: 'center' }}>{t.badge}</span>}
                </div>
              ))}
            </div>
            <div style={{ fontSize: 10, color: M_FG_DIM, letterSpacing: '0.12em', textTransform: 'uppercase', fontWeight: 600, marginBottom: 10 }}>Web tabs · 3</div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
              {webTabs.map(t => (
                <div key={t.id} onClick={(e) => { e.stopPropagation(); choose('ntp'); }} style={{ aspectRatio: '3/4', background: M_SURFACE, border: '1px solid ' + M_BORDER, borderRadius: 12, overflow: 'hidden' }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 6, padding: 8, borderBottom: '1px solid ' + M_BORDER_SOFT }}>
                    <MTile size={14} bg={t.bg} color="#fff" label={t.fav} radius={3}/>
                    <span style={{ fontSize: 9, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace' }}>{t.url}</span>
                  </div>
                  <div style={{ padding: 8, fontSize: 11 }}>{t.label}</div>
                </div>
              ))}
            </div>
            <div style={{ marginTop: 20, textAlign: 'center', fontSize: 11, color: M_FG_DIM }}>Long-press any tab to pin · tap a pinned app to open</div>
          </div>
        )}
      </div>

      {screen !== 'thread' && screen !== 'thread-empty' && !focus && (
        <div style={{ padding: '8px 16px', display: 'flex', gap: 8, alignItems: 'center', borderTop: '1px solid ' + M_BORDER_SOFT }}>
          <button onClick={() => setScreen('ntp')} style={iconBtn(false)}>{MIc.back({ s: 20 })}</button>
          <div style={{ flex: 1 }} onClick={() => setFocus(true)}><MAddressBar url={'ajna://' + (screen === 'ntp' ? 'newtab' : screen)}/></div>
          <button onClick={() => setSwitcher(true)} style={iconBtn(false)}>
            <div style={{ position: 'relative' }}>
              {MIc.tabs({ s: 20 })}
              <span style={{ position: 'absolute', top: -3, right: -6, fontSize: 8, fontWeight: 700, background: M_ACCENT_B, color: '#0B0C0F', borderRadius: 5, padding: '1px 3px' }}>7</span>
            </div>
          </button>
        </div>
      )}
      <MHomeIndicator/>
    </MobileScreen>
  );
}

// Mobile back-button with long-press → history popover (forward + recent pages)
// Tap = back. Long-press (380ms) = open history sheet with forward + recents.
function MNavBack({ screen, onGoHome }) {
  const [open, setOpen] = React.useState(false);
  const timer = React.useRef(null);
  const wasLongPress = React.useRef(false);
  const start = () => { wasLongPress.current = false; timer.current = setTimeout(() => { wasLongPress.current = true; setOpen(true); }, 380); };
  const stop  = () => { if (timer.current) clearTimeout(timer.current); };
  const onClick = () => {
    if (wasLongPress.current) return; // long-press already opened the menu
    if (screen && screen !== 'ntp' && onGoHome) onGoHome();
  };

  const isOnNtp = screen === 'ntp';

  const history = [
    { dir: 'back',    title: 'ajna://newtab',                          time: 'now', icon: MIc.home },
    { dir: 'back',    title: 'linear.app/ajna-inc/inbox',              time: '2m',  icon: MIc.globe },
    { dir: 'back',    title: 'github.com/ajna-inc/browser/pull/284',   time: '8m',  icon: MIc.globe },
    { dir: 'forward', title: 'notion.so/p2p-sync',                     time: '12m', icon: MIc.globe },
  ];

  return (
    <>
      <button
        onClick={onClick}
        onTouchStart={start} onTouchEnd={stop} onTouchMove={stop}
        onMouseDown={start} onMouseUp={stop} onMouseLeave={stop}
        onContextMenu={(e) => { e.preventDefault(); setOpen(true); }}
        style={{ ...iconBtn(false), opacity: isOnNtp ? 0.45 : 1 }} aria-label={isOnNtp ? 'No back' : 'Back to home'}
      >
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m15 18-6-6 6-6"/></svg>
      </button>
      {open && (
        <>
          <div onClick={() => setOpen(false)} style={{ position: 'absolute', inset: 0, zIndex: 70, background: 'rgba(0,0,0,0.4)', backdropFilter: 'blur(6px)' }}/>
          <div style={{
            position: 'absolute', left: 8, right: 8, bottom: 72, zIndex: 71,
            background: M_SURFACE, border: '1px solid ' + M_BORDER,
            borderRadius: 14, padding: '6px 0',
            boxShadow: '0 -10px 40px rgba(0,0,0,0.5)',
            animation: 'mNavBackFade 200ms ease',
          }}>
            <style>{`@keyframes mNavBackFade { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }`}</style>
            <div style={{ fontSize: 9.5, fontWeight: 700, color: M_FG_DIM, letterSpacing: '0.14em', textTransform: 'uppercase', padding: '8px 14px 4px' }}>History</div>
            {history.map((h, i) => (
              <button key={i} onClick={() => setOpen(false)} style={{
                display: 'flex', alignItems: 'center', gap: 10, width: '100%',
                padding: '10px 14px', background: 'transparent', border: 0,
                color: M_FG, cursor: 'pointer', textAlign: 'left', fontFamily: 'inherit',
                borderBottom: i < history.length - 1 ? '1px solid ' + M_BORDER_SOFT : 'none',
              }}>
                <span style={{ color: h.dir === 'forward' ? M_ACCENT_B : M_FG_MUTED, display: 'grid', placeItems: 'center', width: 18, flexShrink: 0 }}>
                  {h.dir === 'forward'
                    ? <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m9 6 6 6-6 6"/></svg>
                    : <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m15 18-6-6 6-6"/></svg>
                  }
                </span>
                <span style={{ flex: 1, fontSize: 12.5, fontWeight: 500, fontFamily: 'JetBrains Mono, monospace', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{h.title}</span>
                <span style={{ fontSize: 10, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace' }}>{h.time}</span>
              </button>
            ))}
            <div style={{ height: 1, margin: '4px 8px', background: M_BORDER_SOFT }}/>
            <div style={{ fontSize: 10.5, color: M_FG_DIM, padding: '8px 14px 10px', textAlign: 'center', fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.05em' }}>
              Tap ← for back · Long-press for history · Swipe left edge to go back
            </div>
          </div>
        </>
      )}
    </>
  );
}

// ═══════════════════════════════════════════════════════════
// Single pill at bottom. Tap opens full-sheet with search, chips, recents.
// Everything lives in the sheet.
// ═══════════════════════════════════════════════════════════
function NavOptionCommand({ screen, setScreen, activePeer, setActivePeer, showAdd, setShowAdd, privateMode, setPrivateMode, activeGroupId, setActiveGroupId, activeCall, setActiveCall, incomingCall, setIncomingCall }) {
  const [sheet, setSheet] = React.useState(false);
  const [pillSheet, setPillSheet] = React.useState(false);
  const addOpen = !!showAdd;
  const setAddOpen = (v) => setShowAdd && setShowAdd(v);
  const [focus, setFocus] = React.useState(screen === 'typing' || screen === 'typing-results');
  // Swipe-up on the center pill → page-actions sheet; plain tap → search focus
  const pillGesture = React.useRef(null);
  const pillHandlers = {
    onPointerDown: (e) => { pillGesture.current = { x: e.clientX, y: e.clientY }; try { e.currentTarget.setPointerCapture(e.pointerId); } catch {} },
    onPointerUp: (e) => { const t = pillGesture.current; pillGesture.current = null; if (!t) return; if (t.y - e.clientY > 24) setPillSheet('menu'); else openFocus(); },
    onPointerCancel: () => { pillGesture.current = null; },
  };

  // Page-level overlays (Find / Zoom / Page info / Clear / Reader / Voice /
  // Permission prompt / Sad tab / Privacy review). Stored as state on the
  // command variant so they render above whatever screen is active.
  const [overlay, setOverlay] = React.useState(null); // 'find'|'zoom'|'page-info'|...
  const [zoom, setZoom] = React.useState(100);
  const [callsView, setCallsView] = React.useState('empty'); // 'empty' | 'history'
  // Identity gating — '0' means the user skipped setup in the FRE; chat/calls
  // stay locked behind MIdentityGate until MIdentitySetupFlow completes.
  const [identityReady, setIdentityReady] = React.useState(() => {
    try { return localStorage.getItem('ajna-identity-ready') !== '0'; } catch { return true; }
  });
  const [identitySetup, setIdentitySetup] = React.useState(false);
  const [loadSite, setLoadSite] = React.useState(null); // site being loaded on 'page-loading'
  const [pagerTab, setPagerTab] = React.useState('chat'); // 'chat' | 'calls' for the Chat/Calls pager
  React.useEffect(() => { if (screen === 'typing' || screen === 'typing-results') setFocus(true); }, [screen]);

  const openFocus = () => setFocus(true);
  const closeFocus = () => { setFocus(false); if (screen === 'typing' || screen === 'typing-results') setScreen('ntp'); };
  const APP_SCREENS_NAV = ['chat', 'mesh', 'tabs', 'files', 'calls', 'settings', 'bookmarks', 'history', 'downloads', 'passwords', 'reading-list', 'permissions', 'help', 'credits', 'recently-closed'];
  // Actions that open a transient overlay (Find/Zoom/Page info/Clear data/
  // Reader/Voice/Privacy review/Sad tab). These don't change the screen.
  const OVERLAY_IDS = ['find', 'zoom', 'page-info', 'clear', 'reader', 'voice', 'privacy-review', 'sad-tab', 'permission-prompt'];
  const navAndClose = (id) => {
    if (APP_SCREENS_NAV.includes(id)) { setPrivateMode && setPrivateMode(false); setScreen(id); }
    else if (id === 'new-tab')        { setPrivateMode && setPrivateMode(false); setScreen('ntp'); }
    else if (id === 'new-private')    { setPrivateMode && setPrivateMode(true);  setScreen('private-ntp'); }
    else if (id === 'exit-private')   { setPrivateMode && setPrivateMode(false); setScreen('ntp'); }
    else if (id === 'reopen')         { setScreen('recently-closed'); }
    else if (OVERLAY_IDS.includes(id)) { setOverlay(id); }
    else if (id === 'scan' || id === 'ai') { /* stub */ }
    // Other page-stub ids (reload, bookmark-page, copy-url, share, translate,
    // request-desktop, pin-tab, pip, add-home, save-pdf, mute-tab, print)
    // are no-ops in this prototype.
    setFocus(false);
  };

  const chips = [
    { id: 'chat',   label: 'Chat',     icon: MIc.chat,   color: M_ACCENT_B, badge: 3 },
    { id: 'mesh',   label: 'Mesh',     icon: MIc.mesh,   color: '#A78BFA', hint: '3' },
    { id: 'tabs',   label: 'Tabs',     icon: MIc.tabs,   color: M_FG, hint: '5' },
    { id: 'files',  label: 'Files',    icon: MIc.files,  color: '#FBBF24' },
    { id: 'calls',  label: 'Calls',    icon: MIc.calls,  color: '#F472B6' },
    { id: 'scan',   label: 'Scan',     icon: MIc.scan,   color: '#FBBF24' },
    { id: 'ai',     label: 'Ask AI',   icon: MIc.ai,     color: '#22D3EE' },
  ];

  const APP_SCREENS = ['chat', 'mesh', 'tabs', 'files', 'calls', 'settings'];
  const choose = (id) => {
    if (APP_SCREENS.includes(id)) setScreen(id);
    setSheet(false);
  };

  return (
    <MobileScreen>
      <MStatusBar/>
      <div style={{ flex: 1, overflow: 'hidden', position: 'relative' }}>
        {(screen === 'ntp' || screen === 'typing' || screen === 'typing-results') && <MScreenNTP onOpenSearch={openFocus} onOpenSite={(r) => { setLoadSite(r); setScreen('page-loading'); }}/>}
        {screen === 'page-loading' && <MScreenPageLoading site={loadSite}/>}
        {screen === 'tabs' && <MScreenTabsWithModes
          onEnterPrivate={() => { setPrivateMode && setPrivateMode(true); setScreen('private-ntp'); }}
          onOpenGroup={(id) => { setActiveGroupId && setActiveGroupId(id); setScreen('group-detail'); }}
          onNewGroup={() => {}}
        />}
        {screen === 'group-detail' && <MScreenGroupDetail groupId={activeGroupId} onBack={() => setScreen('tabs')}/>}
        {screen === 'private-ntp' && <MScreenPrivateNTP onOpenSearch={openFocus}/>}
        {screen === 'private-tabs' && <MScreenPrivateTabs onExitPrivate={() => { setPrivateMode && setPrivateMode(false); setScreen('ntp'); }}/>}
        {screen === 'chat' && (identityReady ? <MChatCallsPager
          tab={pagerTab}
          onTabChange={setPagerTab}
          onOpenChat={(p) => { setActivePeer(p); setScreen('thread'); }}
          onAdd={() => setAddOpen('handle')}
          onCall={(c, kind) => setActiveCall && setActiveCall({ caller: c || M_CALL_LOG[0], kind })}
          onIncomingDemo={() => setIncomingCall && setIncomingCall({ caller: M_CALL_LOG[0], kind: 'video' })}
        /> : <MIdentityGate onSetup={() => setIdentitySetup(true)}/>)}
        {screen === 'chat-empty' && <MScreenChatListEmpty onAdd={(mode) => setAddOpen(mode || 'handle')}/>}
        {screen === 'thread' && <MScreenChat peer={activePeer} onBack={() => setScreen('chat')} onCall={(c, kind) => setActiveCall && setActiveCall({ caller: c, kind })}/>}
        {screen === 'thread-empty' && <MScreenChat peer={activePeer} empty onBack={() => setScreen('chat-empty')} onCall={(c, kind) => setActiveCall && setActiveCall({ caller: c, kind })}/>}
        {screen === 'mesh' && <MEmpty icon={MIc.mesh} title="Mesh · 3 peers"/>}
        {screen === 'calls' && !identityReady && <MIdentityGate onSetup={() => setIdentitySetup(true)}/>}
        {screen === 'calls' && identityReady && (callsView === 'empty'
          ? <MScreenCallsEmpty
              onCall={(c, kind) => setActiveCall({ caller: c || M_CALL_LOG[0], kind })}
              onShowHistory={() => setCallsView('history')}
            />
          : <MScreenCalls
              onCall={(c, kind) => setActiveCall({ caller: c || M_CALL_LOG[0], kind })}
              onIncomingDemo={() => setIncomingCall({ caller: M_CALL_LOG[0], kind: 'video' })}
              onShowEmpty={() => setCallsView('empty')}
            />
        )}
        {addOpen && <MScreenAddConnection mode={showAdd} onClose={() => setAddOpen(null)}/>}
        {screen === 'files' && <MEmpty icon={MIc.files} title="Files"/>}
        {screen === 'settings' && <MScreenSettings/>}
        {screen === 'history'         && <MScreenHistory         onOpen={() => { setPrivateMode && setPrivateMode(false); setScreen('ntp'); }}/>}
        {screen === 'bookmarks'       && <MScreenBookmarks       onOpen={() => { setPrivateMode && setPrivateMode(false); setScreen('ntp'); }}/>}
        {screen === 'downloads'       && <MScreenDownloads       onOpen={() => {}}/>}
        {screen === 'recently-closed' && <MScreenRecentlyClosed  onOpen={() => { setPrivateMode && setPrivateMode(false); setScreen('ntp'); }}/>}
        {screen === 'passwords'       && <MScreenPasswords/>}
        {screen === 'reading-list'    && <MScreenReadingList     onOpen={() => setOverlay('reader')}/>}
        {screen === 'permissions'     && <MScreenSitePermissions/>}
        {screen === 'help'            && <MScreenHelp/>}
        {screen === 'credits'         && <MScreenCredits/>}

        {focus && <MCommandFocus key={screen === 'typing-results' ? 'tr' : 'tf'} initialQuery={screen === 'typing-results' ? 'mesh' : ''} onClose={closeFocus} onNavigate={navAndClose} isPrivate={screen === 'private-ntp' || screen === 'private-tabs'}/>}

        {sheet && (
          <>
            <div onClick={() => setSheet(false)} style={{ position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.6)', backdropFilter: 'blur(6px)', zIndex: 50 }}/>
            <div style={{
              position: 'absolute', left: 0, right: 0, bottom: 0,
              background: M_SURFACE, borderTop: '1px solid ' + M_BORDER,
              borderRadius: '22px 22px 0 0', padding: '12px 18px 28px',
              zIndex: 51, animation: 'slideUp 260ms cubic-bezier(0.2,0.8,0.2,1)',
            }}>
              <style>{`@keyframes slideUp{from{transform:translateY(100%)}to{transform:translateY(0)}}`}</style>
              <div style={{ width: 40, height: 4, borderRadius: 2, background: M_FG_DIM, margin: '0 auto 14px' }}/>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '12px 14px', background: M_BG, borderRadius: 12, border: '1px solid ' + M_BORDER_SOFT, marginBottom: 16 }}>
                <span style={{ color: M_FG_DIM }}>{MIc.search({ s: 16 })}</span>
                <span style={{ flex: 1, fontSize: 14, color: M_FG_MUTED }}>Search, ask AI, pay, or type URL</span>
                <span style={{ color: M_FG_DIM }}>{MIc.mic({ s: 16 })}</span>
              </div>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8, marginBottom: 18 }}>
                {chips.map(c => (
                  <button key={c.id} onClick={() => choose(c.id)} style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 8, padding: '12px 12px', background: M_BG, border: '1px solid ' + M_BORDER_SOFT, borderRadius: 12, color: M_FG, position: 'relative' }}>
                    <span style={{ color: c.color }}>{c.icon({ s: 18 })}</span>
                    <div style={{ fontSize: 12, fontWeight: 500 }}>{c.label}</div>
                    {c.badge && <span style={{ position: 'absolute', top: 8, right: 8, minWidth: 16, height: 16, padding: '0 4px', borderRadius: 8, background: c.color, color: '#0B0C0F', fontSize: 9.5, fontWeight: 700, display: 'grid', placeItems: 'center' }}>{c.badge}</span>}
                    {c.hint && <span style={{ position: 'absolute', top: 10, right: 10, fontSize: 9.5, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace' }}>{c.hint}</span>}
                  </button>
                ))}
              </div>
              <div style={{ fontSize: 10, color: M_FG_DIM, letterSpacing: '0.12em', textTransform: 'uppercase', fontWeight: 600, marginBottom: 8 }}>Recent</div>
              {['linear.app/inbox', 'github.com/ajna-inc/browser', 'notion.so/p2p-sync'].map(u => (
                <div key={u} onClick={() => { setScreen('ntp'); setSheet(false); }} style={{ padding: '10px 2px', fontSize: 13, fontFamily: 'JetBrains Mono, monospace', color: M_FG_MUTED, borderBottom: '1px solid ' + M_BORDER_SOFT, display: 'flex', alignItems: 'center', gap: 8 }}>
                  <span style={{ color: M_FG_DIM }}>{MIc.globe({ s: 12 })}</span>{u}
                </div>
              ))}
            </div>
          </>
        )}

        {/* Page-level overlays — Arc-style, surface from menu sheet or pill */}
        {overlay === 'find'              && <MFindInPage          onClose={() => setOverlay(null)}/>}
        {overlay === 'zoom'              && <MZoomControl         value={zoom} onChange={setZoom} onClose={() => setOverlay(null)}/>}
        {overlay === 'page-info'         && <MPageInfo            onClose={() => setOverlay(null)}/>}
        {overlay === 'clear'             && <MClearDataSheet      onClose={() => setOverlay(null)}/>}
        {overlay === 'reader'            && <MReader              onClose={() => setOverlay(null)}/>}
        {overlay === 'voice'             && <MVoiceSearch         onClose={() => setOverlay(null)} onCommit={() => setOverlay(null)}/>}
        {overlay === 'privacy-review'    && <MPrivacyReview       onClose={() => setOverlay(null)}/>}
        {overlay === 'sad-tab'           && <MSadTab              onClose={() => setOverlay(null)}/>}
        {overlay === 'permission-prompt' && <MPermissionPrompt    onResolve={() => setOverlay(null)}/>}

        {/* Swipe-up page-actions sheet from the center pill */}
        {pillSheet && <MPillPageSheet
          startEditing={pillSheet === 'edit'}
          url={loadSite ? loadSite.u : (screen === 'ntp' || screen === 'typing' ? 'ajna://newtab' : 'ajna://' + screen)}
          zoom={zoom} setZoom={setZoom}
          onClose={() => setPillSheet(false)}
          onAction={(id) => {
            setPillSheet(false);
            if (id === 'find') setOverlay('find');
            else if (id === 'site-settings') setScreen('permissions');
            else if (id === 'back') { setPrivateMode && setPrivateMode(false); setScreen('ntp'); }
          }}
        />}

        {/* In-app identity setup — launched from MIdentityGate */}
        {identitySetup && <MIdentitySetupFlow
          onComplete={() => { setIdentitySetup(false); setIdentityReady(true); }}
          onCancel={() => setIdentitySetup(false)}
        />}

      </div>

      {/* tabs tray: single glass "+" square instead of the full command bar */}
      {screen === 'tabs' && !focus && (
        <div style={{ position: 'absolute', left: 0, right: 0, bottom: 47, zIndex: 55, padding: '10px 12px 4px', display: 'flex', justifyContent: 'center', pointerEvents: 'none' }}>
          <button onClick={() => setScreen('ntp')} className="glass" aria-label="New tab" style={{ position: 'relative', width: 58, height: 58, borderRadius: 20, display: 'grid', placeItems: 'center', color: M_FG, cursor: 'pointer', pointerEvents: 'auto', fontFamily: 'inherit', background: 'linear-gradient(150deg, rgba(255,255,255,0.20), rgba(255,255,255,0.05) 46%, rgba(255,255,255,0.11))', backdropFilter: 'blur(var(--glass-blur)) saturate(1.7)', WebkitBackdropFilter: 'blur(var(--glass-blur)) saturate(1.7)', border: '1px solid var(--glass-border)', boxShadow: 'inset 0 1px 0 var(--glass-highlight), inset 0 -1px 0 rgba(255,255,255,0.06), 0 10px 26px rgba(0,0,0,0.45)', overflow: 'hidden' }}>
            <span style={{ position: 'absolute', inset: 0, borderRadius: 20, background: 'radial-gradient(120% 80% at 22% 8%, rgba(255,255,255,0.28), transparent 58%)', pointerEvents: 'none' }}/>
            <svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" style={{ position: 'relative', filter: 'drop-shadow(0 1px 1px rgba(0,0,0,0.5))' }}><path d="M12 5v14M5 12h14"/></svg>
          </button>
        </div>
      )}

      {/* bottom command bar — floating glass bubbles overlaid on content */}
      {screen !== 'thread' && screen !== 'thread-empty' && screen !== 'private-ntp' && screen !== 'private-tabs' && screen !== 'tabs' && !focus && (
        <div style={{ position: 'absolute', left: 0, right: 0, bottom: 26, zIndex: 55, padding: '10px 12px 4px', display: 'flex', gap: 8, alignItems: 'center', background: 'transparent', pointerEvents: 'none' }}>
          <div className="glass" style={{ display: 'flex', alignItems: 'center', borderRadius: 999, padding: '2px 4px', flexShrink: 0, pointerEvents: 'auto' }}>
            <button onClick={() => screen === 'chat' ? setPagerTab(pagerTab === 'chat' ? 'calls' : 'chat') : setScreen('chat')} style={{ ...iconBtn(screen === 'chat'), overflow: 'visible' }} aria-label={screen === 'chat' ? (pagerTab === 'chat' ? 'Switch to Calls' : 'Switch to Messages') : 'Chat'}>
              <div style={{ position: 'relative', display: 'grid', placeItems: 'center' }}>
                {(screen === 'chat' && pagerTab === 'chat') ? MIc.calls({ s: 20 }) : MIc.chat({ s: 20 })}
                <span style={{ position: 'absolute', top: -13, right: -11, minWidth: 15, height: 15, padding: '0 4px', borderRadius: 8, background: (screen === 'chat' && pagerTab === 'chat') ? '#F87171' : M_ACCENT_B, color: '#0B0C0F', fontSize: 9, fontWeight: 700, display: 'grid', placeItems: 'center', boxShadow: '0 2px 6px rgba(0,0,0,0.4)', zIndex: 2 }}>{(screen === 'chat' && pagerTab === 'chat') ? 2 : 3}</span>
              </div>
            </button>
          </div>
          {screen === 'page-loading' ? (
            <div style={{ flex: 1, position: 'relative', borderRadius: 999, padding: 2, overflow: 'hidden', minWidth: 0, pointerEvents: 'auto' }}>
              <style>{`@keyframes mPillSpin{to{transform:translate(-50%,-50%) rotate(360deg)}}`}</style>
              <div style={{ position: 'absolute', left: '50%', top: '50%', width: 420, height: 420, transform: 'translate(-50%,-50%)', background: 'conic-gradient(from 0deg, transparent 0 55%, ' + M_ACCENT + ' 72%, ' + M_ACCENT_B + ' 88%, transparent 100%)', animation: 'mPillSpin 1.3s linear infinite' }}/>
              <button {...pillHandlers} className="glass" style={{
                position: 'relative', width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
                padding: '12px 16px', borderRadius: 999, boxSizing: 'border-box',
                color: M_FG, cursor: 'pointer', minWidth: 0, fontFamily: 'inherit', touchAction: 'none',
              }}>
                <span style={{ color: M_FG_MUTED, flexShrink: 0 }}>{MIc.shield({ s: 14 })}</span>
                <span style={{ fontSize: 13, color: M_FG, fontFamily: 'JetBrains Mono, monospace', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{(loadSite && loadSite.u) || 'firstpost.com'}</span>
              </button>
            </div>
          ) : (
          <button {...pillHandlers} className="glass" style={{
            flex: 1, display: 'flex', alignItems: 'center', gap: 10,
            padding: '12px 16px', borderRadius: 999,
            color: M_FG, cursor: 'pointer', minWidth: 0, fontFamily: 'inherit', pointerEvents: 'auto', touchAction: 'none',
          }}>
            <span style={{ color: M_ACCENT_B, flexShrink: 0 }}>{MIc.search({ s: 16 })}</span>
            <span style={{ flex: 1, textAlign: 'left', fontSize: 13, color: M_FG_MUTED, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>Search or do anything</span>
          </button>
          )}
          <div className="glass" style={{ display: 'flex', alignItems: 'center', gap: 2, borderRadius: 999, padding: '2px 4px', flexShrink: 0, pointerEvents: 'auto' }}>
            <MNavBack screen={screen} onGoHome={() => { setPrivateMode && setPrivateMode(false); setActiveGroupId && setActiveGroupId(null); setShowAdd && setShowAdd(null); setScreen('ntp'); }}/>
            <div style={{ width: 1, height: 20, background: 'var(--glass-border)', flexShrink: 0 }}/>
            <button onClick={() => setScreen(screen === 'tabs' ? 'ntp' : 'tabs')} style={{ ...iconBtn(screen === 'tabs'), overflow: 'visible' }} aria-label={screen === 'tabs' ? 'Back to web' : 'Tabs'}>
              <div style={{ position: 'relative' }}>
                {MIc.tabs({ s: 20 })}
                <span style={{ position: 'absolute', top: -12, right: -10, minWidth: 15, height: 15, padding: '0 4px', borderRadius: 8, background: M_FG, color: '#0B0C0F', fontSize: 9, fontWeight: 700, display: 'grid', placeItems: 'center', boxShadow: '0 2px 6px rgba(0,0,0,0.4)', zIndex: 2 }}>5</span>
              </div>
            </button>
          </div>
        </div>
      )}
      {screen !== 'thread' && screen !== 'thread-empty' && screen !== 'private-ntp' && screen !== 'private-tabs' && !focus && <MHomeIndicator/>}

      {/* Private mode bottom bar — violet themed, simpler (no chat/mesh in private) */}
      {(screen === 'private-ntp' || screen === 'private-tabs') && !focus && (
        <>
          <div style={{ padding: '10px 12px 4px', display: 'flex', gap: 6, alignItems: 'center', borderTop: '1px solid ' + PRIV_BORDER_SOFT, background: 'rgba(14,11,23,0.85)' }}>
            <button onClick={() => setScreen('private-ntp')} style={{
              width: 40, height: 40, borderRadius: 12,
              background: screen === 'private-ntp' ? 'rgba(167,139,250,0.18)' : 'transparent',
              border: 0, color: screen === 'private-ntp' ? PRIV_ACCENT_2 : PRIV_FG_MUTED,
              display: 'grid', placeItems: 'center', cursor: 'pointer', flexShrink: 0,
            }} aria-label="Private home">{MIc.home({ s: 20 })}</button>
            <button onClick={openFocus} style={{
              flex: 1, display: 'flex', alignItems: 'center', gap: 10,
              padding: '12px 16px', borderRadius: 999,
              background: PRIV_SURFACE, border: '1px solid ' + PRIV_BORDER,
              color: PRIV_FG, cursor: 'pointer', minWidth: 0,
            }}>
              <span style={{ color: PRIV_ACCENT, flexShrink: 0 }}><IcMask s={13}/></span>
              <span style={{ flex: 1, textAlign: 'left', fontSize: 13, color: PRIV_FG_MUTED, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>Search privately</span>
              <span style={{ fontSize: 10, color: PRIV_FG_DIM, fontFamily: 'JetBrains Mono, monospace', flexShrink: 0 }}>⌘K</span>
            </button>
            <button onClick={() => setScreen('private-tabs')} style={{
              width: 40, height: 40, borderRadius: 12,
              background: screen === 'private-tabs' ? 'rgba(167,139,250,0.18)' : 'transparent',
              border: 0, color: screen === 'private-tabs' ? PRIV_ACCENT_2 : PRIV_FG_MUTED,
              display: 'grid', placeItems: 'center', cursor: 'pointer', flexShrink: 0,
            }} aria-label="Private tabs">
              <div style={{ position: 'relative' }}>
                {MIc.tabs({ s: 20 })}
                <span style={{ position: 'absolute', top: -3, right: -6, fontSize: 8, fontWeight: 700, background: PRIV_ACCENT, color: '#0B0C0F', borderRadius: 5, padding: '1px 3px' }}>3</span>
              </div>
            </button>
            <button onClick={() => { setPrivateMode && setPrivateMode(false); setScreen('ntp'); }} style={{
              width: 40, height: 40, borderRadius: 12, background: 'transparent', border: 0,
              color: PRIV_FG_MUTED, display: 'grid', placeItems: 'center', cursor: 'pointer', flexShrink: 0,
            }} aria-label="Exit private">
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M21 14v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5"/></svg>
            </button>
          </div>
          <MHomeIndicator light/>
        </>
      )}
    </MobileScreen>
  );
}

// ─── Page-loading screen — webpage skeleton while the pill loader spins ──
function MScreenPageLoading({ site }) {
  const s = site || { t: 'Firstpost', u: 'firstpost.com', bg: '#DC2626', glyph: 'F' };
  const line = (w, h = 12) => (
    <div style={{ width: w, height: h, borderRadius: 6, background: 'rgba(255,255,255,0.06)', position: 'relative', overflow: 'hidden' }}>
      <div className="mldg-sheen" style={{ position: 'absolute', inset: 0, background: 'linear-gradient(90deg, transparent, rgba(255,255,255,0.07), transparent)' }}/>
    </div>
  );
  return (
    <div style={{ height: '100%', overflow: 'hidden', padding: '18px 20px 120px', boxSizing: 'border-box' }}>
      <style>{`@keyframes mldgSheen{from{transform:translateX(-100%)}to{transform:translateX(100%)}}.mldg-sheen{animation:mldgSheen 1.4s ease-in-out infinite}`}</style>
      {/* Site identity while connecting */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 18 }}>
        <MFav site={s} size={34} radius={9}/>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 13.5, fontWeight: 600, color: M_FG, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.01em' }}>{s.t}</div>
          <div style={{ fontSize: 10, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace', marginTop: 1 }}>Establishing secure connection…</div>
        </div>
        <span style={{ fontSize: 9.5, color: M_ACCENT, fontFamily: 'JetBrains Mono, monospace', display: 'inline-flex', alignItems: 'center', gap: 5 }}>
          <span style={{ width: 5, height: 5, borderRadius: 3, background: M_ACCENT, boxShadow: '0 0 6px ' + M_ACCENT }}/>TLS 1.3
        </span>
      </div>
      {/* Hero skeleton */}
      <div style={{ width: '100%', height: 170, borderRadius: 14, background: 'rgba(255,255,255,0.05)', position: 'relative', overflow: 'hidden', marginBottom: 16 }}>
        <div className="mldg-sheen" style={{ position: 'absolute', inset: 0, background: 'linear-gradient(90deg, transparent, rgba(255,255,255,0.06), transparent)' }}/>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10, marginBottom: 22 }}>
        {line('88%', 16)}{line('70%', 16)}{line('45%')}
      </div>
      {[0, 1, 2].map(i => (
        <div key={i} style={{ display: 'flex', gap: 12, padding: '13px 0', borderBottom: '1px solid ' + M_BORDER_SOFT }}>
          <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 8, paddingTop: 3 }}>
            {line('40%', 9)}{line('92%')}{line('60%')}
          </div>
          <div style={{ width: 68, height: 68, borderRadius: 10, background: 'rgba(255,255,255,0.05)', flexShrink: 0, position: 'relative', overflow: 'hidden' }}>
            <div className="mldg-sheen" style={{ position: 'absolute', inset: 0, background: 'linear-gradient(90deg, transparent, rgba(255,255,255,0.06), transparent)' }}/>
          </div>
        </div>
      ))}
    </div>
  );
}

// Shared tiny empty-state
function MEmpty({ icon, title }) {
  return (
    <div style={{ height: '100%', display: 'grid', placeItems: 'center', color: M_FG_MUTED, padding: 40, textAlign: 'center' }}>
      <div>
        <div style={{ opacity: 0.4, marginBottom: 12 }}>{icon({ s: 36 })}</div>
        <div style={{ fontSize: 15, fontFamily: 'Geist' }}>{title}</div>
      </div>
    </div>
  );
}

// Library screens — reused for Bookmarks / History / Downloads so the menu's
// items actually OPEN something instead of being stubs.
const M_LIB_DATA = {
  bookmarks: {
    title: 'Bookmarks',
    sub: '12 saved',
    icon: (p) => <svg width={p?.s||18} height={p?.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M19 21V5a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v16l7-4z"/></svg>,
    folders: [
      { name: 'Work', count: 5 },
      { name: 'Reading', count: 4 },
      { name: 'Daily', count: 3 },
    ],
    items: [
      { title: 'Linear — Inbox',        url: 'linear.app/inbox',                  fav: 'L', bg: '#5E6AD2', folder: 'Work' },
      { title: 'Ajna Browser',          url: 'github.com/ajna-inc/browser',       fav: 'G', bg: '#24292F', folder: 'Work' },
      { title: 'P2P Sync RFC',          url: 'notion.so/p2p-sync',                fav: 'N', bg: '#fff',    c: '#000', folder: 'Reading' },
      { title: 'DIDComm Spec',          url: 'identity.foundation/didcomm',       fav: 'D', bg: '#7C3AED', folder: 'Reading' },
      { title: 'Hacker News',           url: 'news.ycombinator.com',              fav: 'Y', bg: '#FF6600', folder: 'Daily' },
      { title: 'Hypermedia Protocol',   url: 'hyper.media',                       fav: 'H', bg: '#0F172A', folder: 'Reading' },
      { title: 'UCAN Spec',             url: 'ucan.xyz',                          fav: 'U', bg: '#1E40AF', folder: 'Reading' },
      { title: 'Linear · Triage',       url: 'linear.app/ajna/triage',            fav: 'L', bg: '#5E6AD2', folder: 'Work' },
      { title: 'Posthog Dashboard',     url: 'us.posthog.com/dashboard/ajna',     fav: 'P', bg: '#1D4ED8', folder: 'Work' },
      { title: 'Tailwind Docs',         url: 'tailwindcss.com/docs',              fav: 'T', bg: '#0EA5E9', folder: 'Work' },
      { title: 'iA Writer',             url: 'ia.net/writer',                     fav: 'i', bg: '#000',    folder: 'Daily' },
      { title: 'Cloudflare Status',     url: 'cloudflarestatus.com',              fav: 'C', bg: '#F38020', folder: 'Daily' },
    ],
  },
  history: {
    title: 'History',
    sub: 'Today',
    icon: (p) => <svg width={p?.s||18} height={p?.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M3 12a9 9 0 1 0 3-6.7L3 9"/><path d="M3 3v6h6"/><path d="M12 7v5l3 2"/></svg>,
    items: [
      { title: 'Linear — Inbox',        url: 'linear.app/inbox',                    fav: 'L', bg: '#5E6AD2', time: '12 min ago' },
      { title: 'Ajna Browser PRs',      url: 'github.com/ajna-inc/browser/pulls',   fav: 'G', bg: '#24292F', time: '34 min ago' },
      { title: 'P2P Sync RFC',          url: 'notion.so/p2p-sync',                  fav: 'N', bg: '#fff', c: '#000', time: '1 hr ago' },
      { title: 'DIDComm Spec',          url: 'identity.foundation/didcomm',         fav: 'D', bg: '#7C3AED', time: '2 hr ago' },
      { title: 'Stripe Dashboard',      url: 'dashboard.stripe.com',                fav: 'S', bg: '#635BFF', time: '3 hr ago' },
      { title: 'Hacker News',           url: 'news.ycombinator.com',                fav: 'Y', bg: '#FF6600', time: '4 hr ago' },
      { title: 'Cloudflare D1 Pricing', url: 'developers.cloudflare.com/d1',        fav: 'C', bg: '#F38020', time: 'Yesterday' },
      { title: 'iA Writer',             url: 'ia.net/writer',                       fav: 'i', bg: '#000',    time: 'Yesterday' },
      { title: 'Tailwind v4 Blog',      url: 'tailwindcss.com/blog/tailwindcss-v4', fav: 'T', bg: '#0EA5E9', time: '2 days ago' },
    ],
  },
  downloads: {
    title: 'Downloads',
    sub: '3 files',
    icon: (p) => <svg width={p?.s||18} height={p?.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M12 3v12M6 11l6 6 6-6M5 21h14"/></svg>,
    items: [
      { title: 'P2P-Sync-RFC.pdf',      url: '1.2 MB · 12 min ago', fav: 'P', bg: '#EF4444' },
      { title: 'didcomm-v2.zip',        url: '6.8 MB · 1 hr ago',   fav: 'Z', bg: '#0EA5E9' },
      { title: 'ajna-keys-backup.kbx',  url: '14 KB · Yesterday',   fav: 'K', bg: '#10B981' },
    ],
  },
};

function MScreenLibrary({ kind, onOpen }) {
  const data = M_LIB_DATA[kind];
  const [q, setQ] = React.useState('');
  const [folder, setFolder] = React.useState('All');
  if (!data) return <MEmpty icon={MIc.files} title={kind}/>;
  const filtered = (data.items || []).filter(it => {
    if (folder !== 'All' && it.folder !== folder) return false;
    if (!q) return true;
    const ql = q.toLowerCase();
    return it.title.toLowerCase().includes(ql) || it.url.toLowerCase().includes(ql);
  });
  return (
    <div style={{ height: '100%', overflowY: 'auto', padding: '20px 16px 100px', boxSizing: 'border-box', color: M_FG }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 14 }}>
        <div style={{
          width: 28, height: 28, borderRadius: 8,
          background: 'var(--m-tint)', border: '1px solid ' + M_BORDER_SOFT,
          color: M_FG, display: 'grid', placeItems: 'center',
        }}>{data.icon({ s: 14 })}</div>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 17, fontWeight: 600, fontFamily: 'Geist', letterSpacing: '-0.02em' }}>{data.title}</div>
          <div style={{ fontSize: 10.5, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace', marginTop: 1 }}>{data.sub}</div>
        </div>
      </div>

      {kind !== 'downloads' && (
        <div style={{
          display: 'flex', alignItems: 'center', gap: 8,
          padding: '8px 12px', marginBottom: 12,
          background: M_SURFACE, border: '1px solid ' + M_BORDER_SOFT, borderRadius: 10,
        }}>
          <span style={{ color: M_FG_DIM }}>{MIc.search({ s: 14 })}</span>
          <input
            value={q}
            onChange={(e) => setQ(e.target.value)}
            placeholder={'Search ' + data.title.toLowerCase() + '…'}
            style={{ flex: 1, background: 'transparent', border: 0, outline: 'none', color: M_FG, fontSize: 12.5, fontFamily: 'inherit' }}
          />
          {q && <button onClick={() => setQ('')} style={{ background: 'transparent', border: 0, color: M_FG_DIM, cursor: 'pointer', padding: 0, fontSize: 11 }}>Clear</button>}
        </div>
      )}

      {kind === 'bookmarks' && data.folders && (
        <div style={{ display: 'flex', gap: 6, overflowX: 'auto', marginBottom: 14, paddingBottom: 4 }}>
          {[{ name: 'All', count: data.items.length }, ...data.folders].map(f => (
            <button key={f.name} onClick={() => setFolder(f.name)} style={{
              flexShrink: 0, padding: '6px 10px', borderRadius: 999,
              background: folder === f.name ? M_FG : 'transparent',
              border: '1px solid ' + (folder === f.name ? M_FG : M_BORDER_SOFT),
              color: folder === f.name ? '#0B0C0F' : M_FG_MUTED,
              fontSize: 11, fontWeight: 500, cursor: 'pointer', fontFamily: 'inherit', whiteSpace: 'nowrap',
            }}>{f.name} <span style={{ opacity: 0.55, marginLeft: 4 }}>{f.count}</span></button>
          ))}
        </div>
      )}

      <div style={{ background: M_SURFACE, border: '1px solid ' + M_BORDER_SOFT, borderRadius: 12, overflow: 'hidden' }}>
        {filtered.length === 0 && (
          <div style={{ padding: '40px 20px', textAlign: 'center', color: M_FG_DIM, fontSize: 12 }}>No matches</div>
        )}
        {filtered.map((it, i) => (
          <div key={it.title + i} onClick={() => onOpen && onOpen(it)} style={{
            display: 'flex', alignItems: 'center', gap: 10,
            padding: '11px 12px',
            borderTop: i === 0 ? 0 : '1px solid ' + M_BORDER_SOFT,
            cursor: 'pointer',
          }}>
            <MTile size={22} bg={it.bg} color={it.c||'#fff'} label={it.fav} radius={5}/>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 12.5, fontWeight: 500, color: M_FG, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{it.title}</div>
              <div style={{ fontSize: 10, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace', marginTop: 1, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                {kind === 'history' && it.time && <span style={{ marginRight: 6, color: M_FG_MUTED }}>{it.time}</span>}
                {it.url}
                {kind === 'bookmarks' && it.folder && <span style={{ marginLeft: 6, color: M_ACCENT_B }}>· {it.folder}</span>}
              </div>
            </div>
            {kind === 'downloads'
              ? <button onClick={(e) => { e.stopPropagation(); }} aria-label="More" style={{ width: 28, height: 28, borderRadius: 6, background: 'var(--m-tint)', border: '1px solid ' + M_BORDER_SOFT, color: M_FG_MUTED, display: 'grid', placeItems: 'center', cursor: 'pointer' }}>{MIc.more({ s: 12 })}</button>
              : <span style={{ color: M_FG_DIM }}>↗</span>}
          </div>
        ))}
      </div>
    </div>
  );
}

const iconBtn = (active) => ({
  width: 40, height: 40, borderRadius: 12,
  background: active ? 'var(--m-tint)' : 'transparent',
  border: 0, color: active ? M_FG : M_FG_MUTED,
  display: 'grid', placeItems: 'center', cursor: 'pointer', flexShrink: 0,
});

// ─── Menu sheet (bottom) ────────────────────────────────────────
// Mirrors the iPad TMoreMenu's structure 1:1 — same sections, same items —
// just rendered as a bottom sheet instead of a popover. Triggered from the
// dedicated Menu button in the bottom command bar (NOT inside the search pill).
function MMenuSheet({ isPrivate, onClose, onAction }) {
  const surface = isPrivate ? '#13101D' : M_SURFACE;
  const border  = isPrivate ? 'rgba(167,139,250,0.20)' : M_BORDER;
  const soft    = isPrivate ? 'rgba(167,139,250,0.14)' : M_BORDER_SOFT;
  const fg      = isPrivate ? '#E9E4FA' : M_FG;
  const fgMuted = isPrivate ? 'rgba(196,181,253,0.62)' : M_FG_MUTED;
  const fgDim   = isPrivate ? 'rgba(196,181,253,0.40)' : M_FG_DIM;
  const accent  = isPrivate ? '#C4B5FD' : M_ACCENT_B;
  const scrim   = isPrivate ? 'rgba(7,5,14,0.65)' : 'rgba(0,0,0,0.6)';
  const privAccent = '#C4B5FD';

  // Same sections as TMoreMenu (tablet-menu.jsx) so the menu is genuinely unified.
  const sections = [
    {
      items: [
        { id: 'new-tab',     icon: MIc.plus({ s: 16 }), label: 'New tab',         short: '⌘ T' },
        isPrivate
          ? { id: 'exit-private', icon: <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M21 14v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5"/></svg>, label: 'Exit private', short: '⇧⌘ N', accent: privAccent }
          : { id: 'new-private', icon: <IcMask s={16}/>, label: 'New private tab', short: '⇧⌘ N', accent: privAccent },
        { id: 'reopen',      icon: <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M3 3v6h6"/><path d="M3.5 9A9 9 0 1 1 6 18.7"/></svg>, label: 'Reopen closed tab', short: '⇧⌘ T' },
        { id: 'tabs',        icon: MIc.tabs({ s: 16 }), label: 'All tabs',        short: '⌘ ⇧ \\' },
      ],
    },
    {
      items: [
        { id: 'find',   icon: MIc.search({ s: 16 }), label: 'Find in page…', short: '⌘ F' },
        { id: 'reader', icon: <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M4 6h16M4 10h12M4 14h16M4 18h10"/></svg>, label: 'Show Reader View', short: '⇧⌘ R' },
        { id: 'zoom',   icon: <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><circle cx="11" cy="11" r="7"/><path d="m20 20-4-4M8 11h6M11 8v6"/></svg>, label: 'Zoom', right: '100%' },
      ],
    },
    {
      items: [
        { id: 'history',   icon: <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M3 12a9 9 0 1 0 3-6.7L3 9"/><path d="M3 3v6h6"/><path d="M12 7v5l3 2"/></svg>, label: 'History', short: '⌘ Y', disabled: isPrivate, disabledHint: 'not saved here' },
        { id: 'bookmarks', icon: <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M19 21V5a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v16l7-4z"/></svg>, label: 'Bookmarks', short: '⌘ B' },
        { id: 'downloads', icon: <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M12 3v12M6 11l6 6 6-6M5 21h14"/></svg>, label: 'Downloads', short: '⌥⌘ L' },
      ],
    },
    {
      items: [
        { id: 'share',     icon: <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M4 12v6a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-6"/><path d="m16 6-4-4-4 4"/><path d="M12 2v14"/></svg>, label: 'Share page…' },
        { id: 'send-peer', icon: MIc.chat({ s: 16 }), label: 'Send to a peer…', disabled: isPrivate, disabledHint: 'unavailable in private' },
        { id: 'print',     icon: <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M6 9V3h12v6"/><rect x="3" y="9" width="18" height="9" rx="2"/><path d="M6 14h12v7H6z"/></svg>, label: 'Print…', short: '⌘ P' },
      ],
    },
    {
      items: [
        { id: 'clear',    icon: <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>, label: 'Clear browsing data…' },
        { id: 'settings', icon: MIc.settings({ s: 16 }), label: 'Settings…', short: '⌘ ,' },
      ],
    },
  ];

  return (
    <>
      <div onClick={onClose} style={{ position: 'absolute', inset: 0, background: scrim, backdropFilter: 'blur(6px)', zIndex: 80 }}/>
      <div style={{
        position: 'absolute', left: 0, right: 0, bottom: 0,
        background: 'var(--glass-strong)', backdropFilter: 'blur(var(--glass-blur)) saturate(1.5)', WebkitBackdropFilter: 'blur(var(--glass-blur)) saturate(1.5)', borderTop: '1px solid var(--glass-border)',
        borderRadius: '22px 22px 0 0', padding: '8px 0 22px',
        zIndex: 81, animation: 'mMenuUp 220ms cubic-bezier(0.2,0.85,0.3,1)',
        color: fg, maxHeight: '80%', overflowY: 'auto',
      }}>
        <style>{`@keyframes mMenuUp{from{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}`}</style>

        <div style={{ width: 40, height: 4, borderRadius: 2, background: fgDim, margin: '4px auto 8px', opacity: 0.5 }}/>

        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '4px 16px 10px' }}>
          <div style={{ fontSize: 10.5, color: fgDim, letterSpacing: '0.16em', textTransform: 'uppercase', fontWeight: 600, fontFamily: 'JetBrains Mono, monospace' }}>
            {isPrivate ? 'Private menu' : 'Menu'}
          </div>
          <button onClick={onClose} aria-label="Close" style={{ background: 'transparent', border: 0, color: fgMuted, cursor: 'pointer', padding: 4 }}>
            {MIc.close({ s: 16 })}
          </button>
        </div>

        {sections.map((sec, si) => (
          <React.Fragment key={si}>
            {si > 0 && <div style={{ height: 1, margin: '6px 12px', background: soft }}/>}
            {sec.items.map((it) => (
              <button
                key={it.id}
                onClick={() => { if (!it.disabled) onAction && onAction(it.id); }}
                disabled={it.disabled}
                style={{
                  width: '100%', display: 'flex', alignItems: 'center', gap: 12,
                  padding: '12px 18px', background: 'transparent', border: 0,
                  color: it.disabled ? fgDim : fg, cursor: it.disabled ? 'default' : 'pointer',
                  textAlign: 'left', fontFamily: 'inherit', fontSize: 14,
                  opacity: it.disabled ? 0.55 : 1,
                }}>
                <span style={{ color: it.accent || (it.disabled ? fgDim : fgMuted), display: 'grid', placeItems: 'center', width: 18, flexShrink: 0 }}>{it.icon}</span>
                <span style={{ flex: 1, fontWeight: 500, fontFamily: 'Geist', letterSpacing: '-0.01em' }}>{it.label}</span>
                {it.right && <span style={{ fontSize: 11, color: fgDim, fontFamily: 'JetBrains Mono, monospace' }}>{it.right}</span>}
                {it.disabledHint && <span style={{ fontSize: 10, color: fgDim, fontFamily: 'JetBrains Mono, monospace' }}>{it.disabledHint}</span>}
                {it.short && !it.right && <span style={{ fontSize: 10.5, color: fgDim, fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.02em' }}>{it.short}</span>}
              </button>
            ))}
          </React.Fragment>
        ))}
      </div>
    </>
  );
}

// ─── Page-actions sheet — swipe up on the center pill ───────────
// URL bar row + 4-tile action grid + page controls (Translate / Zoom /
// Desktop site / Site settings). Chrome-style, in Ajna glass.
function MPillPageSheet({ url, zoom, setZoom, onClose, onAction, startEditing = false }) {
  const [pinned, setPinned] = React.useState(false);
  const [desktop, setDesktop] = React.useState(false);
  const [editing, setEditing] = React.useState(startEditing);
  const [editUrl, setEditUrl] = React.useState(url);
  const [copied, setCopied] = React.useState(false);
  const [kbMode, setKbMode] = React.useState('letters');
  const [dirty, setDirty] = React.useState(false);
  const [selectedAll, setSelectedAll] = React.useState(startEditing);
  const q = editUrl.trim();
  const cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
  const suggestions = (dirty && q) ? [
    { kind: 'search',  title: q },
    { kind: 'history', title: q + ' — recent search' },
    { kind: 'site',    title: q + '.app', sub: cap(q) + ' · visited 2 days ago', letter: cap(q).charAt(0) },
    { kind: 'entity',  title: cap(q) + ' Labs', sub: 'Company', letter: cap(q).charAt(0) },
    { kind: 'search',  title: q + ' on ajna mesh' },
    { kind: 'history', title: q + ' docs', sub: 'From history' },
    { kind: 'search',  title: q + ' peers nearby' },
    { kind: 'search',  title: 'how to ' + q },
  ] : [];
  // URL: long-press → copy, single tap → edit with keyboard
  const lp = React.useRef(null);
  const urlPress = {
    onPointerDown: () => { lp.current = setTimeout(() => { lp.current = null; setCopied(true); setTimeout(() => setCopied(false), 1400); }, 480); },
    onPointerUp: () => { if (lp.current) { clearTimeout(lp.current); lp.current = null; setEditUrl(url); setEditing(true); } },
    onPointerLeave: () => { if (lp.current) { clearTimeout(lp.current); lp.current = null; } },
  };
  const kbKey = (k) => {
    const clear = selectedAll;
    if (clear) setSelectedAll(false);
    setDirty(true);
    if (k === 'back') setEditUrl(s => clear ? '' : s.slice(0, -1));
    else if (k === 'space') setEditUrl(s => (clear ? '' : s) + ' ');
    else if (k === 'go') { setEditing(false); onClose(); }
    else if (k === 'mode') { setSelectedAll(selectedAll); setKbMode(m => m === 'letters' ? 'numbers' : 'letters'); }
    else if (k === 'shift' || k === 'globe') { setSelectedAll(selectedAll); }
    else setEditUrl(s => (clear ? '' : s) + k);
  };
  const ic = (d, s = 18) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">{d}</svg>;
  const roundBtn = { width: 34, height: 34, borderRadius: 999, background: 'transparent', border: 0, color: M_FG_MUTED, display: 'grid', placeItems: 'center', cursor: 'pointer', flexShrink: 0, fontFamily: 'inherit' };
  const tiles = [
    { id: 'summarize', label: 'Summarize', icon: ic(<><path d="M8 6h13M8 12h13M8 18h13"/><path d="M3 6h.01M3 12h.01M3 18h.01"/></>) },
    { id: 'pin',       label: 'Pin',       icon: ic(<><path d="M12 17v5"/><path d="M9 3h6l-.7 6.2 2.7 2.3v2.5H7v-2.5l2.7-2.3z"/></>), active: pinned, toggle: () => setPinned(p => !p) },
    { id: 'find',      label: 'Find',      icon: ic(<><rect x="4" y="3" width="13" height="18" rx="2"/><circle cx="14.5" cy="13.5" r="3"/><path d="m17 16 3 3"/></>) },
    { id: 'share',     label: 'Share',     icon: ic(<><circle cx="18" cy="5" r="2.5"/><circle cx="6" cy="12" r="2.5"/><circle cx="18" cy="19" r="2.5"/><path d="m8.2 10.9 7.6-4.4M8.2 13.1l7.6 4.4"/></>) },
  ];
  const rows = [
    { id: 'translate', label: 'Translate', icon: ic(<><path d="m5 8 6 6"/><path d="m4 14 6-6 2-3"/><path d="M2 5h12"/><path d="M7 2h1"/><path d="m22 22-5-10-5 10"/><path d="M14 18h6"/></>) },
    { id: 'zoom', label: 'Zoom', sub: zoom + '%', icon: ic(<><path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/></>), right: (
      <div style={{ display: 'flex', gap: 4 }}>
        <button onClick={(e) => { e.stopPropagation(); setZoom && setZoom(Math.min(200, zoom + 10)); }} aria-label="Zoom in" style={roundBtn}>{ic(<path d="M5 12h14M12 5v14"/>, 16)}</button>
        <button onClick={(e) => { e.stopPropagation(); setZoom && setZoom(Math.max(50, zoom - 10)); }} aria-label="Zoom out" style={roundBtn}>{ic(<path d="M5 12h14"/>, 16)}</button>
      </div>
    ) },
    { id: 'desktop', label: 'Desktop Site', icon: ic(<><rect x="2" y="4" width="20" height="13" rx="2"/><path d="M8 21h8M12 17v4"/></>), right: (
      <span style={{ width: 19, height: 19, borderRadius: 5, border: '1.5px solid ' + (desktop ? M_ACCENT_B : M_FG_DIM), background: desktop ? M_ACCENT_B : 'transparent', display: 'grid', placeItems: 'center', color: '#0B0C0F', flexShrink: 0 }}>
        {desktop && <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><path d="m5 13 4 4L19 7"/></svg>}
      </span>
    ), toggle: () => setDesktop(d => !d) },
    { id: 'site-settings', label: 'Site Settings', icon: ic(<><circle cx="12" cy="12" r="3"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></>) },
  ];
  const pageTiles = [
    { id: 'reload',   label: 'Reload',   icon: ic(<><path d="M3 12a9 9 0 1 0 3-6.7L3 9"/><path d="M3 3v6h6"/></>, 17) },
    { id: 'bookmark', label: 'Bookmark', icon: ic(<path d="M19 21V5a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v16l7-4z"/>, 17) },
    { id: 'share',    label: 'Share',    icon: ic(<><path d="M4 12v6a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-6"/><path d="m16 6-4-4-4 4"/><path d="M12 2v14"/></>, 17) },
    { id: 'find',     label: 'Find',     icon: ic(<><circle cx="11" cy="11" r="7"/><path d="m20 20-4.3-4.3"/></>, 17), accent: true },
    { id: '__more',   label: 'More',     icon: ic(<><circle cx="5" cy="12" r="1.6" fill="currentColor"/><circle cx="12" cy="12" r="1.6" fill="currentColor"/><circle cx="19" cy="12" r="1.6" fill="currentColor"/></>, 17), accent: true },
  ];

  // ── Editing: the pill flies to the TOP of the screen, tiles under it, keyboard below
  if (editing) return (
    <>
      <div onClick={onClose} style={{ position: 'absolute', inset: 0, background: 'transparent', zIndex: 80 }}/>
      <div style={{ position: 'absolute', left: 0, right: 0, top: -52, zIndex: 81, padding: '60px 10px 10px', boxSizing: 'border-box', background: 'var(--glass-strong)', backdropFilter: 'blur(var(--glass-blur)) saturate(1.5)', WebkitBackdropFilter: 'blur(var(--glass-blur)) saturate(1.5)', borderBottom: '1px solid var(--glass-border)', borderRadius: '0 0 22px 22px', color: M_FG, animation: 'mPillToTop 300ms cubic-bezier(0.2,0.85,0.3,1)' }}>
        <style>{`@keyframes mPillToTop{from{transform:translateY(62vh);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes mUrlCursor{0%,49%{opacity:1}50%,100%{opacity:0}}@keyframes mTilesIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}`}</style>
        {/* URL row — back · bookmark · editable url · reload · forward */}
        <div style={{ position: 'relative', display: 'flex', alignItems: 'center', gap: 2, padding: '3px 6px', background: 'var(--m-tint)', border: '1px solid rgba(96,165,250,0.5)', boxShadow: '0 0 0 3px rgba(96,165,250,0.12)', borderRadius: 999 }}>
          {copied && <div style={{ position: 'absolute', bottom: -32, left: '50%', transform: 'translateX(-50%)', padding: '5px 12px', borderRadius: 999, background: 'rgba(16,18,24,0.95)', border: '1px solid ' + M_BORDER, fontSize: 11, fontWeight: 500, fontFamily: 'Geist', color: M_FG, whiteSpace: 'nowrap' }}>Link copied</div>}
          <button onClick={() => onAction('back')} aria-label="Back" style={roundBtn}>{ic(<path d="m15 18-6-6 6-6"/>, 17)}</button>
          <button onClick={onClose} aria-label="Bookmark" style={roundBtn}>{ic(<path d="M19 21V5a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v16l7-4z"/>, 16)}</button>
          <span style={{ flex: 1, minWidth: 0, textAlign: 'left', fontSize: 13, fontWeight: 500, fontFamily: 'JetBrains Mono, monospace', color: M_FG, whiteSpace: 'nowrap', overflow: 'hidden', padding: '8px 4px' }}>
            <span style={{ background: selectedAll ? 'rgba(96,165,250,0.35)' : 'transparent', borderRadius: 3, padding: selectedAll ? '1px 1px' : 0 }}>{editUrl}</span>
            {!selectedAll && <span style={{ display: 'inline-block', width: 1.5, height: 15, background: '#60A5FA', marginLeft: 1, verticalAlign: 'middle', animation: 'mUrlCursor 1s infinite' }}/>}
          </span>
          <button onClick={onClose} aria-label="Reload" style={roundBtn}>{ic(<><path d="M21 12a9 9 0 1 1-2.6-6.4"/><path d="M21 3v6h-6"/></>, 16)}</button>
          <button aria-label="Forward" style={{ ...roundBtn, opacity: 0.4 }}>{ic(<path d="m9 6 6 6-6 6"/>, 17)}</button>
        </div>
        {/* Page tiles under the url bar — hidden once typing starts */}
        {suggestions.length === 0 && <div style={{ display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 6, marginTop: 10, animation: 'mTilesIn 260ms 60ms both ease-out' }}>
          {pageTiles.map(t => (
            <button key={t.id} onClick={() => t.id === '__more' ? setEditing(false) : onAction(t.id)} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 7, padding: '11px 2px', borderRadius: 13, background: 'rgba(255,255,255,0.06)', border: '1px solid ' + M_BORDER_SOFT, boxShadow: 'inset 0 1px 0 var(--glass-highlight)', color: t.accent ? M_ACCENT_B : M_FG, cursor: 'pointer', fontFamily: 'inherit' }}>
              <span style={{ color: t.accent ? M_ACCENT_B : M_FG_MUTED, display: 'grid', placeItems: 'center' }}>{t.icon}</span>
              <span style={{ fontSize: 10.5, fontWeight: 500, fontFamily: 'Geist', letterSpacing: '-0.01em' }}>{t.label}</span>
            </button>
          ))}
        </div>}
        {suggestions.length > 0 && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 4, marginTop: 10, maxHeight: '46vh', overflowY: 'auto', scrollbarWidth: 'none', animation: 'mTilesIn 200ms both ease-out' }}>
            {suggestions.map((s, i) => (
              <button key={i} onClick={() => { setEditing(false); onClose(); }} style={{ display: 'flex', alignItems: 'center', gap: 11, padding: s.sub ? '9px 12px' : '11px 12px', borderRadius: 12, background: i === 0 ? 'rgba(255,255,255,0.11)' : 'rgba(255,255,255,0.05)', border: '1px solid ' + M_BORDER_SOFT, boxShadow: 'inset 0 1px 0 var(--glass-highlight)', color: M_FG, cursor: 'pointer', fontFamily: 'inherit', textAlign: 'left', flexShrink: 0 }}>
                <span style={{ width: 26, height: 26, borderRadius: s.kind === 'entity' || s.kind === 'site' ? 8 : 999, display: 'grid', placeItems: 'center', flexShrink: 0, background: (s.kind === 'entity' || s.kind === 'site') ? 'rgba(96,165,250,0.18)' : 'transparent', color: (s.kind === 'entity' || s.kind === 'site') ? M_ACCENT_B : M_FG_MUTED, fontSize: 11, fontWeight: 600, fontFamily: 'Geist' }}>
                  {s.letter ? s.letter : s.kind === 'history' ? ic(<><path d="M12 8v4l3 2"/><path d="M3.05 11a9 9 0 1 1 .5 4"/><path d="M3 21v-6h6"/></>, 15) : ic(<><circle cx="11" cy="11" r="7"/><path d="m20 20-4.3-4.3"/></>, 15)}
                </span>
                <span style={{ flex: 1, minWidth: 0 }}>
                  <span style={{ display: 'block', fontSize: 13.5, fontFamily: 'Geist', letterSpacing: '-0.01em', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                    <span style={{ fontWeight: 600 }}>{s.title.slice(0, q.length)}</span><span style={{ fontWeight: 400, color: 'rgba(255,255,255,0.86)' }}>{s.title.slice(q.length)}</span>
                  </span>
                  {s.sub && <span style={{ display: 'block', fontSize: 10.5, color: M_FG_DIM, fontFamily: 'Geist', marginTop: 1.5, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{s.sub}</span>}
                </span>
                {i > 0 && <span style={{ color: M_FG_DIM, flexShrink: 0 }}>{ic(<><path d="M17 17 7 7"/><path d="M7 16V7h9"/></>, 16)}</span>}
              </button>
            ))}
          </div>
        )}
      </div>
      <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, zIndex: 81 }}>
        <MKeyboard mode={kbMode} onKey={kbKey}/>
      </div>
    </>
  );

  return (
    <>
      <div onClick={onClose} style={{ position: 'absolute', inset: 0, background: 'transparent', zIndex: 80 }}/>
      <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, zIndex: 81, display: 'flex', flexDirection: 'column', animation: 'mPillSheetUp 240ms cubic-bezier(0.2,0.85,0.3,1)' }}>
      <div style={{ background: 'var(--glass-strong)', backdropFilter: 'blur(var(--glass-blur)) saturate(1.5)', WebkitBackdropFilter: 'blur(var(--glass-blur)) saturate(1.5)', borderTop: '1px solid var(--glass-border)', borderRadius: '22px 22px 0 0', padding: editing ? '10px 14px 14px' : '10px 14px 26px', color: M_FG, boxSizing: 'border-box' }}>
        <style>{`@keyframes mPillSheetUp{from{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes mUrlCursor{0%,49%{opacity:1}50%,100%{opacity:0}}`}</style>
        <div style={{ width: 40, height: 4, borderRadius: 2, background: M_FG_DIM, margin: '0 auto 12px', opacity: 0.5 }}/>
        {/* URL bar row — bookmark · back · url · reload · forward */}
        <div style={{ position: 'relative', display: 'flex', alignItems: 'center', gap: 2, padding: '4px 8px', background: 'var(--m-tint)', border: '1px solid ' + M_BORDER_SOFT, borderRadius: 999, marginBottom: 12 }}>
          {copied && <div style={{ position: 'absolute', top: -34, left: '50%', transform: 'translateX(-50%)', padding: '5px 12px', borderRadius: 999, background: 'rgba(16,18,24,0.95)', border: '1px solid ' + M_BORDER, fontSize: 11, fontWeight: 500, fontFamily: 'Geist', color: M_FG, whiteSpace: 'nowrap' }}>Link copied</div>}
          <button onClick={() => onAction('back')} aria-label="Back" style={roundBtn}>{ic(<path d="m15 18-6-6 6-6"/>, 17)}</button>
          <button onClick={onClose} aria-label="Bookmark" style={roundBtn}>{ic(<path d="M19 21V5a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v16l7-4z"/>, 16)}</button>
          <span {...urlPress} style={{ flex: 1, textAlign: 'center', fontSize: 13, fontWeight: 500, fontFamily: 'JetBrains Mono, monospace', color: M_FG, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', padding: '8px 4px', cursor: 'text', touchAction: 'none', userSelect: 'none' }}>{url}</span>
          <button onClick={onClose} aria-label="Reload" style={roundBtn}>{ic(<><path d="M21 12a9 9 0 1 1-2.6-6.4"/><path d="M21 3v6h-6"/></>, 16)}</button>
          <button aria-label="Forward" style={{ ...roundBtn, opacity: 0.4 }}>{ic(<path d="m9 6 6 6-6 6"/>, 17)}</button>
        </div>
        {/* Action tiles */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 8, marginBottom: 14 }}>
          {tiles.map(t => (
            <button key={t.id} onClick={() => t.toggle ? t.toggle() : onAction(t.id)} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8, padding: '13px 4px', borderRadius: 13, background: t.active ? 'rgba(255,255,255,0.16)' : 'var(--m-tint)', border: '1px solid ' + (t.active ? M_BORDER : M_BORDER_SOFT), color: M_FG, cursor: 'pointer', fontFamily: 'inherit' }}>
              <span style={{ color: t.active ? M_FG : M_FG_MUTED }}>{t.icon}</span>
              <span style={{ fontSize: 11, fontWeight: 500, fontFamily: 'Geist' }}>{t.label}</span>
            </button>
          ))}
        </div>
        {/* Page control rows */}
        <div style={{ display: 'flex', flexDirection: 'column' }}>
          {rows.map(r => (
            <button key={r.id} onClick={() => r.toggle ? r.toggle() : onAction(r.id)} style={{ display: 'flex', alignItems: 'center', gap: 14, padding: '13px 8px', background: 'transparent', border: 0, color: M_FG, cursor: 'pointer', textAlign: 'left', fontFamily: 'inherit' }}>
              <span style={{ color: M_FG_MUTED, display: 'grid', placeItems: 'center', width: 22, flexShrink: 0 }}>{r.icon}</span>
              <span style={{ flex: 1 }}>
                <span style={{ display: 'block', fontSize: 14.5, fontWeight: 500, fontFamily: 'Geist', letterSpacing: '-0.01em' }}>{r.label}</span>
                {r.sub && <span style={{ display: 'block', fontSize: 11, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace', marginTop: 2 }}>{r.sub}</span>}
              </span>
              {r.right}
            </button>
          ))}
        </div>
      </div>
      </div>
    </>
  );
}

Object.assign(window, {
  NAV_OPTIONS, NavOptionDrawer, NavOptionSuperTab, NavOptionCommand, MEmpty, iconBtn,
  MMenuSheet, MScreenLibrary, MPillPageSheet,
});
