// Mobile keyboard + typing state — shows exact flow when user taps the search pill
// Rendered inside the mobile prototype so we can design the full input experience.

// Compact iOS-style keyboard (dark). Simplified from the starter for mobile shell use.
function MKeyboard({ mode = 'letters', onKey }) {
  const keyBg = 'rgba(120,120,128,0.28)';
  const specialBg = 'rgba(90,90,95,0.55)';
  const glyph = '#fff';

  const rows = mode === 'numbers'
    ? [
        ['1','2','3','4','5','6','7','8','9','0'],
        ['-','/',':',';','(',')','$','&','@','"'],
        ['.',',','?','!',"'"],
      ]
    : [
        ['q','w','e','r','t','y','u','i','o','p'],
        ['a','s','d','f','g','h','j','k','l'],
        ['z','x','c','v','b','n','m'],
      ];

  const key = (label, { flex = 1, w, fs = 22, fw = 400, bg = keyBg, k } = {}) => (
    <button key={k || label} onClick={() => onKey && onKey(k || label)} style={{
      height: 42, borderRadius: 6, flex: w ? 'none' : flex, width: w,
      background: bg, border: 0, color: glyph, fontSize: fs, fontWeight: fw,
      fontFamily: '-apple-system, "SF Pro", system-ui',
      boxShadow: '0 1px 0 rgba(0,0,0,0.4)',
      display: 'grid', placeItems: 'center', padding: 0, minWidth: 0,
    }}>{label}</button>
  );

  return (
    <div style={{
      background: 'rgba(35,37,42,0.96)', backdropFilter: 'blur(20px)',
      padding: '8px 3px 6px', display: 'flex', flexDirection: 'column', gap: 10,
      flexShrink: 0,
    }}>
      {/* predictions */}
      <div style={{ display: 'flex', gap: 0, padding: '4px 0 8px', fontFamily: '-apple-system, system-ui' }}>
        {['“ajna”', 'ajna', 'Ajna'].map((t, i) => (
          <React.Fragment key={i}>
            {i > 0 && <div style={{ width: 1, background: 'rgba(255,255,255,0.15)' }}/>}
            <div style={{ flex: 1, textAlign: 'center', fontSize: 15, color: '#fff', padding: '4px 0' }}>{t}</div>
          </React.Fragment>
        ))}
      </div>
      {rows.map((r, i) => (
        <div key={i} style={{ display: 'flex', gap: 6, padding: mode !== 'numbers' && i === 1 ? '0 22px' : '0 3px' }}>
          {i === 2 && mode !== 'numbers' && key('⇧', { w: 38, fs: 16, bg: specialBg, k: 'shift' })}
          {r.map(l => key(l, { flex: 1, k: l }))}
          {i === 2 && mode !== 'numbers' && key('⌫', { w: 38, fs: 16, bg: specialBg, k: 'back' })}
        </div>
      ))}
      <div style={{ display: 'flex', gap: 6, padding: '0 3px' }}>
        {key(mode === 'numbers' ? 'ABC' : '123', { w: 50, fs: 14, fw: 500, bg: specialBg, k: 'mode' })}
        {key('🌐', { w: 40, fs: 14, bg: specialBg, k: 'globe' })}
        {key('space', { flex: 5, fs: 14, fw: 500, k: 'space' })}
        {key('go', { w: 58, fs: 14, fw: 500, bg: '#2970FF', k: 'go' })}
      </div>
      {/* home indicator area */}
      <div style={{ height: 20, display: 'grid', placeItems: 'center', paddingTop: 6 }}>
        <div style={{ width: 134, height: 5, borderRadius: 3, background: 'rgba(255,255,255,0.7)' }}/>
      </div>
    </div>
  );
}

// Focused command bar state — MINIMAL bottom-sheet version.
// The page stays visible behind a dimmed blur; only a compact glass sheet
// (chips when empty, ranked results when typing) + the input bar float
// above the keyboard. "More" reveals the full menu inside the sheet.
function MCommandFocus({ onClose, onNavigate, initialQuery = '', isPrivate = false }) {
  const [q, setQ] = React.useState(initialQuery);
  const [mode, setMode] = React.useState('letters');
  const [moreOpen, setMoreOpen] = React.useState(false);
  const [voiceOpen, setVoiceOpen] = React.useState(false);

  // Theme tokens — switches violet in private
  const surface = isPrivate ? 'rgba(22,17,36,0.92)' : 'rgba(16,18,24,0.92)';
  const border  = isPrivate ? 'rgba(167,139,250,0.20)' : M_BORDER;
  const soft    = isPrivate ? 'rgba(167,139,250,0.12)' : 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 empty = q.length === 0;

  // Simulated results — app routes (chat/mesh/tabs/files/calls/scan/ai) bubble to the top
  const isUrlLike = /\./.test(q) || q.startsWith('http');
  const appRoutes = [
    { type: 'chat',  label: 'Open Chat',      icon: MIc.chat,  color: M_ACCENT_B, sub: '3 unread', match: ['chat','message','msg'] },
    { type: 'mesh',  label: 'Mesh peers',     icon: MIc.mesh,  color: '#A78BFA',  sub: '3 nearby · BLE', match: ['mesh','peer','nearby','ble'] },
    { type: 'tabs',  label: 'All tabs',       icon: MIc.tabs,  color: M_FG,       sub: '5 open · 2 pinned', match: ['tab','tabs'] },
    { type: 'files', label: 'Files',          icon: MIc.files, color: '#FBBF24',  sub: 'Local + shared', match: ['file','files','doc','document'] },
    { type: 'calls', label: 'Calls',          icon: MIc.calls, color: '#F472B6',  sub: 'Recent calls', match: ['call','calls','dial'] },
    { type: 'scan',  label: 'Scan QR',        icon: MIc.scan,  color: '#FBBF24',  sub: 'Pair, share, connect', match: ['scan','qr'] },
    { type: 'ai',    label: 'Ask AI',         icon: MIc.ai,    color: '#22D3EE',  sub: 'Claude · on device', match: ['ai','ask','claude'] },
  ];
  const ql = q.toLowerCase();
  const matchedApps = empty ? [] : appRoutes.filter(a => a.match.some(m => m.startsWith(ql) || ql.startsWith(m) || m.includes(ql)));

  const suggestions = (empty ? [] : [
    ...matchedApps,
    { type: 'search', label: `Search Google for “${q}”`, icon: MIc.search, color: M_FG_MUTED, sub: 'google.com' },
    { type: 'ai-q',   label: `Ask AI: ${q}`,             icon: MIc.ai,     color: '#22D3EE', sub: 'Claude Haiku · on device' },
    ...(isUrlLike ? [{ type: 'url', label: `Go to ${q}`, icon: MIc.globe, color: '#60A5FA', sub: 'URL' }] : []),
    { type: 'tab',    label: 'Linear — Inbox',            icon: () => <MTile size={16} bg="#5E6AD2" color="#fff" label="L" radius={3}/>, sub: 'linear.app · open tab' },
  ].filter(s => matchedApps.includes(s) || s.label.toLowerCase().includes(ql) || ['search','ai-q','url'].includes(s.type))).slice(0, 5);

  // Empty-state chips — page actions first, then app shortcuts. One scrollable row.
  const sw = (d) => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">{d}</svg>;
  const chips = [
    { id: 'reload',        label: 'Reload',   icon: sw(<><path d="M3 12a9 9 0 1 0 3-6.7L3 9"/><path d="M3 3v6h6"/></>) },
    { id: 'bookmark-page', label: 'Bookmark', icon: sw(<path d="M19 21V5a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v16l7-4z"/>) },
    { id: 'share',         label: 'Share',    icon: sw(<><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"/></>) },
    { id: 'find',          label: 'Find',     icon: MIc.search({ s: 15 }) },
    ...(isPrivate
      ? [{ id: 'exit-private', label: 'Exit private', icon: sw(<><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"/></>), color: '#C4B5FD' }]
      : [
          { id: 'calls', label: 'Calls', icon: MIc.calls({ s: 15 }), color: '#F472B6' },
          { id: 'mesh',  label: 'Mesh',  icon: MIc.mesh({ s: 15 }),  color: '#A78BFA' },
        ]),
    { id: 'scan',   label: 'Scan', icon: MIc.scan({ s: 15 }), color: '#FBBF24' },
    { id: '__more', label: 'More', icon: MIc.more({ s: 15 }) },
  ];

  // Page tiles (Reload / Bookmark / Share / Find / More) + quick actions + recents
  const pageTiles = [
    { id: 'reload',        label: 'Reload',   icon: sw(<><path d="M3 12a9 9 0 1 0 3-6.7L3 9"/><path d="M3 3v6h6"/></>) },
    { id: 'bookmark-page', label: 'Bookmark', icon: sw(<path d="M19 21V5a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v16l7-4z"/>) },
    { id: 'share',         label: 'Share',    icon: sw(<><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"/></>) },
    { id: 'find',          label: 'Find',     icon: MIc.search({ s: 16 }) },
    { id: '__more',        label: 'More',     icon: MIc.more({ s: 16 }) },
  ];
  const quickActions = isPrivate ? [
    { id: 'exit-private', label: 'Exit private', short: '⌘⇧P', color: '#C4B5FD', icon: <IcMask s={16}/> },
    { id: 'files',        label: 'Files',        short: '⌘F',  color: '#60A5FA', icon: MIc.files({ s: 16 }) },
    { id: 'mesh',         label: 'Mesh peers',   short: '⌘M',  color: '#A78BFA', icon: MIc.mesh({ s: 16 }) },
    { id: 'scan',         label: 'Scan QR',      short: '⌘Q',  color: '#FBBF24', icon: MIc.scan({ s: 16 }) },
  ] : [
    { id: 'calls', label: 'Calls',      short: '⌘K', color: '#F472B6', icon: MIc.calls({ s: 16 }) },
    { id: 'files', label: 'Files',      short: '⌘F', color: '#60A5FA', icon: MIc.files({ s: 16 }) },
    { id: 'mesh',  label: 'Mesh peers', short: '⌘M', color: '#A78BFA', icon: MIc.mesh({ s: 16 }) },
    { id: 'scan',  label: 'Scan QR',    short: '⌘Q', color: '#FBBF24', icon: MIc.scan({ s: 16 }) },
  ];
  const recents = [
    { letter: 'L', bg: '#5E6AD2', label: 'Linear — Inbox', url: 'linear.app/inbox' },
    { letter: 'G', bg: '#2B3038', label: 'Ajna Browser',   url: 'github.com/ajna-inc/browser' },
    { letter: 'N', bg: '#1A1A1A', label: 'P2P Sync RFC',   url: 'notion.so/p2p-sync' },
  ];

  // ─── Sectioned long tail — revealed when user taps "More" ─────────
  const moreSections = [
    { title: 'Browse', items: [
      !isPrivate && { id: 'new-private',  label: 'New private window', icon: <IcMask s={16}/>, color: '#C4B5FD' },
      isPrivate  && { id: 'exit-private', label: 'Exit private',       icon: sw(<><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"/></>), color: '#C4B5FD' },
      { id: 'reopen',     label: 'Recently closed',  icon: sw(<><path d="M3 7h13a5 5 0 0 1 0 10h-2"/><path d="m7 11-4-4 4-4"/></>), short: '⇧⌘T' },
    ].filter(Boolean) },
    { title: 'Library', items: [
      { id: 'history',      label: 'History',     icon: sw(<><path d="M3 12a9 9 0 1 0 3-6.7L3 9"/><path d="M3 3v6h6"/><path d="M12 7v5l3 2"/></>), short: '⌘Y', disabled: isPrivate, disabledHint: 'not saved here' },
      { id: 'bookmarks',    label: 'Bookmarks',   icon: sw(<path d="M19 21V5a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v16l7-4z"/>), short: '⌘B' },
      { id: 'downloads',    label: 'Downloads',   icon: sw(<><path d="M12 3v12M6 11l6 6 6-6M5 21h14"/></>), short: '⌥⌘L' },
      { id: 'passwords',    label: 'Passwords',   icon: sw(<><rect x="3" y="11" width="18" height="10" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></>) },
      { id: 'reading-list', label: 'Reading list', icon: sw(<><path d="M3 3h12a3 3 0 0 1 3 3v15"/><path d="M3 21V3"/><path d="M9 8h6M9 12h6"/></>) },
    ] },
    { title: 'Page', items: [
      { id: 'translate',       label: 'Translate',        icon: sw(<><path d="M3 5h12M9 3v2M12 17l3-5 3 5M12.5 21h7M13.5 14h5"/><path d="M5 9c0 4 3 6 6 6"/><path d="M11 9c0 4-3 8-8 8"/></>) },
      { id: 'request-desktop', label: 'Request desktop',  icon: sw(<><rect x="2" y="4" width="20" height="14" rx="2"/><path d="M8 22h8"/><path d="M12 18v4"/></>) },
      { id: 'reader',          label: 'Reader view',      icon: sw(<path d="M4 6h16M4 10h12M4 14h16M4 18h10"/>), short: '⇧⌘R' },
      { id: 'pin-tab',         label: 'Pin tab',          icon: sw(<><path d="m12 17 .01 4"/><path d="M9.85 13H3l3-5h12l3 5h-6.85"/><path d="M6 8 9 3h6l3 5"/></>) },
      { id: 'pip',             label: 'Picture-in-picture', icon: sw(<><rect x="3" y="4" width="18" height="14" rx="2"/><rect x="11" y="9" width="9" height="7" rx="1"/></>) },
      { id: 'add-home',        label: 'Add to Home Screen', icon: sw(<><path d="M3 11 12 3l9 8"/><path d="M5 9v11h14V9"/><path d="M12 14v6"/></>) },
      { id: 'save-pdf',        label: 'Save as PDF',      icon: sw(<><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></>) },
      { id: 'page-info',       label: 'Page info',        icon: sw(<><rect x="3" y="3" width="18" height="18" rx="3"/><path d="M12 8v.01"/><path d="M11 12h1v4h1"/></>) },
      { id: 'mute-tab',        label: 'Mute tab',         icon: sw(<><path d="m9 9-5 4v-4-4l5 4"/><path d="m23 9-6 6"/><path d="m17 9 6 6"/></>) },
      { id: 'zoom',            label: 'Zoom',             icon: sw(<><circle cx="11" cy="11" r="7"/><path d="m20 20-4-4M8 11h6M11 8v6"/></>), right: '100%' },
    ] },
    { title: 'App', items: [
      { id: 'chat',      label: 'Chat',            icon: MIc.chat({ s: 16 }),  short: '⌘1' },
      { id: 'mesh',      label: 'Mesh peers',      icon: MIc.mesh({ s: 16 }),  short: '⌘2' },
      { id: 'calls',     label: 'Calls',           icon: MIc.calls({ s: 16 }), short: '⌘3' },
      { id: 'files',     label: 'Files',           icon: MIc.files({ s: 16 }), short: '⌘4' },
      { id: 'send-peer', label: 'Send to peer',    icon: MIc.share ? MIc.share({ s: 16 }) : MIc.chat({ s: 16 }), disabled: isPrivate, disabledHint: 'unavailable in private' },
      { id: 'print',     label: 'Print',           icon: sw(<><path d="M6 9V3h12v6"/><rect x="3" y="9" width="18" height="9" rx="2"/><path d="M6 14h12v7H6z"/></>), short: '⌘P' },
      { id: 'clear',     label: 'Clear data',      icon: sw(<><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"/></>) },
      { id: 'privacy-review', label: 'Privacy review', icon: sw(<><path d="M12 2 4 5v7c0 5 3.5 8.5 8 10 4.5-1.5 8-5 8-10V5z"/><path d="m9 12 2 2 4-4"/></>), color: '#6EE7B7' },
      { id: 'permissions', label: 'Site permissions', icon: sw(<><path d="M12 2 4 5v7c0 5 3.5 8.5 8 10 4.5-1.5 8-5 8-10V5z"/></>) },
      { id: 'help',      label: 'Help & feedback', icon: sw(<><circle cx="12" cy="12" r="10"/><path d="M9.1 9a3 3 0 1 1 5.8 1c0 2-3 3-3 3"/><path d="M12 17h.01"/></>) },
      { id: 'credits',   label: 'About & credits', icon: sw(<><path d="M12 2 4 5v7c0 5 3.5 8.5 8 10 4.5-1.5 8-5 8-10V5z"/></>) },
      { id: 'settings',  label: 'Settings',        icon: MIc.settings({ s: 16 }), short: '⌘,' },
    ] },
  ];

  // Flatten for type-to-search — typing "settings" surfaces the Settings row.
  const allMenuLike = [...chips.filter(c => c.id !== '__more'), ...moreSections.flatMap(s => s.items)];
  const matchedMenu = empty ? [] : allMenuLike.filter(m =>
    !m.disabled && (m.label.toLowerCase().includes(ql) || m.id.includes(ql))
  ).slice(0, 3);

  const handleKey = (k) => {
    if (k === 'back') setQ(s => s.slice(0, -1));
    else if (k === 'space') setQ(s => s + ' ');
    else if (k === 'go') { onClose(); /* submit */ }
    else if (k === 'mode') setMode(m => m === 'letters' ? 'numbers' : 'letters');
    else if (k === 'shift' || k === 'globe') {} // no-op in mock
    else if (k.length === 1 || k.length > 1 && /^[a-z0-9]/.test(k)) setQ(s => s + k);
  };

  const go = (id) => { onNavigate && onNavigate(id); onClose(); };

  const glassRow = (r, i, kind) => {
    const label = r.label || '';
    const boldLen = label.toLowerCase().startsWith(ql) ? ql.length : 0;
    const hasTile = kind !== 'menu' && !!r.bg;
    return (
      <button key={kind + i} onClick={() => { if (kind === 'menu') go(r.id); else { if (['chat','mesh','tabs','files','calls','scan','ai'].includes(r.type)) onNavigate && onNavigate(r.type); onClose(); } }}
        style={{ width: '100%', display: 'flex', alignItems: 'center', gap: 11, padding: (r.sub || kind === 'menu') ? '9px 12px' : '11px 12px', borderRadius: 12, background: i === 0 ? 'rgba(255,255,255,0.11)' : 'rgba(255,255,255,0.05)', border: '1px solid ' + soft, boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.06)', color: fg, cursor: 'pointer', fontFamily: 'inherit', textAlign: 'left', flexShrink: 0 }}>
        <span style={{ width: 26, height: 26, borderRadius: hasTile ? 8 : 999, flexShrink: 0, display: 'grid', placeItems: 'center', background: hasTile ? r.bg : 'transparent', color: hasTile ? '#fff' : (r.color || fgMuted), fontSize: 11, fontWeight: 600, fontFamily: 'Geist' }}>
          {hasTile ? (r.letter || label.charAt(0).toUpperCase()) : (r.icon ? (typeof r.icon === 'function' ? r.icon({ s: 16 }) : r.icon) : sw(<><circle cx="11" cy="11" r="7"/><path d="m20 20-4.3-4.3"/></>))}
        </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 }}>{label.slice(0, boldLen)}</span><span style={{ fontWeight: 400, color: 'rgba(255,255,255,0.86)' }}>{label.slice(boldLen)}</span>
          </span>
          {(r.sub || kind === 'menu') && <span style={{ display: 'block', fontSize: 10.5, color: fgDim, fontFamily: 'Geist', marginTop: 1.5, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{r.sub || 'Menu'}</span>}
        </span>
        <span style={{ color: fgDim, flexShrink: 0 }}>{sw(<><path d="M17 17 7 7"/><path d="M7 16V7h9"/></>, 16)}</span>
      </button>
    );
  };

  const resultRow = (r, i, kind) => (
    <div key={kind + i} onClick={() => { if (kind === 'menu') go(r.id); else { if (['chat','mesh','tabs','files','calls','scan','ai'].includes(r.type)) onNavigate && onNavigate(r.type); onClose(); } }}
      style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '9px 4px', borderTop: i === 0 && kind === 'menu' ? 0 : '1px solid ' + soft, cursor: 'pointer' }}>
      <span style={{ color: r.color || fgMuted, flexShrink: 0, width: 20, display: 'grid', placeItems: 'center' }}>{r.icon ? (typeof r.icon === 'function' ? r.icon({ s: 16 }) : r.icon) : null}</span>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 13, fontWeight: 500, color: fg, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{r.label}</div>
        {(r.sub || kind === 'menu') && <div style={{ fontSize: 10, color: fgDim, fontFamily: 'JetBrains Mono, monospace', marginTop: 1 }}>{r.sub || 'Menu'}</div>}
      </div>
      <span style={{ color: fgDim, fontSize: 12 }}>↗</span>
    </div>
  );

  // Google-style continuous suggestion row: icon · query (bold completion) · edit arrow
  const gRow = (r, i, kind) => {
    const label = r.label || '';
    const boldFrom = label.toLowerCase().startsWith(ql) ? ql.length : 0;
    return (
      <button key={kind + i} onClick={() => { if (kind === 'menu') go(r.id); else { if (['chat','mesh','tabs','files','calls','scan','ai'].includes(r.type)) onNavigate && onNavigate(r.type); onClose(); } }}
        style={{ width: '100%', display: 'flex', alignItems: 'center', gap: 14, padding: '12px 14px', borderRadius: 16, background: 'linear-gradient(160deg, rgba(255,255,255,0.13), rgba(255,255,255,0.04) 55%, rgba(255,255,255,0.085))', backdropFilter: 'blur(30px) saturate(1.6)', WebkitBackdropFilter: 'blur(30px) saturate(1.6)', border: '1px solid rgba(255,255,255,0.13)', boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.15), 0 8px 20px rgba(0,0,0,0.32)', color: fg, cursor: 'pointer', fontFamily: 'inherit', textAlign: 'left', flexShrink: 0 }}>
        <span style={{ width: 20, flexShrink: 0, display: 'grid', placeItems: 'center', color: r.color || fgMuted }}>
          {r.icon ? (typeof r.icon === 'function' ? r.icon({ s: 17 }) : r.icon) : sw(<><circle cx="11" cy="11" r="7"/><path d="m20 20-4.3-4.3"/></>, 17)}
        </span>
        <span style={{ flex: 1, minWidth: 0, fontSize: 14.5, fontFamily: 'Geist', letterSpacing: '-0.01em', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
          <span style={{ fontWeight: 400, color: 'rgba(255,255,255,0.9)' }}>{label.slice(0, boldFrom)}</span><span style={{ fontWeight: 600 }}>{label.slice(boldFrom)}</span>
          {(r.sub || kind === 'menu') && <span style={{ display: 'block', fontSize: 10.5, color: fgDim, fontWeight: 400, marginTop: 1.5, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{r.sub || 'Menu'}</span>}
        </span>
        <span style={{ color: fgDim, flexShrink: 0 }}>{sw(<><path d="M17 17 7 7"/><path d="M7 16V7h9"/></>, 17)}</span>
      </button>
    );
  };

  return (
    <div style={{ position: 'absolute', inset: 0, zIndex: 90, display: 'flex', flexDirection: 'column' }}>
      <style>{`@keyframes focusIn{from{opacity:0}to{opacity:1}}@keyframes sheetUp{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}`}</style>
      {/* full-page glass overlay — covers the whole page behind the bar + results; tap to dismiss */}
      <div onClick={onClose} style={{ position: 'absolute', inset: 0, background: 'var(--glass-strong)', backdropFilter: 'blur(var(--glass-blur)) saturate(1.4)', WebkitBackdropFilter: 'blur(var(--glass-blur)) saturate(1.4)', animation: 'focusIn 160ms ease-out' }}/>

      <div style={{ position: 'relative', flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'flex-end', minHeight: 0 }}>
        {/* bar block sits just above the keyboard: options bubbles on top, field below */}
        <div style={{ order: 2, padding: '0 10px 8px', animation: 'barToTop 240ms cubic-bezier(0.2,0.85,0.3,1)', flexShrink: 0 }}>
          <style>{`@keyframes barToTop{from{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}`}</style>
          <div style={{ display: 'flex', flexDirection: 'column-reverse', gap: 8 }}>
          <div style={{
            display: 'flex', alignItems: 'center', gap: 10, padding: '11px 14px',
            background: 'linear-gradient(160deg, rgba(255,255,255,0.16), rgba(255,255,255,0.05) 52%, rgba(255,255,255,0.10))',
            backdropFilter: 'blur(34px) saturate(1.7)', WebkitBackdropFilter: 'blur(34px) saturate(1.7)',
            border: '1px solid ' + (isPrivate ? 'rgba(167,139,250,0.45)' : 'rgba(96,165,250,0.4)'),
            boxShadow: '0 0 0 3px ' + (isPrivate ? 'rgba(167,139,250,0.12)' : 'rgba(96,165,250,0.12)') + ', inset 0 1px 0 rgba(255,255,255,0.18), 0 14px 34px rgba(0,0,0,0.45)',
            borderRadius: 16,
          }}>
            <span style={{ color: accent, flexShrink: 0 }}>{MIc.search({ s: 16 })}</span>
            <div style={{ flex: 1, fontSize: 14, color: fg, fontFamily: q && /\./.test(q) ? 'JetBrains Mono, monospace' : 'inherit', overflow: 'hidden', whiteSpace: 'nowrap' }}>
              {q || <span style={{ color: fgMuted }}>{isPrivate ? 'Search privately or ask AI' : 'Search, URL, or ask AI'}</span>}
              <span style={{ display: 'inline-block', width: 1.5, height: 16, background: accent, marginLeft: 1, verticalAlign: 'middle', animation: 'cursorBlink 1s infinite' }}/>
              <style>{`@keyframes cursorBlink{0%,49%{opacity:1}50%,100%{opacity:0}}`}</style>
            </div>
            <button onClick={() => setVoiceOpen(true)} aria-label="Voice search" style={{ width: 30, height: 30, borderRadius: 8, flexShrink: 0, background: 'transparent', border: 0, color: fgMuted, display: 'grid', placeItems: 'center', cursor: 'pointer' }}>{MIc.mic({ s: 16 })}</button>
            <button onClick={onClose} style={{ background: 'transparent', border: 0, color: fgMuted, fontSize: 13, cursor: 'pointer', padding: 0, fontFamily: 'inherit' }}>Cancel</button>
          </div>
          {/* page options — individual glass bubbles */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            {pageTiles.map(t => (
              <button key={t.id} onClick={() => { if (t.id === '__more') { setMoreOpen(m => !m); return; } go(t.id); }} aria-label={t.label} title={t.label} style={{
                flex: 1, display: 'grid', placeItems: 'center', padding: '11px 0', borderRadius: 14,
                background: (t.id === '__more' && moreOpen)
                  ? 'linear-gradient(160deg, rgba(255,255,255,0.24), rgba(255,255,255,0.10))'
                  : 'linear-gradient(160deg, rgba(255,255,255,0.14), rgba(255,255,255,0.045) 55%, rgba(255,255,255,0.09))',
                backdropFilter: 'blur(30px) saturate(1.6)', WebkitBackdropFilter: 'blur(30px) saturate(1.6)',
                border: '1px solid rgba(255,255,255,0.14)',
                boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.16), 0 8px 20px rgba(0,0,0,0.35)',
                color: t.color || (t.id === '__more' ? accent : fgMuted), cursor: 'pointer', fontFamily: 'inherit',
              }}>{t.icon}</button>
            ))}
          </div>
          </div>
        </div>

        {/* glass results sheet — directly under the field */}
        <div style={{
          order: 1, margin: '0 10px 8px', borderRadius: 18,
          background: empty ? 'linear-gradient(160deg, rgba(255,255,255,0.10), rgba(255,255,255,0.04))' : 'transparent',
          border: empty ? '1px solid rgba(255,255,255,0.12)' : 0,
          backdropFilter: empty ? 'blur(30px) saturate(1.5)' : 'none', WebkitBackdropFilter: empty ? 'blur(30px) saturate(1.5)' : 'none',
          boxShadow: empty ? 'inset 0 1px 0 rgba(255,255,255,0.14), 0 18px 40px rgba(0,0,0,0.45)' : 'none',
          flex: '0 1 auto', minHeight: 0, overflowY: 'auto', scrollbarWidth: 'none',
          animation: 'sheetUp 200ms cubic-bezier(0.2,0.9,0.3,1)',
        }}>
          {empty && moreOpen && (
            <div style={{ padding: '10px 14px 12px' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '2px 0 10px', position: 'sticky', top: 0 }}>
                <button onClick={() => setMoreOpen(false)} aria-label="Back" style={{ width: 28, height: 28, borderRadius: 9, background: 'rgba(255,255,255,0.06)', border: '1px solid ' + soft, color: fg, display: 'grid', placeItems: 'center', cursor: 'pointer' }}>{MIc.back({ s: 14 })}</button>
                <div style={{ fontSize: 13, fontWeight: 600, color: fg, fontFamily: 'Geist', letterSpacing: '-0.01em' }}>{isPrivate ? 'Private menu' : 'Menu'}</div>
                <div style={{ flex: 1 }}/>
                <div style={{ fontSize: 9.5, color: fgDim, fontFamily: 'JetBrains Mono, monospace' }}>type to search</div>
              </div>
              {moreSections.map((section, si) => (
                <div key={section.title} style={{ marginBottom: si === moreSections.length - 1 ? 0 : 12 }}>
                  <div style={{ fontSize: 10, fontWeight: 600, color: fgDim, letterSpacing: '0.12em', textTransform: 'uppercase', margin: '0 2px 6px' }}>{section.title}</div>
                  <div style={{ border: '1px solid ' + soft, borderRadius: 12, overflow: 'hidden' }}>
                    {section.items.map((it, ii) => (
                      <button key={it.id} disabled={it.disabled} onClick={() => { if (!it.disabled) go(it.id); }} style={{
                        width: '100%', display: 'flex', alignItems: 'center', gap: 12, padding: '10px 12px',
                        background: 'transparent', border: 0, borderTop: ii === 0 ? 0 : '1px solid ' + soft,
                        color: it.disabled ? fgDim : fg, textAlign: 'left', fontFamily: 'inherit', fontSize: 13.5, fontWeight: 500,
                        cursor: it.disabled ? 'default' : 'pointer', opacity: it.disabled ? 0.55 : 1,
                      }}>
                        <span style={{ color: it.color || (it.disabled ? fgDim : fgMuted), display: 'grid', placeItems: 'center', width: 18, flexShrink: 0 }}>{it.icon}</span>
                        <span style={{ flex: 1, fontFamily: 'Geist', letterSpacing: '-0.01em' }}>{it.label}</span>
                        {it.right && <span style={{ fontSize: 11, color: fgDim, fontFamily: 'JetBrains Mono, monospace' }}>{it.right}</span>}
                        {it.disabled && it.disabledHint && <span style={{ fontSize: 10, color: fgDim, fontFamily: 'JetBrains Mono, monospace' }}>{it.disabledHint}</span>}
                        {it.short && !it.right && !it.disabledHint && <span style={{ fontSize: 10.5, color: fgDim, fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.02em' }}>{it.short}</span>}
                      </button>
                    ))}
                  </div>
                </div>
              ))}
            </div>
          )}

          {empty && !moreOpen && (
            <div style={{ padding: '12px 12px 12px' }}>
              {/* RECENT */}
              <div style={{ fontSize: 10, fontWeight: 600, color: fgDim, letterSpacing: '0.12em', textTransform: 'uppercase', margin: '0 2px 6px' }}>Recent</div>
              <div>
                {recents.map((r, i) => (
                  <button key={r.label} onClick={() => { onClose(); }} style={{
                    width: '100%', display: 'flex', alignItems: 'center', gap: 11, padding: '9px 4px',
                    background: 'transparent', border: 0, borderTop: i === 0 ? 0 : '1px solid ' + soft,
                    color: fg, cursor: 'pointer', fontFamily: 'inherit', textAlign: 'left',
                  }}>
                    <MTile size={22} bg={r.bg} color="#fff" label={r.letter} radius={6}/>
                    <span style={{ flex: 1, minWidth: 0 }}>
                      <span style={{ display: 'block', fontSize: 13, fontWeight: 500, fontFamily: 'Geist', letterSpacing: '-0.01em', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{r.label}</span>
                      <span style={{ display: 'block', fontSize: 10, color: fgDim, fontFamily: 'JetBrains Mono, monospace', marginTop: 1, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{r.url}</span>
                    </span>
                    <span style={{ color: fgDim, fontSize: 13, flexShrink: 0 }}>←</span>
                  </button>
                ))}
              </div>
            </div>
          )}

          {!empty && (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
              {matchedMenu.map((m, i) => gRow(m, i, 'menu'))}
              {suggestions.map((r, i) => gRow(r, i + matchedMenu.length, 'result'))}
            </div>
          )}
        </div>

        <div style={{ order: 0, flex: 1, minHeight: 0 }}/>
        {/* keyboard */}
        <div style={{ order: 3 }}><MKeyboard mode={mode} onKey={handleKey}/></div>
      </div>

      {voiceOpen && <MVoiceSearch onClose={() => setVoiceOpen(false)} onCommit={(t) => { setQ(t); setVoiceOpen(false); }}/>}
    </div>
  );
}

Object.assign(window, { MKeyboard, MCommandFocus });
