// ===========================================================
// DEAD SAILOR · PROJECT DOCK · SHARED COMPONENTS
// ===========================================================

const { useState, useEffect, useMemo, useRef, useCallback, Fragment } = React;
var API = window.API;

// ---- Tiny SVG icons (consistent stroke, no decoration) ----
const Ico = {
  arrow: (p={}) => <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.2" {...p}><path d="M2 6h8M7 3l3 3-3 3"/></svg>,
  arrowL: (p={}) => <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.2" {...p}><path d="M10 6H2M5 3L2 6l3 3"/></svg>,
  check: (p={}) => <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M2.5 6.5L5 9l4.5-5.5"/></svg>,
  close: (p={}) => <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" {...p}><path d="M3 3l6 6M9 3l-6 6"/></svg>,
  plus: (p={}) => <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" {...p}><path d="M6 2v8M2 6h8"/></svg>,
  download: (p={}) => <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M6 2v6M3 6l3 3 3-3M2 10h8"/></svg>,
  upload: (p={}) => <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M7 10V3M4 6l3-3 3 3M2 12h10"/></svg>,
  bell: (p={}) => <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M7 1v1M11 11H3l1-2V6a3 3 0 016 0v3l1 2zM5 11a2 2 0 004 0"/></svg>,
  search: (p={}) => <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.2" {...p}><circle cx="5" cy="5" r="3"/><path d="M7.5 7.5L10 10"/></svg>,
  dot: (p={}) => <svg width="6" height="6" viewBox="0 0 6 6" {...p}><circle cx="3" cy="3" r="2" fill="currentColor"/></svg>,
  dash: (p={}) => <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.2" {...p}><path d="M3 6h6"/></svg>,
  pin: (p={}) => <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.2" {...p}><circle cx="6" cy="6" r="1.5"/><circle cx="6" cy="6" r="4.5"/></svg>,
  link: (p={}) => <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" {...p}><path d="M5 3h1a3 3 0 010 6H5M7 9H6a3 3 0 010-6h1M4.5 6h3"/></svg>,
  ext: (p={}) => <svg width="10" height="10" viewBox="0 0 10 10" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" {...p}><path d="M4 2H2v6h6V6M5 2h3v3M5 5l3-3"/></svg>,
  drag: (p={}) => <svg width="14" height="14" viewBox="0 0 14 14" fill="none" {...p}><circle cx="5" cy="4" r="1" fill="currentColor"/><circle cx="5" cy="7" r="1" fill="currentColor"/><circle cx="5" cy="10" r="1" fill="currentColor"/><circle cx="9" cy="4" r="1" fill="currentColor"/><circle cx="9" cy="7" r="1" fill="currentColor"/><circle cx="9" cy="10" r="1" fill="currentColor"/></svg>,
  trash: (p={}) => <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" {...p}><path d="M2 3h8M4 3V2h4v1M3 3l1 7h4l1-7M5 5v4M7 5v4"/></svg>,
  edit: (p={}) => <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M2 10l1-3 5-5 2 2-5 5-3 1zM7 3l2 2"/></svg>,
  view: (p={}) => <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.2" {...p}><path d="M1 6s2-3.5 5-3.5S11 6 11 6s-2 3.5-5 3.5S1 6 1 6z"/><circle cx="6" cy="6" r="1.3"/></svg>,
  file: (p={}) => <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 1h5l3 3v9H3V1z"/><path d="M8 1v3h3"/></svg>,
  flag: (p={}) => <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 1v12M3 2h7l-1.5 2L10 6H3"/></svg>,
  layers: (p={}) => <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M7 1l6 3-6 3-6-3 6-3zM1 7l6 3 6-3M1 10l6 3 6-3"/></svg>,
  inbox: (p={}) => <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M1 8h3l1 2h4l1-2h3M1 8l2-6h8l2 6v5H1V8z"/></svg>,
  grid: (p={}) => <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" {...p}><rect x="1" y="1" width="5" height="5"/><rect x="8" y="1" width="5" height="5"/><rect x="1" y="8" width="5" height="5"/><rect x="8" y="8" width="5" height="5"/></svg>,
  user: (p={}) => <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" {...p}><circle cx="7" cy="5" r="2.5"/><path d="M2 13c0-3 2-5 5-5s5 2 5 5"/></svg>,
  users: (p={}) => <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" {...p}><circle cx="5" cy="5" r="2"/><circle cx="10" cy="6" r="1.5"/><path d="M1 12c0-2.2 1.8-4 4-4s4 1.8 4 4M9 12c0-1.5.7-2.8 1.8-3.5 1.2.5 2.2 1.7 2.2 3.5"/></svg>,
  gear: (p={}) => <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" {...p}><circle cx="7" cy="7" r="2"/><path d="M7 1v2M7 11v2M1 7h2M11 7h2M2.6 2.6l1.4 1.4M10 10l1.4 1.4M2.6 11.4L4 10M10 4l1.4-1.4"/></svg>,
  out: (p={}) => <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" {...p}><path d="M6 13H2V1h4M9 4l3 3-3 3M5 7h7"/></svg>,
  home: (p={}) => <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M2 7l5-5 5 5v6H8V9H6v4H2V7z"/></svg>,
  briefcase: (p={}) => <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" {...p}><rect x="1" y="4" width="12" height="8"/><path d="M5 4V2h4v2M1 8h12"/></svg>,
  check2: (p={}) => <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="7" cy="7" r="5.5"/><path d="M5 7l1.5 1.5L9 6"/></svg>,
  refresh: (p={}) => <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M2 7a5 5 0 018-3.5L11 4M12 7a5 5 0 01-8 3.5L3 10M11 2v2H9M3 12v-2h2"/></svg>,
  send: (p={}) => <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M13 1L1 6l5 2 2 5L13 1zM6 8l3-3"/></svg>,
  chat: (p={}) => <svg width="13" height="13" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M13 3.5a3 3 0 00-3-3H4a3 3 0 00-3 3v5a3 3 0 003 3h1l.5 1.5 2-1.5h2.5a3 3 0 003-3v-5z"/></svg>,
};
window.Ico = Ico;

// ---- Button ----
function Button({ kind='default', size, icon, arrow, children, onClick, disabled, type, ...rest }){
  const cls = ['btn'];
  if(kind === 'primary') cls.push('btn-primary');
  if(kind === 'signal') cls.push('btn-signal');
  if(kind === 'ghost') cls.push('btn-ghost');
  if(kind === 'danger') cls.push('btn-danger');
  if(size === 'sm') cls.push('btn-sm');
  return (
    <button type={type || 'button'} className={cls.join(' ')} onClick={onClick} disabled={disabled} {...rest}>
      {icon}
      <span>{children}</span>
      {arrow && <span className="arr">{Ico.arrow()}</span>}
    </button>
  );
}
window.Button = Button;

// ---- Chip / status ----
function Chip({ status='idle', children, live }){
  return (
    <span className={`chip ${status} ${live ? 'live':''}`}>
      <span className="dot"></span>{children}
    </span>
  );
}
window.Chip = Chip;

// Map status keys → chip variants
const STATUS_MAP = {
  approved: 'approved',
  waiting: 'waiting',
  production: 'production',
  review: 'review',
  delay: 'delay',
  idle: 'idle',
  approval: 'waiting',
  'brief-received': 'review',
  analysis: 'review',
  planning: 'production',
  final: 'approved',
  done: 'archived',
  'in-analysis': 'waiting',
  awaiting: 'review',
  addendum: 'delay',
};
function statusChip(key, label){
  return <Chip status={STATUS_MAP[key] || 'idle'}>{label}</Chip>;
}
window.statusChip = statusChip;

// ---- Avatar ----
function Avatar({ initials, size=36 }){
  return (
    <span className="avatar" style={{width:size, height:size, fontSize: size*0.5, display:'grid', placeItems:'center', border:'1px solid var(--steel-3)', background:'var(--hull-3)', fontFamily:'var(--serif)', fontStyle:'italic', color:'var(--bone)'}}>{initials}</span>
  );
}
window.Avatar = Avatar;

// ---- Sidebar ----
function Sidebar({ profile, current, navigate }){
  const [user, setUser] = React.useState(null);
  const [briefingsCount, setBriefingsCount] = React.useState(0);

  React.useEffect(() => {
    if (API.token) {
      API.me().then(setUser).catch(() => {});
      
      // Carrega contagem real de briefings pendentes
      API.getBriefings()
        .then(list => {
          const pendingCount = list.filter(b => b.status === 'pending' || b.status === 'in-analysis').length;
          setBriefingsCount(pendingCount);
        })
        .catch(() => {});
    }
  }, [profile]);

  const D = window.DS_DATA;

  const clientNav = [
    { key:'home',         label:'Dashboard',    icon: Ico.home() },
    { key:'projects',     label:'Meus projetos', icon: Ico.briefcase() },
    { key:'company',      label:'Minha empresa',icon: Ico.user() },
  ];

  const adminNav = [];
  if (user) {
    if (user.role === 'admin') {
      adminNav.push(
        { key:'home',         label:'Dashboard',    icon: Ico.home() },
        { key:'briefings',    label:'Briefings',    icon: Ico.inbox(), badge: briefingsCount > 0 ? String(briefingsCount) : null },
        { key:'projects',     label:'Projetos',     icon: Ico.briefcase() },
        { key:'clients',      label:'Clientes',     icon: Ico.users() },
        { key:'settings',     label:'Configurações',icon: Ico.gear() }
      );
    } else if (user.role === 'leader') {
      adminNav.push(
        { key:'home',         label:'Dashboard',    icon: Ico.home() },
        { key:'briefings',    label:'Briefings',    icon: Ico.inbox(), badge: briefingsCount > 0 ? String(briefingsCount) : null },
        { key:'projects',     label:'Projetos',     icon: Ico.briefcase() },
        { key:'clients',      label:'Clientes',     icon: Ico.users() }
      );
    } else { // collaborator
      adminNav.push(
        { key:'projects',     label:'Projetos',     icon: Ico.briefcase() }
      );
    }
  } else {
    // Fallback inicial
    adminNav.push(
      { key:'home',         label:'Dashboard',    icon: Ico.home() },
      { key:'projects',     label:'Projetos',     icon: Ico.briefcase() }
    );
  }
  const nav = profile === 'client' ? clientNav : adminNav;

  let whoRole = 'Cliente · Acesso';
  if (profile !== 'client') {
    if (user?.role === 'admin') whoRole = 'Admin · Controle Total';
    else if (user?.role === 'leader') whoRole = 'Líder · Gestão';
    else if (user?.role === 'collaborator') whoRole = 'Colaborador · Projetos';
    else whoRole = 'Equipe · Dead Sailor';
  }

  const who = profile === 'client'
    ? { name: user?.name || D.currentClient.name, role: 'Cliente · Acesso completo', av: (user?.name?.[0] || D.currentClient.avatar) }
    : { name: user?.name || 'Denis Paganini',    role: whoRole,    av: (user?.name?.[0] || 'D') };

  return (
    <aside className="sidebar">
      <div className="top">
        <div className="brand-row">
          <span className="logo" aria-label="Dead Sailor"></span>
        </div>
        <div className="product">
          <span>Project Dock</span>
          <span className="v">v0.1</span>
        </div>
      </div>

      <div className="who">
        <span className="avatar">{who.av}</span>
        <div className="who-info">
          <span className="name">{who.name}</span>
          <span className="role">{who.role}</span>
        </div>
        <span className="pulse"></span>
      </div>

      <nav>
        <div className="group-label">// Navegação</div>
        {nav.map(item => (
          <a key={item.key}
             className={current === item.key ? 'active':''}
             onClick={() => navigate(item.key)}>
            <span className="ic">{item.icon}</span>
            <span>{item.label}</span>
            {item.badge && <span className="badge">{item.badge}</span>}
          </a>
        ))}
        <div style={{marginTop: 'auto', display: 'flex', flexDirection: 'column', gap: 2}}>
          <a onClick={() => window.dispatchEvent(new CustomEvent('ds-show-change-password'))} style={{cursor: 'pointer'}}>
            <span className="ic">{Ico.gear()}</span>
            <span>Alterar Senha</span>
          </a>
          <a onClick={() => navigate('logout')} style={{cursor: 'pointer'}}>
            <span className="ic">{Ico.out()}</span>
            <span>Sair</span>
          </a>
        </div>
      </nav>

      <div className="bottom-meta">
        <span>DS / SYSTEM 001</span>
        <span>v0.1</span>
      </div>
    </aside>
  );
}
window.Sidebar = Sidebar;

// ---- Topbar ----
function Topbar({ crumb, profile }){
  const [isOpen, setIsOpen] = useState(false);
  const [notifications, setNotifications] = useState([]);
  const popoverRef = useRef(null);

  const loadNotifications = useCallback(async () => {
    if (!window.API?.getNotifications) return;
    try {
      const data = await window.API.getNotifications();
      setNotifications(data);
    } catch (e) {
      console.warn('Erro ao carregar notificações:', e);
    }
  }, []);

  useEffect(() => {
    loadNotifications();
    const timer = setInterval(loadNotifications, 15000);
    return () => clearInterval(timer);
  }, [loadNotifications]);

  useEffect(() => {
    if (!isOpen) return;
    function handleClickOutside(e) {
      if (popoverRef.current && !popoverRef.current.contains(e.target)) {
        setIsOpen(false);
      }
    }
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, [isOpen]);

  const unreadCount = notifications.filter(n => !n.read).length;

  const handleMarkAllRead = async (e) => {
    e.stopPropagation();
    if (!window.API?.markAllNotificationsRead) return;
    try {
      await window.API.markAllNotificationsRead();
      loadNotifications();
    } catch (e) {}
  };

  const handleItemClick = async (item) => {
    setIsOpen(false);
    if (window.API?.markNotificationRead) {
      try {
        await window.API.markNotificationRead(item.id);
        loadNotifications();
      } catch (e) {}
    }
    if (item.link) {
      const cleanPath = item.link.replace(/^#/, '');
      window.location.hash = cleanPath;
    }
  };

  function getNotifIcon(title) {
    const t = title.toLowerCase();
    if (t.includes('mensagem') || t.includes('chat')) return Ico.send({ width: 11, height: 11 });
    if (t.includes('briefing')) return Ico.inbox({ width: 11, height: 11 });
    if (t.includes('entrega') || t.includes('aprovad') || t.includes('revis')) return Ico.check2({ width: 11, height: 11 });
    return Ico.bell({ width: 11, height: 11 });
  }

  function formatTimeAgo(dateStr) {
    try {
      const d = new Date(dateStr);
      const diffMs = Date.now() - d.getTime();
      const diffMins = Math.floor(diffMs / 60000);
      if (diffMins < 1) return 'Agora mesmo';
      if (diffMins < 60) return `há ${diffMins} min`;
      const diffHrs = Math.floor(diffMins / 60);
      if (diffHrs < 24) return `há ${diffHrs} ${diffHrs === 1 ? 'hora' : 'horas'}`;
      return d.toLocaleDateString('pt-BR', { day: 'numeric', month: 'short' });
    } catch(e) {
      return 'Algum tempo atrás';
    }
  }

  return (
    <header className="topbar" style={{ position: 'relative' }}>
      <style>{`
        .notif-popover {
          position: absolute;
          top: 100%;
          right: 24px;
          margin-top: 12px;
          width: 350px;
          background: rgba(10, 11, 12, 0.94);
          backdrop-filter: blur(20px);
          -webkit-backdrop-filter: blur(20px);
          border: 1px solid var(--steel-3);
          border-radius: 4px;
          box-shadow: 0 15px 35px rgba(0, 0, 0, 0.7), 0 0 15px rgba(0, 255, 102, 0.03);
          z-index: 1000;
          overflow: hidden;
          font-family: var(--sans);
          text-align: left;
          animation: notifFadeIn 0.2s cubic-bezier(0.16, 1, 0.3, 1) forwards;
        }

        @keyframes notifFadeIn {
          from { opacity: 0; transform: translateY(-8px); }
          to { opacity: 1; transform: translateY(0); }
        }

        .notif-header {
          display: flex;
          justify-content: space-between;
          align-items: center;
          padding: 14px 16px;
          border-bottom: 1px solid var(--steel-3);
          background: rgba(20, 21, 22, 0.4);
        }

        .notif-header .title {
          font-family: var(--mono);
          font-size: 10px;
          letter-spacing: 0.15em;
          color: var(--bone);
          display: flex;
          align-items: center;
          gap: 8px;
          text-transform: uppercase;
        }

        .notif-header .title .cnt {
          background: var(--signal);
          color: var(--abyss);
          font-family: var(--mono);
          font-size: 9px;
          font-weight: 600;
          padding: 1px 5px;
          border-radius: 20px;
          box-shadow: 0 0 8px var(--signal);
        }

        .notif-header .mark-all {
          font-family: var(--mono);
          font-size: 9px;
          letter-spacing: 0.05em;
          color: var(--fog-2);
          background: transparent;
          border: none;
          cursor: pointer;
          transition: color 0.2s;
          padding: 0;
          text-transform: uppercase;
          outline: none;
        }

        .notif-header .mark-all:hover {
          color: var(--signal);
        }

        .notif-list {
          max-height: 290px;
          overflow-y: auto;
        }

        .notif-list::-webkit-scrollbar {
          width: 4px;
        }
        .notif-list::-webkit-scrollbar-track {
          background: transparent;
        }
        .notif-list::-webkit-scrollbar-thumb {
          background: var(--steel-3);
          border-radius: 2px;
        }
        .notif-list::-webkit-scrollbar-thumb:hover {
          background: var(--steel-2);
        }

        .notif-item {
          display: flex;
          gap: 12px;
          padding: 14px 16px;
          border-bottom: 1px solid rgba(232, 226, 216, 0.04);
          cursor: pointer;
          transition: all 0.2s ease;
          position: relative;
        }

        .notif-item:last-child {
          border-bottom: none;
        }

        .notif-item.unread {
          background: rgba(0, 255, 102, 0.015);
        }

        .notif-item::before {
          content: '';
          position: absolute;
          left: 0;
          top: 0;
          bottom: 0;
          width: 2px;
          background: transparent;
          transition: background 0.2s;
        }

        .notif-item.unread::before {
          background: var(--signal);
          box-shadow: 0 0 6px var(--signal);
        }

        .notif-item:hover {
          background: rgba(232, 226, 216, 0.03);
        }

        .notif-item:hover::before {
          background: var(--signal);
        }

        .notif-icon {
          flex-shrink: 0;
          width: 24px;
          height: 24px;
          border-radius: 50%;
          border: 1px solid var(--steel-3);
          background: var(--hull-3);
          display: grid;
          place-items: center;
          color: var(--fog-2);
          transition: all 0.2s;
        }

        .notif-item:hover .notif-icon {
          border-color: var(--signal);
          color: var(--signal);
          box-shadow: 0 0 6px rgba(0, 255, 102, 0.1);
        }

        .notif-info {
          flex-grow: 1;
          display: flex;
          flex-direction: column;
          gap: 3px;
        }

        .notif-info .item-title {
          font-size: 11px;
          font-weight: 600;
          color: var(--bone);
          letter-spacing: 0.02em;
        }

        .notif-info .item-body {
          font-size: 10px;
          color: var(--fog-2);
          line-height: 1.4;
        }

        .notif-info .item-time {
          font-family: var(--mono);
          font-size: 8px;
          color: var(--steel-2);
          text-transform: uppercase;
          margin-top: 3px;
          letter-spacing: 0.05em;
        }

        .notif-empty {
          padding: 48px 24px;
          text-align: center;
          font-family: var(--mono);
          font-size: 10px;
          color: var(--fog-2);
          letter-spacing: 0.12em;
          display: flex;
          flex-direction: column;
          align-items: center;
          gap: 12px;
        }
      `}</style>

      <div className="crumb">
        {crumb.flatMap((c, i) => {
          const node = <span key={'c'+i} className={i === crumb.length-1 ? 'cur' : ''}>{c}</span>;
          return i === 0 ? [node] : [<span key={'s'+i} className="sep">/</span>, node];
        })}
      </div>
      <div className="topright">
        <div className="search">
          <span style={{color:'var(--fog-2)'}}>{Ico.search()}</span>
          <input placeholder="Buscar projetos, briefings, clientes…" />
          <span className="kbd">⌘ K</span>
        </div>
        
        <div style={{ position: 'relative' }} ref={popoverRef}>
          <button 
            className="icon-btn" 
            title="Notificações" 
            onClick={() => setIsOpen(!isOpen)}
            style={{ 
              position: 'relative',
              outline: 'none',
              background: isOpen ? 'rgba(232, 226, 216, 0.05)' : 'transparent',
              borderColor: isOpen ? 'var(--steel-2)' : 'var(--steel-3)'
            }}
          >
            {Ico.bell()}
            {unreadCount > 0 && (
              <span 
                className="ind" 
                style={{ 
                  background: 'var(--signal)', 
                  boxShadow: '0 0 8px var(--signal)',
                  position: 'absolute',
                  top: 8,
                  right: 8,
                  width: 6,
                  height: 6,
                  borderRadius: '50%'
                }}
              ></span>
            )}
          </button>

          {isOpen && (
            <div className="notif-popover">
              <div className="notif-header">
                <span className="title">
                  Notificações
                  {unreadCount > 0 && <span className="cnt">{unreadCount}</span>}
                </span>
                {unreadCount > 0 && (
                  <button className="mark-all" onClick={handleMarkAllRead}>
                    Limpar todas
                  </button>
                )}
              </div>
              <div className="notif-list">
                {notifications.length === 0 ? (
                  <div className="notif-empty">
                    {Ico.bell({ width: 16, height: 16, style: { color: 'var(--steel-3)' } })}
                    <span>// NENHUMA NOTIFICAÇÃO PENDENTE</span>
                  </div>
                ) : (
                  notifications.map(item => (
                    <div 
                      key={item.id} 
                      className={`notif-item ${!item.read ? 'unread' : ''}`}
                      onClick={() => handleItemClick(item)}
                    >
                      <div className="notif-icon">
                        {getNotifIcon(item.title)}
                      </div>
                      <div className="notif-info">
                        <span className="item-title">{item.title}</span>
                        <span className="item-body">{item.body}</span>
                        <span className="item-time">{formatTimeAgo(item.created_at)}</span>
                      </div>
                    </div>
                  ))
                )}
              </div>
            </div>
          )}
        </div>

        <div className="now">
          <span className="dot"></span>
          <span>25 MAI 2026</span>
        </div>
      </div>
    </header>
  );
}
window.Topbar = Topbar;

// ---- Stat card ----
function Stat({ l, v, desc, trend, em }){
  return (
    <div className="stat">
      <span className="corner tr"></span>
      <span className="corner bl"></span>
      <div className="lbl">
        <span>{l}</span>
        {trend && <span className="trend">{trend}</span>}
      </div>
      <div className="v">{em ? <em>{v}</em> : v}</div>
      <div className="desc">{desc}</div>
    </div>
  );
}
window.Stat = Stat;

// ---- Project card ----
function ProjectCard({ p, onOpen }){
  return (
    <div className="proj-card" onClick={() => onOpen && onOpen(p.id)}>
      <div className="art">
        <div className="grid-overlay"></div>
        <span className="micro">{p.territory || 'DS / TERRITORY 014'}</span>
        <span className="badge-tr">{statusChip(p.status, p.statusLabel)}</span>
        <span className="word">{p.titleShort || p.title}</span>
        <span className="coord"><span className="dot"></span>{p.coord || '23°33′S · 46°38′W'}</span>
      </div>
      <div className="body">
        <div className="row1">
          <div>
            <h4>{p.title.split(' ').slice(0,2).join(' ')}<br/><em>{p.title.split(' ').slice(2).join(' ')}</em></h4>
            <div className="svc" style={{marginTop:6}}>{p.service}</div>
          </div>
        </div>
        <div className="progress">
          <div className="meta-line">
            <span>// Progresso</span>
            <span className="pct">{p.progress}%</span>
          </div>
          <div className="bar"><div className="fill" style={{width: p.progress+'%'}}></div></div>
        </div>
      </div>
      <div className="footer-row">
        <div className="deadline">
          <span>// Próximo prazo</span>
          <span className="v">{p.nextDeadline}</span>
        </div>
        <div className="lead">
          <span>{p.leadInitials}</span>
          <span className="avatar">{p.leadInitials}</span>
        </div>
      </div>
    </div>
  );
}
window.ProjectCard = ProjectCard;

// ---- Section header ----
function SectionHd({ title, n, right }){
  return (
    <div className="section-hd">
      <h3>{title}</h3>
      <div className="right">
        {n && <span className="mono-sm">// {n}</span>}
        {right}
      </div>
    </div>
  );
}
window.SectionHd = SectionHd;

// ---- Modal ----
function Modal({ title, onClose, children, footer, wide, xWide }){
  useEffect(() => {
    const onKey = (e) => { if(e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, [onClose]);
  return (
    <div className="modal-back" onClick={onClose}>
      <div className={`modal ${wide?'wide':''} ${xWide?'x-wide':''}`} onClick={e=>e.stopPropagation()}>
        <div className="ptop">
          <span className="ttl">{title}</span>
          <button className="close" onClick={onClose}>{Ico.close()}</button>
        </div>
        <div className="mbody">{children}</div>
        {footer && <div className="mfoot">{footer}</div>}
      </div>
    </div>
  );
}
window.Modal = Modal;

// ---- Field ----
function Field({ label, required, hint, children }){
  return (
    <div className="fld">
      <label>
        <span>{label}</span>
        {required && <span className="req">*</span>}
      </label>
      {children}
      {hint && <span className="hint">{hint}</span>}
    </div>
  );
}
window.Field = Field;

// ---- Check ----
function Check({ checked, onChange, children }){
  return (
    <div className={`check ${checked?'on':''}`} onClick={() => onChange(!checked)}>
      <span className="box">{Ico.check({width:11, height:11})}</span>
      <span className="lbl">{children}</span>
    </div>
  );
}
window.Check = Check;

// ---- Toast ----
function Toast({ children }){
  return (
    <div className="toast"><span className="dot"></span><span>{children}</span></div>
  );
}
window.Toast = Toast;

// ---- Tabs ----
function Tabs({ tabs, active, onChange }){
  return (
    <div className="tabs">
      {tabs.map((t, i) => (
        <div key={t.key}
             className={`tab ${active === t.key ? 'active':''} ${t.highlight ? 'highlight' : ''}`}
             onClick={() => onChange(t.key)}>
          <span className="n">§ {String(i+1).padStart(2,'0')}</span>
          {t.icon && <span className="tab-icon" style={{display:'inline-flex', alignItems:'center', color:'inherit'}}>{t.icon}</span>}
          <span>{t.label}</span>
          {t.count != null && <span className="count">{t.count}</span>}
        </div>
      ))}
    </div>
  );
}
window.Tabs = Tabs;

// ---- File icon helper ----
function FileIcon({ kind }){
  return <span className="icon">{kind}</span>;
}
window.FileIcon = FileIcon;

// ---- Notification toast helper hook ----
function useToast(){
  const [msg, setMsg] = useState(null);
  useEffect(() => {
    if(!msg) return;
    const t = setTimeout(() => setMsg(null), 2800);
    return () => clearTimeout(t);
  }, [msg]);
  return [msg, setMsg];
}
window.useToast = useToast;
