/* ============================================
   APP SHELL
   ============================================ */

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "dark",
  "accent": ["#a78bfa", "#67e8f9"],
  "density": "comfortable",
  "fontPair": "geist",
  "glassBlur": 28,
  "auroraOn": true
}/*EDITMODE-END*/;

const ACCENT_PALETTES = [
  ["#a78bfa", "#67e8f9"],
  ["#22d3ee", "#3b82f6"],
  ["#f97316", "#ec4899"],
  ["#84cc16", "#22d3ee"],
  ["#f5f5f7", "#a3a3a3"],
];

function fmtTs(ts) {
  try {
    const d = new Date(ts);
    const diff = Date.now() - d;
    if (diff < 60000) return 'just now';
    if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`;
    if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`;
    return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
  } catch { return ''; }
}

// Convert hex to rgba string
function hexRgba(hex, alpha) {
  const m = hex.replace('#', '');
  const r = parseInt(m.substring(0, 2), 16);
  const g = parseInt(m.substring(2, 4), 16);
  const b = parseInt(m.substring(4, 6), 16);
  return `rgba(${r},${g},${b},${alpha})`;
}

const FONT_PAIRS = {
  geist:    { sans: 'Geist',     mono: 'Geist Mono',  display: 'Geist' },
  serif:    { sans: 'Geist',     mono: 'Geist Mono',  display: 'Instrument Serif' },
  grotesk:  { sans: 'Space Grotesk', mono: 'Geist Mono', display: 'Space Grotesk' },
};

function App() {
  const [authed, setAuthed] = React.useState(false);
  const [authLoading, setAuthLoading] = React.useState(true);
  const [user, setUser] = React.useState(null);
  const [screen, setScreen] = React.useState('home');
  const [adminMode, setAdminMode] = React.useState(false);
  const [openTrack, setOpenTrack] = React.useState(null);
  const [shareTarget, setShareTarget] = React.useState(null);
  const [showCreate, setShowCreate] = React.useState(false);
  const [showEditProfile, setShowEditProfile] = React.useState(false);
  const [currentTrack, setCurrentTrack] = React.useState(TRACKS[4]);
  const [isPlaying, setIsPlaying] = React.useState(false);
  const [progress, setProgress] = React.useState(0.35);
  const [volume, setVolume] = React.useState(0.75);
  const [shuffle, setShuffle] = React.useState(false);
  const [repeat, setRepeat] = React.useState(false);
  const audioRef = React.useRef(null);
  // Refs so interval/audio callbacks always see latest values
  const shuffleRef = React.useRef(shuffle);
  const repeatRef  = React.useRef(repeat);
  const currentTrackRef = React.useRef(currentTrack);
  React.useEffect(() => { shuffleRef.current = shuffle; }, [shuffle]);
  React.useEffect(() => { repeatRef.current = repeat; }, [repeat]);
  React.useEffect(() => { currentTrackRef.current = currentTrack; }, [currentTrack]);
  const toast = useToast();

  // Liked tracks — persisted to localStorage
  const [likedTrackIds, setLikedTrackIds] = React.useState(() => {
    try { return new Set(JSON.parse(localStorage.getItem('ams-liked') || '[]')); }
    catch { return new Set(); }
  });

  // Search
  const [searchQuery, setSearchQuery] = React.useState('');
  const [searchFocused, setSearchFocused] = React.useState(false);
  const searchBlurTimer = React.useRef(null);
  const searchInputRef = React.useRef(null);

  // Notifications
  const [notifications, setNotifications] = React.useState(() => (window.NOTIFICATIONS || []).slice());
  const [notifOpen, setNotifOpen] = React.useState(false);
  const [lastSeenNotif, setLastSeenNotif] = React.useState(() => {
    try { return localStorage.getItem('lastSeenNotif') || ''; } catch { return ''; }
  });
  const bellRef = React.useRef(null);
  const unreadCount = notifications.filter(n => (n.timestamp || '') > lastSeenNotif).length;

  const openBell = () => {
    setNotifOpen(o => !o);
    if (!notifOpen) {
      const now = new Date().toISOString();
      setLastSeenNotif(now);
      try { localStorage.setItem('lastSeenNotif', now); } catch {}
    }
  };

  // Restore Firebase auth session on page load
  React.useEffect(() => {
    let done = false;
    const restore = (u) => {
      if (done) return; done = true;
      if (u) {
        const isAdmin = u.role === 'admin' || u.role === 'co-admin';
        setUser(u); setAuthed(true);
        setAdminMode(isAdmin);
        setScreen(isAdmin ? 'admin-dashboard' : 'home');
      }
      setAuthLoading(false);
    };
    if (window.__authResolved) { restore(window.__restoredUser || null); return; }
    const handler = (e) => restore(e.detail);
    window.addEventListener('authRestored', handler, { once: true });
    const fallback = setTimeout(() => restore(null), 5000);
    return () => { window.removeEventListener('authRestored', handler); clearTimeout(fallback); };
  }, []); // eslint-disable-line

  // Deep-link routing — handle /t/{id}, /p/{id}, and legal pages
  React.useEffect(() => {
    const path = window.location.pathname.replace(/\/$/, '') || '/';
    const LEGAL = ['about', 'privacy', 'terms', 'contact'];
    const legalMatch = LEGAL.find(p => path === '/' + p);
    if (legalMatch) { setScreen(legalMatch); return; }
    const tMatch = path.match(/\/t\/([^/]+)/);
    const pMatch = path.match(/\/p\/([^/]+)/);
    if (!tMatch && !pMatch) return;
    const navigate = () => {
      if (tMatch) {
        const track = (window.TRACKS || []).find(t => t.id === tMatch[1]);
        if (track) { setOpenTrack(track); setScreen('track'); }
      } else {
        setScreen('playlists');
      }
      window.history.replaceState(null, '', '/');
    };
    const handler = () => { navigate(); window.removeEventListener('dataLoaded', handler); };
    window.addEventListener('dataLoaded', handler);
    return () => window.removeEventListener('dataLoaded', handler);
  }, []); // eslint-disable-line

  // Close bell dropdown on outside click
  React.useEffect(() => {
    if (!notifOpen) return;
    const handler = (e) => { if (bellRef.current && !bellRef.current.contains(e.target)) setNotifOpen(false); };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, [notifOpen]);

  // Re-render when Firestore data arrives; refresh currentTrack so audioUrl is picked up
  const [, setDataTs] = React.useState(0);
  React.useEffect(() => {
    const onLoad = () => {
      setDataTs(Date.now());
      setCurrentTrack(prev => window.TRACKS?.find(t => t.id === prev?.id) || prev);
      setNotifications((window.NOTIFICATIONS || []).slice());
    };
    const onNotif = (e) => {
      setNotifications(ns => {
        const exists = ns.some(n => n.id === e.detail.id);
        return exists ? ns : [e.detail, ...ns];
      });
    };
    window.addEventListener('dataLoaded', onLoad);
    window.addEventListener('notificationSent', onNotif);
    return () => {
      window.removeEventListener('dataLoaded', onLoad);
      window.removeEventListener('notificationSent', onNotif);
    };
  }, []);

  // Create Audio element once
  React.useEffect(() => {
    const audio = new Audio();
    audioRef.current = audio;
    audio.volume = 0.75;
    const onTime = () => { if (audio.duration) setProgress(audio.currentTime / audio.duration); };
    const onEnd  = () => {
      if (repeatRef.current) {
        audio.currentTime = 0;
        audio.play().catch(() => {});
        setProgress(0);
      } else {
        const list = window.TRACKS || TRACKS;
        const cur  = currentTrackRef.current;
        const idx  = list.findIndex(t => t.id === cur?.id);
        const next = shuffleRef.current
          ? list[Math.floor(Math.random() * list.length)]
          : list[(idx + 1 + list.length) % list.length];
        if (next) { setCurrentTrack(next); setProgress(0); setIsPlaying(true); }
        else      { setIsPlaying(false); setProgress(0); }
      }
    };
    audio.addEventListener('timeupdate', onTime);
    audio.addEventListener('ended', onEnd);
    return () => { audio.pause(); audio.removeEventListener('timeupdate', onTime); audio.removeEventListener('ended', onEnd); };
  }, []);

  // Tweaks
  const [tweaks, setTweaks] = useTweaks(TWEAK_DEFAULTS);

  // Apply theme + accent + font + density + blur
  React.useEffect(() => {
    let theme = tweaks.theme;
    try {
      const stored = localStorage.getItem('ams-theme');
      if (stored && stored !== tweaks.theme && !window.__amsThemeSynced) {
        window.__amsThemeSynced = true;
        setTweaks('theme', stored);
        theme = stored;
      }
    } catch (e) {}
    document.documentElement.setAttribute('data-theme', theme);
    document.body.setAttribute('data-theme', theme);
    try { localStorage.setItem('ams-theme', theme); } catch (e) {}
    const [a, b] = Array.isArray(tweaks.accent) ? tweaks.accent : ACCENT_PALETTES[0];
    document.documentElement.style.setProperty('--accent', a);
    document.documentElement.style.setProperty('--accent-2', b);
    document.documentElement.style.setProperty('--accent-glow', hexRgba(a, 0.45));
    document.documentElement.style.setProperty('--accent-soft', hexRgba(a, 0.12));
    document.documentElement.style.setProperty('--glass-blur', tweaks.glassBlur + 'px');

    const fp = FONT_PAIRS[tweaks.fontPair] || FONT_PAIRS.geist;
    document.documentElement.style.setProperty('--font-sans', `'${fp.sans}', ui-sans-serif, system-ui, -apple-system, sans-serif`);
    document.documentElement.style.setProperty('--font-mono', `'${fp.mono}', ui-monospace, 'SF Mono', Menlo, monospace`);
    document.documentElement.style.setProperty('--font-display', `'${fp.display}', ui-sans-serif, system-ui, sans-serif`);

    const d = tweaks.density;
    if (d === 'compact') {
      document.documentElement.style.setProperty('--space-5', '16px');
      document.documentElement.style.setProperty('--space-6', '20px');
    } else if (d === 'spacious') {
      document.documentElement.style.setProperty('--space-5', '32px');
      document.documentElement.style.setProperty('--space-6', '44px');
    } else {
      document.documentElement.style.setProperty('--space-5', '24px');
      document.documentElement.style.setProperty('--space-6', '32px');
    }
  }, [tweaks]);

  // Keyboard: A toggles admin, ⌘K / Ctrl+K focuses search
  React.useEffect(() => {
    const onKey = (e) => {
      if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
      if (e.key.toLowerCase() === 'a' && user && (user.role === 'admin' || user.role === 'co-admin')) {
        setAdminMode(a => !a);
        toast(adminMode ? 'Exited admin mode' : 'Entered admin mode', 'info');
      }
    };
    const onSearch = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
        e.preventDefault();
        searchInputRef.current?.focus();
      }
    };
    window.addEventListener('keydown', onKey);
    window.addEventListener('keydown', onSearch);
    return () => { window.removeEventListener('keydown', onKey); window.removeEventListener('keydown', onSearch); };
  }, [user, adminMode, toast]);

  // Real audio playback
  React.useEffect(() => {
    const audio = audioRef.current;
    if (!audio || !currentTrack) return;
    if (!currentTrack.audioUrl) {
      audio.pause();
      return;
    }
    if (audio.src !== currentTrack.audioUrl) {
      audio.pause();
      audio.src = currentTrack.audioUrl;
      audio.currentTime = 0;
    }
    if (isPlaying) { audio.play().catch(() => setIsPlaying(false)); }
    else           { audio.pause(); }
  }, [currentTrack, isPlaying]);

  // Volume sync
  React.useEffect(() => {
    if (audioRef.current) audioRef.current.volume = volume;
  }, [volume]);

  // Simulation fallback — only runs when the track has no audioUrl
  React.useEffect(() => {
    if (!isPlaying || !currentTrack || currentTrack.audioUrl) return;
    const dur = currentTrack.durationSec || 180;
    const t = setInterval(() => {
      setProgress(p => {
        const next = p + 1 / dur;
        if (next >= 1) {
          if (repeatRef.current) return 0;
          setTimeout(() => {
            const list = window.TRACKS || TRACKS;
            const cur = currentTrackRef.current;
            const idx = list.findIndex(t => t.id === cur?.id);
            const nextTrack = shuffleRef.current
              ? list[Math.floor(Math.random() * list.length)]
              : list[(idx + 1) % list.length];
            if (nextTrack) { setCurrentTrack(nextTrack); setIsPlaying(true); }
          }, 0);
          return 0;
        }
        return next;
      });
    }, 1000);
    return () => clearInterval(t);
  }, [isPlaying, currentTrack]);

  // Handlers
  const handleToggleLike = (trackId) => {
    setLikedTrackIds(prev => {
      const next = new Set(prev);
      next.has(trackId) ? next.delete(trackId) : next.add(trackId);
      try { localStorage.setItem('ams-liked', JSON.stringify([...next])); } catch {}
      return next;
    });
  };

  const handlePlay = (t) => {
    if (currentTrack && currentTrack.id === t.id) {
      setIsPlaying(p => !p);
    } else {
      setCurrentTrack(t);
      setProgress(0);
      setIsPlaying(true);
      // Increment play count in window.TRACKS
      window.TRACKS = (window.TRACKS || TRACKS).map(tr =>
        tr.id === t.id ? { ...tr, plays: (tr.plays || 0) + 1 } : tr
      );
      // Add to history (most recent first, dedupe, cap at 20)
      const histEntry = {
        trackId: t.id,
        when: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
      };
      window.HISTORY = [histEntry, ...(window.HISTORY || []).filter(h => h.trackId !== t.id).slice(0, 19)];
      window.dispatchEvent(new CustomEvent('dataLoaded'));
      // Persist to Firestore (best-effort)
      window.dbHelpers?.updateTrack(t.id, { plays: (t.plays || 0) + 1 }).catch(() => {});
    }
  };

  const skipTrack = (dir) => {
    const list = window.TRACKS || TRACKS;
    if (!list.length) return;
    const idx = list.findIndex(t => t.id === (currentTrackRef.current || currentTrack)?.id);
    const next = shuffleRef.current
      ? list[Math.floor(Math.random() * list.length)]
      : list[(idx + dir + list.length) % list.length];
    setCurrentTrack(next);
    setProgress(0);
    setIsPlaying(true);
  };

  const handleOpenTrack = (t) => {
    setOpenTrack(t);
    setScreen('track');
  };
  const handleShare = (target) => setShareTarget(target);
  const LEGAL_SCREENS = ['about', 'privacy', 'terms', 'contact'];
  const handleNavigate = (s) => {
    if (s.startsWith('admin')) setAdminMode(true);
    setScreen(s);
    // Keep URL in sync for legal pages (good for SEO + direct linking)
    if (LEGAL_SCREENS.includes(s)) {
      window.history.pushState(null, '', '/' + s);
    } else if (LEGAL_SCREENS.some(l => window.location.pathname === '/' + l)) {
      window.history.replaceState(null, '', '/');
    }
  };
  const handleLogin = (u) => {
    setUser(u);
    setAuthed(true);
    const isAdmin = u.role === 'admin' || u.role === 'co-admin';
    setAdminMode(isAdmin);
    setScreen(isAdmin ? 'admin-dashboard' : 'home');
  };
  const handleLogout = async () => {
    try {
      if (window.firebaseAuthBridge && window.firebaseAuthBridge.signOutGoogle) {
        await window.firebaseAuthBridge.signOutGoogle();
      }
    } catch (e) { console.error(e); }
    setAuthed(false);
    setUser(null);
    setAdminMode(false);
    setScreen('home');
  };

  if (authLoading) {
    return (
      <React.Fragment>
        <div className="aurora"><span /></div>
        <div className="aurora-noise"></div>
        <div style={{ display: 'grid', placeItems: 'center', height: '100vh' }}>
          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 16, opacity: 0.55 }}>
            <div className="brand-mark" style={{ width: 52, height: 52, borderRadius: 13 }}>
              <svg width="26" height="26" viewBox="0 0 24 24" fill="currentColor">
                <polygon points="9.2,5.5 22.8,2.8 22.8,6.3 9.2,9"/>
                <rect x="9.2" y="5.5" width="1.8" height="12.5" rx="0.9"/>
                <rect x="21" y="2.8" width="1.8" height="12.7" rx="0.9"/>
                <ellipse cx="7" cy="18" rx="3.5" ry="2.5" transform="rotate(-15 7 18)"/>
                <ellipse cx="19" cy="15.5" rx="3.5" ry="2.5" transform="rotate(-15 19 15.5)"/>
              </svg>
            </div>
            <div style={{ fontSize: 13, color: 'var(--fg-2)' }}>Loading…</div>
          </div>
        </div>
      </React.Fragment>
    );
  }

  if (!authed) {
    // Legal/info pages are publicly accessible without login
    if (LEGAL_SCREENS.includes(screen)) {
      const goBack = () => handleNavigate('home');
      return (
        <React.Fragment>
          <div className="aurora"><span /></div>
          <div className="aurora-noise"></div>
          <div style={{ height: '100vh', padding: 'var(--space-5)', overflowY: 'auto', boxSizing: 'border-box' }}>
            <div style={{ maxWidth: 760, margin: '0 auto', paddingTop: 'var(--space-4)' }}>
              {/* Mini brand header */}
              <div className="row gap-3" style={{ alignItems: 'center', marginBottom: 'var(--space-5)' }}>
                <div className="brand-mark" style={{ width: 32, height: 32, borderRadius: 8 }}>
                  <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
                    <polygon points="9.2,5.5 22.8,2.8 22.8,6.3 9.2,9"/>
                    <rect x="9.2" y="5.5" width="1.8" height="12.5" rx="0.9"/>
                    <rect x="21" y="2.8" width="1.8" height="12.7" rx="0.9"/>
                    <ellipse cx="7" cy="18" rx="3.5" ry="2.5" transform="rotate(-15 7 18)"/>
                    <ellipse cx="19" cy="15.5" rx="3.5" ry="2.5" transform="rotate(-15 19 15.5)"/>
                  </svg>
                </div>
                <span style={{ fontWeight: 700, fontSize: 15 }}>AI Music Studio</span>
                <span className="spacer" />
                <button className="btn btn-glass btn-sm" onClick={goBack}>
                  <Icon name="arrow-left" size={13} /> Back to login
                </button>
              </div>
            </div>
            {screen === 'about'   && <AboutScreen   onNavigate={handleNavigate} />}
            {screen === 'privacy' && <PrivacyScreen onBack={goBack} />}
            {screen === 'terms'   && <TermsScreen   onBack={goBack} />}
            {screen === 'contact' && <ContactScreen onBack={goBack} />}
          </div>
        </React.Fragment>
      );
    }
    return (
      <React.Fragment>
        <div className="aurora"><span /></div>
        <div className="aurora-noise"></div>
        <AuthScreen
          onLogin={handleLogin}
          theme={tweaks.theme}
          onToggleTheme={() => setTweaks('theme', tweaks.theme === 'dark' ? 'light' : 'dark')}
          onNavigate={handleNavigate}
        />
      </React.Fragment>
    );
  }

  const userNavItems = [
    { k: 'home', label: 'Home', icon: 'home' },
    { k: 'tracks', label: 'Tracks', icon: 'compass' },
    { k: 'trending', label: 'Trending', icon: 'flame' },
    { k: 'playlists', label: 'Playlists', icon: 'list' },
    { k: 'profile', label: 'Profile', icon: 'user' },
  ];
  const adminNavItems = [
    { k: 'admin-dashboard', label: 'Dashboard', icon: 'gauge' },
    { k: 'admin-tracks', label: 'Tracks', icon: 'plus' },
    { k: 'admin-moderation', label: 'Moderation', icon: 'flag', badge: (window.COMMENTS || COMMENTS).filter(c => c.flagged || c.reported).length || null },
    { k: 'admin-users', label: 'Users', icon: 'users' },
    { k: 'admin-notifications', label: 'Notifications', icon: 'bell' },
  ];

  // Search results dropdown (up to 5 tracks matching query)
  const searchResults = searchQuery.trim()
    ? (window.TRACKS || TRACKS).filter(t =>
        t.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
        (t.artist || '').toLowerCase().includes(searchQuery.toLowerCase())
      ).slice(0, 5)
    : [];
  const showSearchDrop = searchFocused && searchResults.length > 0;

  return (
    <React.Fragment>
      {tweaks.auroraOn && <div className="aurora"><span /></div>}
      <div className="aurora-noise"></div>

      <div className="app">
        {/* Sidebar */}
        <aside className="sidebar glass">
          <div className="brand">
            <div className="brand-mark">
              <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
                <polygon points="9.2,5.5 22.8,2.8 22.8,6.3 9.2,9"/>
                <rect x="9.2" y="5.5" width="1.8" height="12.5" rx="0.9"/>
                <rect x="21" y="2.8" width="1.8" height="12.7" rx="0.9"/>
                <ellipse cx="7" cy="18" rx="3.5" ry="2.5" transform="rotate(-15 7 18)"/>
                <ellipse cx="19" cy="15.5" rx="3.5" ry="2.5" transform="rotate(-15 19 15.5)"/>
              </svg>
            </div>
            <div className="col">
              <div className="brand-name">AI Music Studio</div>
              <div className="brand-tag">Where AI creates heat</div>
            </div>
          </div>

          <div className="nav-section">
            <div className="nav-label">Listen</div>
            {userNavItems.map(item => (
              <button
                key={item.k}
                className={`nav-item ${screen === item.k && !adminMode ? 'active' : ''}`}
                onClick={() => { setAdminMode(false); setScreen(item.k); }}
              >
                <Icon name={item.icon} size={16} />
                <span>{item.label}</span>
              </button>
            ))}
          </div>

          {(user.role === 'admin' || user.role === 'co-admin') && (
            <div className="nav-section">
              <div className="nav-label">Admin</div>
              {adminNavItems.map(item => (
                <button
                  key={item.k}
                  className={`nav-item ${screen === item.k && adminMode ? 'active' : ''}`}
                  onClick={() => { setAdminMode(true); setScreen(item.k); }}
                >
                  <Icon name={item.icon} size={16} />
                  <span style={{ flex: 1, textAlign: 'left' }}>{item.label}</span>
                  {item.badge && <span className="pill warn">{item.badge}</span>}
                </button>
              ))}
            </div>
          )}

          <div className="sidebar-foot">
            <div className="row gap-3" style={{ padding: '8px 12px', borderRadius: 12, background: 'var(--glass-highlight)' }}>
              <Avatar name={user.name} size="sm" hue={user.hue} />
              <div className="col" style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 12, fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{user.name}</div>
                <div className="fg-3 mono" style={{ fontSize: 10 }}>{user.role === 'admin' ? 'Admin' : user.role === 'co-admin' ? 'Co-admin' : `@${user.handle}`}</div>
              </div>
              <button className="icon-btn" onClick={handleLogout} title="Log out"><Icon name="logout" size={14} /></button>
            </div>
            <FooterLinks onNavigate={handleNavigate} style={{ padding: '6px 4px' }} />
          </div>
        </aside>

        {/* Main */}
        <main className="main glass">
          <div className="topbar">
            {/* Search with live dropdown */}
            <div className="search" style={{ position: 'relative' }}>
              <Icon name="search" size={14} />
              <input
                ref={searchInputRef}
                placeholder="Search tracks, artists…"
                value={searchQuery}
                onChange={e => setSearchQuery(e.target.value)}
                onFocus={() => {
                  clearTimeout(searchBlurTimer.current);
                  setSearchFocused(true);
                }}
                onBlur={() => {
                  // Delay so clicks on dropdown items register first
                  searchBlurTimer.current = setTimeout(() => setSearchFocused(false), 200);
                }}
                onKeyDown={e => {
                  if (e.key === 'Escape') { setSearchQuery(''); searchInputRef.current?.blur(); }
                  if (e.key === 'Enter' && searchQuery.trim()) {
                    setAdminMode(false);
                    setScreen('tracks');
                    searchInputRef.current?.blur();
                  }
                }}
              />
              {searchQuery
                ? <button className="icon-btn" style={{ width: 18, height: 18, opacity: 0.5, flexShrink: 0 }}
                    onMouseDown={e => { e.preventDefault(); setSearchQuery(''); }}
                  ><Icon name="x" size={10} /></button>
                : <span className="kbd">⌘K</span>
              }
              {/* Search dropdown */}
              {showSearchDrop && (
                <div className="glass glass-strong" style={{
                  position: 'absolute', top: 'calc(100% + 6px)', left: 0, right: 0,
                  zIndex: 300, borderRadius: 12, border: '1px solid var(--line)',
                  padding: 6, boxShadow: 'var(--shadow-2)',
                }}>
                  {searchResults.map(t => (
                    <button key={t.id}
                      onMouseDown={e => { e.preventDefault(); handleOpenTrack(t); setSearchQuery(''); setSearchFocused(false); }}
                      style={{
                        display: 'flex', width: '100%', alignItems: 'center', gap: 10,
                        padding: '7px 10px', background: 'none', border: 'none',
                        color: 'var(--fg-0)', cursor: 'pointer', borderRadius: 8, textAlign: 'left',
                      }}
                      onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-1)'}
                      onMouseLeave={e => e.currentTarget.style.background = 'none'}
                    >
                      <div style={{ width: 34, height: 34, borderRadius: 6, overflow: 'hidden', flexShrink: 0, position: 'relative' }}>
                        <Art index={t.art} />
                      </div>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ fontSize: 13, fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{t.title}</div>
                        <div className="fg-2 mono" style={{ fontSize: 11 }}>{t.artist}</div>
                      </div>
                      <span className={`track-tag ${t.tag === 'ai' ? 'ai' : t.tag === 'human' ? 'human' : ''}`} style={{ fontSize: 9, flexShrink: 0 }}>{t.tag}</span>
                    </button>
                  ))}
                  {searchQuery.trim() && (
                    <button
                      onMouseDown={e => { e.preventDefault(); setAdminMode(false); setScreen('tracks'); setSearchFocused(false); }}
                      style={{
                        display: 'flex', width: '100%', alignItems: 'center', gap: 8,
                        padding: '7px 10px', background: 'none', border: 'none',
                        color: 'var(--accent)', cursor: 'pointer', borderRadius: 8,
                        fontSize: 12, fontWeight: 600, marginTop: 2, borderTop: '1px solid var(--line)',
                      }}
                      onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-1)'}
                      onMouseLeave={e => e.currentTarget.style.background = 'none'}
                    >
                      <Icon name="search" size={12} /> See all results for "{searchQuery}"
                    </button>
                  )}
                </div>
              )}
            </div>

            <div className="topbar-actions">
              <button
                className="icon-btn"
                onClick={() => setTweaks('theme', tweaks.theme === 'dark' ? 'light' : 'dark')}
                title="Toggle theme"
              >
                <Icon name={tweaks.theme === 'dark' ? 'sun' : 'moon'} size={16} />
              </button>
              <div ref={bellRef} style={{ position: 'relative' }}>
                <button className="icon-btn" onClick={openBell}>
                  <Icon name="bell" size={16} />
                  {unreadCount > 0 && <span className="badge"></span>}
                </button>
                {notifOpen && (
                  <div className="notif-dropdown glass">
                    <div className="notif-dropdown-head">
                      <Icon name="bell" size={13} style={{ color: 'var(--accent)' }} />
                      <span style={{ fontWeight: 600, fontSize: 13 }}>Notifications</span>
                      {notifications.length > 0 && (
                        <span className="pill" style={{ fontSize: 10, marginLeft: 4 }}>{notifications.length}</span>
                      )}
                      <span className="spacer" />
                      <button className="icon-btn" style={{ width: 22, height: 22 }} onClick={() => setNotifOpen(false)}>
                        <Icon name="x" size={11} />
                      </button>
                    </div>
                    {notifications.length === 0 ? (
                      <div style={{ padding: '28px 16px', textAlign: 'center', color: 'var(--fg-3)', fontSize: 12 }}>
                        No notifications yet
                      </div>
                    ) : (
                      <div style={{ maxHeight: 340, overflowY: 'auto' }}>
                        {notifications.slice(0, 10).map((n, i) => (
                          <div key={n.id || i} className="notif-item">
                            <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--fg-0)' }}>{n.title || 'Announcement'}</div>
                            <div style={{ fontSize: 11, color: 'var(--fg-2)', marginTop: 2 }}>{n.message}</div>
                            <div style={{ fontSize: 10, color: 'var(--fg-3)', fontFamily: 'var(--font-mono)', marginTop: 4 }}>{fmtTs(n.timestamp)}</div>
                          </div>
                        ))}
                      </div>
                    )}
                  </div>
                )}
              </div>
              <button className="btn btn-glass btn-sm" onClick={() => setShowCreate(true)}>
                <Icon name="plus" size={12} /> New playlist
              </button>
            </div>
          </div>

          <div className="scroll-area">
            {!adminMode && screen === 'home' && (
              <HomeScreen onPlay={handlePlay} onOpenTrack={handleOpenTrack} onNavigate={handleNavigate} onShare={handleShare} />
            )}
            {!adminMode && screen === 'tracks' && (
              <TracksScreen
                onPlay={handlePlay}
                onOpenTrack={handleOpenTrack}
                onShare={handleShare}
                currentTrack={currentTrack}
                searchQuery={searchQuery}
              />
            )}
            {!adminMode && screen === 'trending' && (
              <TrendingScreen onPlay={handlePlay} onOpenTrack={handleOpenTrack} />
            )}
            {!adminMode && screen === 'track' && openTrack && (
              <TrackDetailScreen
                track={openTrack}
                onPlay={handlePlay}
                onShare={handleShare}
                currentTrack={currentTrack}
                isPlaying={isPlaying}
                likedTrackIds={likedTrackIds}
                onToggleLike={handleToggleLike}
              />
            )}
            {!adminMode && screen === 'playlists' && (
              <PlaylistsScreen onShare={handleShare} onCreatePlaylist={() => setShowCreate(true)} onOpenTrack={handleOpenTrack} onPlay={handlePlay} />
            )}
            {!adminMode && screen === 'profile' && (
              <ProfileScreen
                user={user}
                onPlay={handlePlay}
                onOpenTrack={handleOpenTrack}
                onShare={handleShare}
                onCreatePlaylist={() => setShowCreate(true)}
                onLogout={handleLogout}
                onUpdateUser={(updates) => setUser(u => ({ ...u, ...updates }))}
                onEditProfile={() => setShowEditProfile(true)}
                theme={tweaks.theme}
                onToggleTheme={() => setTweaks('theme', tweaks.theme === 'dark' ? 'light' : 'dark')}
                likedTrackIds={likedTrackIds}
              />
            )}
            {adminMode && screen === 'admin-dashboard' && <AdminDashboard onNavigate={handleNavigate} onPlay={handlePlay} />}
            {adminMode && screen === 'admin-tracks' && <AdminTracks user={user} onPlay={handlePlay} />}
            {adminMode && screen === 'admin-moderation' && <AdminModeration />}
            {adminMode && screen === 'admin-users' && <AdminUsers user={user} />}
            {adminMode && screen === 'admin-notifications' && (
              <AdminNotifications onNotifSent={n => setNotifications(ns => [n, ...ns])} />
            )}
            {adminMode && !screen.startsWith('admin') && !LEGAL_SCREENS.includes(screen) && <AdminDashboard onNavigate={handleNavigate} />}
            {/* Legal / info pages — accessible regardless of admin mode */}
            {screen === 'about'   && <AboutScreen   onNavigate={handleNavigate} onBack={() => handleNavigate('home')} />}
            {screen === 'privacy' && <PrivacyScreen onBack={() => handleNavigate('home')} />}
            {screen === 'terms'   && <TermsScreen   onBack={() => handleNavigate('home')} />}
            {screen === 'contact' && <ContactScreen onBack={() => handleNavigate('home')} />}
          </div>
        </main>

        {/* Player bar */}
        {currentTrack && (
          <footer className="player-bar glass">
            <div className="row gap-3" style={{ width: 260, minWidth: 200 }}>
              <div className="np-cover"><Art index={currentTrack.art} /></div>
              <div className="np-meta">
                <div className="np-title">{currentTrack.title}</div>
                <div className="np-artist">{currentTrack.artist} · {currentTrack.author}</div>
              </div>
              <div className={`eq-bars ${isPlaying ? 'playing' : ''}`} style={{ marginLeft: 4 }}>
                {[1,2,3,4,5].map(i => <span key={i} className={`eq-bar eq-bar-${i}`} />)}
              </div>
            </div>

            <div className="col" style={{ flex: 1, gap: 4 }}>
              <div className="transport" style={{ justifyContent: 'center' }}>
                <button className="icon-btn" style={{ color: shuffle ? 'var(--accent)' : undefined, background: shuffle ? 'var(--accent-soft)' : undefined }} onClick={() => setShuffle(s => !s)}><Icon name="shuffle" size={14} /></button>
                <button className="icon-btn" onClick={() => skipTrack(-1)}><Icon name="skip-back" size={14} /></button>
                <button className="play" onClick={() => setIsPlaying(p => !p)}>
                  <Icon name={isPlaying ? 'pause' : 'play'} size={14} />
                </button>
                <button className="icon-btn" onClick={() => skipTrack(1)}><Icon name="skip-fwd" size={14} /></button>
                <button className="icon-btn" style={{ color: repeat ? 'var(--accent)' : undefined, background: repeat ? 'var(--accent-soft)' : undefined }} onClick={() => setRepeat(r => !r)}><Icon name="repeat" size={14} /></button>
              </div>
              <div className="scrubber">
                <span className="time">{formatTime(progress * currentTrack.durationSec)}</span>
                <div className="scrubber-bar" onClick={e => {
                  const r = e.currentTarget.getBoundingClientRect();
                  const pct = (e.clientX - r.left) / r.width;
                  setProgress(pct);
                  if (audioRef.current && currentTrack?.audioUrl) {
                    audioRef.current.currentTime = pct * currentTrack.durationSec;
                  }
                }}>
                  <div className="fill" style={{ width: `${progress * 100}%` }}></div>
                </div>
                <span className="time r">{currentTrack.duration}</span>
              </div>
            </div>

            <div className="row gap-3" style={{ width: 200, justifyContent: 'flex-end' }}>
              <button className="icon-btn" onClick={() => handleShare(currentTrack)}><Icon name="share" size={14} /></button>
              <div className="volume">
                <Icon name={volume === 0 ? 'mute' : 'volume'} size={14} />
                <input type="range" min="0" max="1" step="0.01" value={volume} onChange={e => setVolume(parseFloat(e.target.value))} />
              </div>
            </div>
          </footer>
        )}

        {/* Mobile bottom nav */}
        {(() => {
          const isAdmin = user?.role === 'admin' || user?.role === 'co-admin';
          const coreItems = isAdmin
            ? (adminMode ? adminNavItems.slice(0, 4) : [
                { k: 'home', label: 'Home', icon: 'home' },
                { k: 'tracks', label: 'Tracks', icon: 'compass' },
                { k: 'playlists', label: 'Playlists', icon: 'list' },
                { k: 'profile', label: 'Profile', icon: 'user' },
              ])
            : userNavItems;
          return (
            <nav className="mob-nav glass">
              {coreItems.map(item => (
                <button key={item.k} className={`mob-nav-btn${screen === item.k ? ' active' : ''}`}
                  onClick={() => handleNavigate(item.k)}>
                  <Icon name={item.icon} size={20} />
                  <span>{item.label}</span>
                </button>
              ))}
              {isAdmin && (
                <button
                  className={`mob-nav-btn mob-nav-switch${adminMode ? ' admin-active' : ''}`}
                  onClick={() => { setAdminMode(a => !a); setScreen(adminMode ? 'home' : 'admin-dashboard'); }}
                >
                  <Icon name={adminMode ? 'headphones' : 'gauge'} size={20} />
                  <span>{adminMode ? 'Listen' : 'Admin'}</span>
                </button>
              )}
            </nav>
          );
        })()}
      </div>

      {/* Modals */}
      <EditProfileModal
        open={showEditProfile}
        user={user}
        onClose={() => setShowEditProfile(false)}
        onSave={async (updates) => {
          setUser(u => ({ ...u, ...updates }));
          setShowEditProfile(false);
          toast('Profile updated', 'success');
          try {
            const match = (window.USERS || []).find(u => u.email === user?.email);
            if (match?.id) await window.dbHelpers?.updateUser(match.id, updates);
          } catch(e) { console.error(e); }
        }}
      />
      <ShareModal
        open={!!shareTarget}
        onClose={() => setShareTarget(null)}
        title={shareTarget?.playlist ? shareTarget.playlist.name : shareTarget?.title}
        subtitle={shareTarget?.playlist ? 'Playlist' : (shareTarget?.artist && `by ${shareTarget.artist}`)}
        url={shareTarget?.playlist
          ? `${window.location.host}/p/${shareTarget.playlist.id}`
          : `${window.location.host}/t/${shareTarget?.id}`}
      />
      <CreatePlaylistModal
        open={showCreate}
        onClose={() => setShowCreate(false)}
        onCreate={async (data) => {
          const playlist = {
            id: 'pl' + Date.now(),
            name: data.name,
            shared: data.isPublic,
            tracks: [],
            plays: 0,
            cover: Math.floor(Math.random() * 8),
            createdBy: user?.handle || 'listener',
          };
          window.PLAYLISTS = [playlist, ...(window.PLAYLISTS || [])];
          window.dispatchEvent(new CustomEvent('dataLoaded'));
          try { await window.dbHelpers?.addPlaylist(playlist); } catch(e) { console.error(e); }
        }}
      />

      {/* Tweaks */}
      <TweaksPanel title="Tweaks">
        <TweakSection label="Theme">
          <TweakRadio label="Mode" value={tweaks.theme}
            options={[{ value: 'dark', label: 'Dark' }, { value: 'light', label: 'Light' }]}
            onChange={v => setTweaks('theme', v)} />
        </TweakSection>
        <TweakSection label="Accent">
          <TweakColor label="Palette"
            value={tweaks.accent}
            options={ACCENT_PALETTES}
            onChange={v => setTweaks('accent', v)} />
        </TweakSection>
        <TweakSection label="Type">
          <TweakSelect label="Font pair" value={tweaks.fontPair}
            options={[
              { value: 'geist', label: 'Geist Sans' },
              { value: 'serif', label: 'Geist + Serif' },
              { value: 'grotesk', label: 'Space Grotesk' },
            ]}
            onChange={v => setTweaks('fontPair', v)} />
        </TweakSection>
        <TweakSection label="Density & feel">
          <TweakRadio label="Density" value={tweaks.density}
            options={[
              { value: 'compact', label: 'Compact' },
              { value: 'comfortable', label: 'Comfy' },
              { value: 'spacious', label: 'Spacious' },
            ]}
            onChange={v => setTweaks('density', v)} />
          <TweakSlider label="Glass blur" min={0} max={48} step={2} value={tweaks.glassBlur} unit="px"
            onChange={v => setTweaks('glassBlur', v)} />
          <TweakToggle label="Aurora backdrop" value={tweaks.auroraOn}
            onChange={v => setTweaks('auroraOn', v)} />
        </TweakSection>
        <TweakSection label="Demo">
          <TweakButton label="Trigger toast" onClick={() => toast('Sample toast notification', 'info')} />
          <TweakButton label={(user?.role === 'admin' || user?.role === 'co-admin') ? 'Toggle admin mode' : 'Log out'}
            onClick={(user?.role === 'admin' || user?.role === 'co-admin') ? () => setAdminMode(a => !a) : handleLogout} />
        </TweakSection>
      </TweaksPanel>
    </React.Fragment>
  );
}

// Mount
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <ToastProvider>
    <App />
  </ToastProvider>
);
