/* CACTUS CHAT — bundled JSX (concatenated; transpiled once) */

/* ===== icons.jsx ===== */
/* ============================================================
   Icons + Cactus logo
   ============================================================ */
const I = {
  chat: 'M21 11.5a8.5 8.5 0 0 1-12.3 7.6L3 21l1.9-5.7A8.5 8.5 0 1 1 21 11.5Z',
  funnel: 'M3 5h18l-7 8v6l-4-2v-4L3 5Z',
  bolt: 'M13 2 4 14h6l-1 8 9-12h-6l1-8Z',
  bot: 'M12 7V3M9 3h6M5 11a3 3 0 0 1 3-3h8a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H8a3 3 0 0 1-3-3v-6Z|M9 13h.01M15 13h.01',
  megaphone: 'M3 11v2a1 1 0 0 0 1 1h2l3.5 4V6L6 10H4a1 1 0 0 0-1 1Z|M14 7s3 1.5 3 5-3 5-3 5',
  report: 'M5 3h11l4 4v14H5V3Z|M15 3v5h5M8 13h8M8 17h6M8 9h3',
  phone: 'M5 4h4l1.5 4-2 1.5a11 11 0 0 0 5 5l1.5-2 4 1.5v4a2 2 0 0 1-2.2 2A16 16 0 0 1 3 6.2 2 2 0 0 1 5 4Z',
  tag: 'M3 12.5 11 4.5h7v7l-8 8-7-7Z|M14.5 8h.01',
  contacts: 'M9 11a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7ZM3 20c0-3.3 2.7-6 6-6s6 2.7 6 6M16 4a3.5 3.5 0 0 1 0 7M18 14c2.2.6 3.8 2.5 3.8 4.8',
  media: 'M4 5h16v14H4V5Z|M4 16l4.5-4.5 4 4 3.5-3 4 3.5M9 9.5a1.2 1.2 0 1 1-2.4 0 1.2 1.2 0 0 1 2.4 0Z',
  plug: 'M9 3v5M15 3v5M7 8h10v3a5 5 0 0 1-10 0V8ZM12 16v5',
  gear: 'M12 8.5a3.5 3.5 0 1 0 0 7 3.5 3.5 0 0 0 0-7Z|M19.4 13a7.6 7.6 0 0 0 0-2l2-1.5-2-3.4-2.3 1a7.6 7.6 0 0 0-1.7-1l-.3-2.6h-4l-.3 2.6a7.6 7.6 0 0 0-1.7 1l-2.3-1-2 3.4L4.6 11a7.6 7.6 0 0 0 0 2l-2 1.5 2 3.4 2.3-1a7.6 7.6 0 0 0 1.7 1l.3 2.6h4l.3-2.6a7.6 7.6 0 0 0 1.7-1l2.3 1 2-3.4L19.4 13Z',
  search: 'M11 4a7 7 0 1 0 0 14 7 7 0 0 0 0-14ZM20 20l-3.5-3.5',
  plus: 'M12 5v14M5 12h14',
  filter: 'M4 5h16M7 12h10M10 19h4',
  chevDown: 'M6 9l6 6 6-6',
  chevRight: 'M9 6l6 6-6 6',
  chevUp: 'M6 15l6-6 6 6',
  paperclip: 'M21 11.5 12.5 20a5 5 0 0 1-7-7l8-8a3.3 3.3 0 0 1 4.7 4.7l-8 8a1.6 1.6 0 0 1-2.3-2.3l7.3-7.3',
  dots: 'M5 12h.01M12 12h.01M19 12h.01',
  emoji: 'M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18ZM8.5 10h.01M15.5 10h.01M8.5 14.5s1.3 1.5 3.5 1.5 3.5-1.5 3.5-1.5',
  send: 'M4 12 20 4l-3 8 3 8L4 12Zm0 0h9',
  mic: 'M12 4a3 3 0 0 1 3 3v5a3 3 0 0 1-6 0V7a3 3 0 0 1 3-3ZM6 11a6 6 0 0 0 12 0M12 17v3',
  clock: 'M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18ZM12 7v5l3.5 2',
  calendar: 'M4 6h16v15H4V6ZM4 10h16M8 3v4M16 3v4',
  check: 'M5 12l4.5 4.5L19 7',
  checkcheck: 'M2 13l3.5 3.5L13 9|M9 13l3.5 3.5L20 9',
  bell: 'M6 9a6 6 0 0 1 12 0c0 5 2 6 2 6H4s2-1 2-6ZM10 20a2 2 0 0 0 4 0',
  whatsapp: 'M12 3a8.6 8.6 0 0 0-7.4 12.9L3 21l5.3-1.5A8.6 8.6 0 1 0 12 3Z|M8.5 8.2c.2-.5.4-.5.7-.5h.5c.2 0 .4 0 .6.5l.7 1.6c.1.2 0 .4 0 .5l-.5.6c-.1.1-.2.3 0 .5a6 6 0 0 0 2.6 2.3c.3.1.4 0 .5 0l.6-.7c.2-.2.3-.2.5-.1l1.5.7c.2.1.4.2.4.4 0 .5-.1 1.3-.5 1.6-.4.3-1.6.8-3.5-.1a9 9 0 0 1-3.9-3.9c-.8-1.6-.5-2.7-.2-3.5Z',
  gift: 'M4 11h16v9H4v-9ZM3 7h18v4H3V7ZM12 7v13M12 7S11 3 8.5 3 6 7 12 7ZM12 7s1-4 3.5-4S18 7 12 7Z',
  volume: 'M4 9v6h4l5 4V5L8 9H4ZM16 9a4 4 0 0 1 0 6M18.5 7a7 7 0 0 1 0 10',
  sun: 'M12 6a6 6 0 1 0 0 12 6 6 0 0 0 0-12ZM12 1v2M12 21v2M4 4l1.5 1.5M18.5 18.5 20 20M1 12h2M21 12h2M4 20l1.5-1.5M18.5 5.5 20 4',
  moon: 'M21 13A8.5 8.5 0 0 1 11 3a8.5 8.5 0 1 0 10 10Z',
  logout: 'M14 4h4a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1h-4M10 8l-4 4 4 4M6 12h11',
  user: 'M12 11a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7ZM5 20c0-3.5 3-6 7-6s7 2.5 7 6',
  history: 'M12 3a9 9 0 1 1-8.5 6M3 5v4h4M12 8v4l3 2',
  note: 'M5 4h11l4 4v12H5V4ZM8 11h8M8 15h5',
  archive: 'M4 7h16v13H4V7ZM3 4h18v3H3V4ZM10 11h4',
  trash: 'M5 7h14M9 7V5h6v2M7 7l1 13h8l1-13',
  edit: 'M5 19h14M14 5l4 4-8.5 8.5H5v-4.5L14 5Z',
  doc: 'M6 3h8l4 4v14H6V3Z|M14 3v4h4M9 13h6M9 17h4',
  scale: 'M12 4v16M7 20h10M6 7l12-2M6 7 3.5 13a3 3 0 0 0 5 0L6 7Zm12-2-2.5 6a3 3 0 0 0 5 0L18 5Z',
  calc: 'M5 3h14v18H5V3ZM8 7h8M8 11h2M8 15h2M14 11h2M14 15h2M12 11v8',
  sparkle: 'M12 3l1.8 5.2L19 10l-5.2 1.8L12 17l-1.8-5.2L5 10l5.2-1.8L12 3ZM18 15l.8 2.2L21 18l-2.2.8L18 21l-.8-2.2L15 18l2.2-.8L18 15Z',
  signature: 'M3 17c3 0 4-9 6-9s2 6 4 6 2-4 4-4 2 2 4 2M3 21h18',
  money: 'M12 6v12M9 9.5c0-1 1.3-1.5 3-1.5s3 .8 3 2-1.5 1.7-3 2-3 .8-3 2 1.3 2 3 2 3-.5 3-1.5',
  building: 'M4 21V5l8-2 8 2v16M4 21h16M8 8h.01M12 8h.01M16 8h.01M8 12h.01M12 12h.01M16 12h.01M9 21v-4h6v4',
  flame: 'M12 3c1 4 5 4.5 5 9a5 5 0 0 1-10 0c0-1.5.5-2.5 1.5-3.5C9 10 9 12 10.5 12c1 0 1-1.5 .5-4 .3-2 1-4 1-5Z',
  layers: 'M12 3 3 8l9 5 9-5-9-5ZM3 13l9 5 9-5M3 17l9 5 9-5',
  star: 'M12 3l2.6 6.3L21 9.8l-5 4.3 1.6 6.6L12 17.2 6.4 20.7 8 14.1l-5-4.3 6.4-.5L12 3Z',
  qr: 'M4 4h6v6H4V4ZM14 4h6v6h-6V4ZM4 14h6v6H4v-6ZM14 14h2v2h-2v-2ZM18 14h2v2h-2v-2ZM14 18h2v2h-2v-2ZM18 18h2v2h-2v-2Z',
  refresh: 'M20 11a8 8 0 0 0-14-4M4 7V3m0 4h4M4 13a8 8 0 0 0 14 4m2 0v4m0-4h-4',
  power: 'M12 4v8M7.5 6.5a7 7 0 1 0 9 0',
  link: 'M10 13a4 4 0 0 0 5.7 0l3-3a4 4 0 1 0-5.7-5.7L11 6M14 11a4 4 0 0 0-5.7 0l-3 3a4 4 0 1 0 5.7 5.7L13 18',
  eye: 'M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7ZM12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z',
  download: 'M12 4v11M7 11l5 5 5-5M5 20h14',
  grid: 'M4 4h7v7H4V4ZM13 4h7v7h-7V4ZM4 13h7v7H4v-7ZM13 13h7v7h-7v-7Z',
  list: 'M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01',
  pin: 'M12 21s-7-6.2-7-11a7 7 0 1 1 14 0c0 4.8-7 11-7 11ZM12 12.5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Z',
  flag: 'M5 21V4m0 0 9 2-9 2m0 0v4l9 2M14 6l5 1.2L14 12',
  template: 'M4 4h16v4H4V4ZM4 10h7v10H4V10ZM13 10h7v10h-7V10Z',
  unread: 'M4 6h16v12H4z|M4 7l8 6 8-6',
  broadcast: 'M12 9a3 3 0 1 0 0 6 3 3 0 0 0 0-6ZM6 6a8 8 0 0 0 0 12M18 6a8 8 0 0 1 0 12M3.5 3.5a12 12 0 0 0 0 17M20.5 3.5a12 12 0 0 1 0 17',
  bookmark: 'M6 3h12v18l-6-4-6 4V3Z',
  reply: 'M9 7 4 12l5 5M4 12h9a6 6 0 0 1 6 6v2',
};

function Icon({ name, size = 18, stroke = 2, fill = false, style, className }) {
  const d = I[name] || '';
  const parts = d.split('|');
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={fill ? 'currentColor' : 'none'}
      stroke={fill ? 'none' : 'currentColor'} strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round"
      style={style} className={className} aria-hidden="true">
      {parts.map((p, i) => <path key={i} d={p} />)}
    </svg>
  );
}

/* Cactus logo — outlined arms in rounded square */
function CactusLogo({ size = 42, radius, bg = 'var(--green-700)', spine = '#7BA05B' }) {
  const r = radius != null ? radius : Math.round(size * 0.26);
  return (
    <svg width={size} height={size} viewBox="0 0 48 48" style={{ display: 'block' }} aria-label="CACTUS CHAT">
      <rect x="2" y="2" width="44" height="44" rx={r} fill={bg} />
      <g stroke={spine} strokeWidth="3.2" fill="none" strokeLinecap="round" strokeLinejoin="round">
        <path d="M24 37 V15" />
        <path d="M24 26 q-7 0 -7 -8 v-2" />
        <path d="M24 30 q7 0 7 -9 v-1" />
      </g>
      <rect x="20.5" y="36" width="7" height="5" rx="1.6" fill={spine} opacity="0.55" />
    </svg>
  );
}

Object.assign(window, { Icon, CactusLogo, ICONS: I });


/* ===== data.jsx ===== */
/* ============================================================
   Mock data — Lima Amorim & Advogados Associados
   ============================================================ */

const AV = {
  green: '#5A6E2A', gold: '#B8924A', teal: '#3A6B5E', terr: '#C2683A',
  plum: '#7A5A6E', slate: '#516170', moss: '#7BA05B', clay: '#A8743A',
};

let USERS = [
  { id: 'u1', name: 'Dra. Mariana Lima',    email: 'mariana@limaamorim.adv.br',  dept: 'Cível',        color: AV.green, initials: 'ML' },
  { id: 'u2', name: 'Dr. Rafael Amorim',     email: 'rafael@limaamorim.adv.br',   dept: 'Bancário',     color: AV.teal,  initials: 'RA' },
  { id: 'u3', name: 'Dra. Beatriz Nogueira', email: 'beatriz@limaamorim.adv.br',  dept: 'Trabalhista',  color: AV.plum,  initials: 'BN' },
  { id: 'u4', name: 'Dr. Thiago Mendes',     email: 'thiago@limaamorim.adv.br',   dept: 'Previdenc.',   color: AV.slate, initials: 'TM' },
  { id: 'u5', name: 'Camila Borges',         email: 'camila@limaamorim.adv.br',   dept: 'Recepção',     color: AV.clay,  initials: 'CB' },
];

let CURRENT_USER = { name: 'Dra. Mariana Lima', org: 'Lima Amorim & Advogados', color: AV.green, initials: 'ML' };

const STATUS = {
  open:   { key: 'open',   label: 'Aberto',          cls: 'badge-open' },
  active: { key: 'active', label: 'Em atendimento',  cls: 'badge-active' },
  wait:   { key: 'wait',   label: 'Aguardando',      cls: 'badge-wait' },
  done:   { key: 'done',   label: 'Resolvido',       cls: 'badge-done' },
};

let TAGS = [
  { id: 't1', name: 'Bancário',       bg: '#E3EFEA', fg: '#3A6B5E' },
  { id: 't2', name: 'Revisional',     bg: '#F3E7DC', fg: '#A8743A' },
  { id: 't3', name: 'Cliente VIP',    bg: '#F2EAD3', fg: '#9A7726' },
  { id: 't4', name: 'Trabalhista',    bg: '#EADFE6', fg: '#7A5A6E' },
  { id: 't5', name: 'Cível',          bg: '#E8EDD8', fg: '#5A6E2A' },
  { id: 't6', name: 'Previdenciário', bg: '#E2E8EE', fg: '#516170' },
  { id: 't7', name: 'Urgente',        bg: '#F6E0D6', fg: '#C2683A' },
  { id: 't8', name: 'Contrato',       bg: '#E9E4D2', fg: '#8A7434' },
];

let CONV = [
  { id: 'c1', name: 'Carlos Eduardo Ribeiro', phone: '+55 11 98432-1187', color: AV.teal, initials: 'CR',
    last: 'Perfeito, doutora. Vou providenciar os documentos do financiamento ainda hoje.', time: '14:38',
    status: 'active', owner: 'u2', unread: 0, fav: true, tags: ['t1','t2','t3'], stage: 'Proposta',
    preview_in: false, online: true },
  { id: 'c2', name: 'Fernanda Souza Martins', phone: '+55 21 99617-4420', color: AV.plum, initials: 'FM',
    last: 'Recebi a intimação do processo trabalhista, podem me explicar?', time: '14:21',
    status: 'open', owner: 'u3', unread: 3, fav: false, tags: ['t4','t7'], stage: 'Captação',
    preview_in: true, online: false },
  { id: 'c3', name: 'João Paulo Ferreira', phone: '+55 31 98120-0934', color: AV.green, initials: 'JF',
    last: 'Você: Enviei o contrato de honorários para sua assinatura no ZapSign.', time: '13:55',
    status: 'wait', owner: 'u1', unread: 0, fav: false, tags: ['t5','t8'], stage: 'Contrato enviado',
    preview_in: false, online: true },
  { id: 'c4', name: 'Aparecida Gomes', phone: '+55 11 97455-2210', color: AV.clay, initials: 'AG',
    last: 'Muito obrigada! O benefício do INSS saiu certinho.', time: '11:47',
    status: 'done', owner: 'u4', unread: 0, fav: false, tags: ['t6'], stage: 'Pós-venda',
    preview_in: true, online: false },
  { id: 'c5', name: 'Ricardo Almeida Castro', phone: '+55 47 98801-7765', color: AV.slate, initials: 'RC',
    last: 'Qual o valor da causa na ação revisional do meu veículo?', time: '11:02',
    status: 'open', owner: null, unread: 1, fav: false, tags: ['t1','t2'], stage: 'Qualificação',
    preview_in: true, online: false },
  { id: 'c6', name: 'Luciana Prado', phone: '+55 11 99230-6618', color: AV.gold, initials: 'LP',
    last: 'Você: Bom dia! Conforme conversamos, segue o resumo do diagnóstico.', time: 'Ontem',
    status: 'active', owner: 'u1', unread: 0, fav: true, tags: ['t5','t3'], stage: 'Diagnóstico',
    preview_in: false, online: false },
  { id: 'c7', name: 'Marcos Vinícius Dias', phone: '+55 85 98744-3092', color: AV.terr, initials: 'MD',
    last: 'Áudio · 0:42', time: 'Ontem',
    status: 'wait', owner: 'u2', unread: 0, fav: false, tags: ['t1'], stage: 'Aguarda reunião',
    preview_in: true, audio: true, online: false },
  { id: 'c8', name: 'Patrícia Carvalho', phone: '+55 19 99088-1245', color: AV.plum, initials: 'PC',
    last: 'Vocês atendem casos de superendividamento?', time: 'Ontem',
    status: 'open', owner: null, unread: 2, fav: false, tags: ['t7'], stage: 'Nunca respondeu',
    preview_in: true, online: false },
  { id: 'c9', name: 'Eduardo Tavares', phone: '+55 51 98377-5510', color: AV.green, initials: 'ET',
    last: 'Você: Seu processo está na fase de cumprimento de sentença.', time: 'Seg',
    status: 'done', owner: 'u1', unread: 0, fav: false, tags: ['t5'], stage: 'Pós-venda',
    preview_in: false, online: false },
  { id: 'c10', name: 'Sandra Regina Lopes', phone: '+55 62 99511-8834', color: AV.clay, initials: 'SL',
    last: 'Preciso renegociar a dívida do cartão de crédito com o banco.', time: 'Seg',
    status: 'open', owner: 'u2', unread: 0, fav: false, tags: ['t1','t2'], stage: 'Captação',
    preview_in: true, online: false },
  { id: 'c11', name: 'Anderson Pereira', phone: '+55 11 97001-2398', color: AV.slate, initials: 'AP',
    last: 'Você: Vou te encaminhar para o departamento trabalhista.', time: 'Seg',
    status: 'wait', owner: 'u3', unread: 0, fav: false, tags: ['t4'], stage: 'Follow-up',
    preview_in: false, online: false },
  { id: 'c12', name: 'Vânia Cristina Melo', phone: '+55 71 98266-7741', color: AV.gold, initials: 'VM',
    last: 'O senhor doutor pode me ligar amanhã de manhã?', time: 'Dom',
    status: 'active', owner: 'u4', unread: 0, fav: false, tags: ['t6','t3'], stage: 'Reativação',
    preview_in: true, online: false },
];

/* Messages for active conversation (Carlos Eduardo Ribeiro) */
const MESSAGES = [
  { id: 'm1', dir: 'in', t: '14:02', text: 'Boa tarde! Vi o anúncio de vocês sobre revisão de financiamento de veículos.' },
  { id: 'm2', dir: 'in', t: '14:02', text: 'Estou pagando uma parcela muito alta no meu carro e queria entender se dá pra revisar.' },
  { id: 'm3', dir: 'out', t: '14:05', text: 'Boa tarde, Carlos! Aqui é a Dra. Mariana, do Lima Amorim & Advogados. Tudo bem?', read: true },
  { id: 'm4', dir: 'out', t: '14:05', text: 'Atuamos sim com ações revisionais de contratos bancários. Para fazer uma análise, preciso de alguns dados do seu financiamento.', read: true },
  { id: 'm5', dir: 'in', t: '14:09', text: 'Que ótimo! Pode falar, o que você precisa?' },
  { id: 'm6', dir: 'out', t: '14:12', text: 'Preciso do contrato, valor financiado, número de parcelas, valor da parcela e a taxa de juros que consta no contrato. Pode me enviar uma foto do contrato?', read: true },
  { id: 'm7', dir: 'in', t: '14:21', text: 'Contrato_Financiamento_BV.pdf', file: { name: 'Contrato_Financiamento_BV.pdf', size: '1,4 MB' } },
  { id: 'm8', dir: 'out', t: '14:30', text: 'Recebido! Fiz uma simulação inicial no nosso cálculo Bacen. Identifiquei cobrança de juros acima da média de mercado e tarifas que podem ser revistas. A economia estimada é de aproximadamente R$ 9.840,00 ao longo do contrato.', read: true },
  { id: 'm9', dir: 'in', t: '14:34', text: 'Sério?? Isso seria excelente. Como funciona pra contratar vocês?' },
  { id: 'm10', dir: 'out', t: '14:36', text: 'Vou te enviar a proposta de honorários. Se concordar, geramos o contrato digital para assinatura aqui mesmo pelo WhatsApp, pelo ZapSign. Bem simples.', read: true },
  { id: 'm11', dir: 'in', t: '14:38', text: 'Perfeito, doutora. Vou providenciar os documentos do financiamento ainda hoje.' },
];

/* ADVBOX — client + processes */
const ADVBOX = {
  client: { name: 'Carlos Eduardo Ribeiro', cpf: '328.114.557-09', code: 'CLI-2041', since: 'Mar/2024' },
  processes: [
    { num: '1009823-44.2025.8.26.0100', area: 'Bancário', phase: 'Petição inicial', resp: 'Dr. Rafael Amorim', status: 'active' },
    { num: '0028471-12.2024.8.26.0010', area: 'Cível', phase: 'Cumprimento de sentença', resp: 'Dra. Mariana Lima', status: 'done' },
  ],
  finance: { onTime: 'R$ 2.400,00', overdue: 'R$ 600,00', nextDue: '15/06/2026' },
};

/* Funnel */
let FUNNEL_STAGES = [
  { name: 'Nunca respondeu',  count: 184 },
  { name: 'Captação',         count: 142 },
  { name: 'Qualificação',     count: 98 },
  { name: 'Diagnóstico',      count: 71 },
  { name: 'Aguarda reunião',  count: 54 },
  { name: 'Proposta',         count: 39 },
  { name: 'Contrato enviado', count: 28 },
  { name: 'Follow-up',        count: 21 },
  { name: 'Reativação',       count: 14 },
  { name: 'Não fechado',      count: 32 },
  { name: 'Pós-venda',        count: 47 },
];

const KANBAN = [
  { stage: 'Captação', cards: ['c2','c10'] },
  { stage: 'Qualificação', cards: ['c5'] },
  { stage: 'Diagnóstico', cards: ['c6'] },
  { stage: 'Aguarda reunião', cards: ['c7'] },
  { stage: 'Proposta', cards: ['c1'] },
  { stage: 'Contrato enviado', cards: ['c3'] },
];

/* Dashboard */
let DASH = USERS.map((u, i) => {
  const a = [4, 2, 6, 1, 9][i]; const b = [7, 5, 3, 8, 2][i]; const c = [2, 3, 1, 4, 5][i];
  return { user: u, open: a, active: b, wait: c, total: a + b + c };
});

const QUICK_REPLIES = [
  { sh: '/saudacao', title: 'Saudação inicial', text: 'Olá! Seja bem-vindo(a) ao Lima Amorim & Advogados Associados. Em que podemos ajudá-lo(a) hoje?' },
  { sh: '/horario', title: 'Horário de atendimento', text: 'Nosso horário de atendimento é de segunda a sexta, das 9h às 18h.' },
  { sh: '/honorarios', title: 'Proposta de honorários', text: 'Segue em anexo nossa proposta de honorários. Qualquer dúvida, estou à disposição.' },
  { sh: '/docs', title: 'Lista de documentos', text: 'Para darmos andamento, precisaremos de: RG, CPF, comprovante de residência e o contrato em questão.' },
  { sh: '/agradecimento', title: 'Encerramento', text: 'Agradecemos o contato! Permanecemos à disposição para o que precisar.' },
];

const DIALOGS = [
  { name: 'Triagem inicial',          group: 'Atendimento', status: 'CONTÍNUO', updated: '02/06/2026' },
  { name: 'Qualificação bancário',    group: 'Comercial',   status: 'CONTÍNUO', updated: '28/05/2026' },
  { name: 'Coleta de documentos',     group: 'Atendimento', status: 'CONTÍNUO', updated: '21/05/2026' },
  { name: 'Pesquisa de satisfação',   group: 'Pós-venda',   status: 'PAUSADO',  updated: '15/05/2026' },
  { name: 'Reativação de leads frios', group: 'Comercial',  status: 'CONTÍNUO', updated: '10/05/2026' },
];

const CAMPAIGNS = [
  { name: 'Revisional Bancária — Maio',   status: 'Concluída',     prog: 100, recip: 1240, dialog: 'Qualificação bancário',  start: '05/05/2026', created: '02/05/2026' },
  { name: 'Superendividamento PF',         status: 'Em andamento',  prog: 64,  recip: 880,  dialog: 'Triagem inicial',        start: '01/06/2026', created: '28/05/2026' },
  { name: 'Aviso de audiências trabalhistas', status: 'Agendada',  prog: 0,   recip: 312,  dialog: 'Coleta de documentos',   start: '10/06/2026', created: '04/06/2026' },
  { name: 'NPS pós-encerramento',          status: 'Pausada',       prog: 38,  recip: 540,  dialog: 'Pesquisa de satisfação', start: '20/05/2026', created: '18/05/2026' },
];

const DEVICES = [
  { num: '+55 11 4003-2210', label: 'Atendimento Principal',  status: 'connected', queue: 0,  battery: 86 },
  { num: '+55 11 4003-2211', label: 'Comercial / Bancário',   status: 'connected', queue: 4,  battery: 72 },
  { num: '+55 11 4003-2212', label: 'Trabalhista',            status: 'syncing',   queue: 12, battery: 54 },
  { num: '+55 11 4003-2213', label: 'Previdenciário',         status: 'offline',   queue: 0,  battery: 0 },
];

const NOTES = [
  { author: 'Dra. Mariana Lima', date: '06/06/2026 14:30', text: 'Cliente muito receptivo. Economia estimada de R$ 9.840 na revisional. Enviar proposta de honorários hoje.' },
  { author: 'Dr. Rafael Amorim', date: '05/06/2026 17:10', text: 'Contrato do financiamento já está com tarifas abusivas evidentes (TAC + seguro embutido). Caso forte.' },
  { author: 'Camila Borges', date: '04/06/2026 09:22', text: 'Primeiro contato veio pelo anúncio do Instagram. Lead qualificado.' },
];

const CONTEXT_VARS = [
  { tag: '$nome',          value: 'Carlos Eduardo Ribeiro' },
  { tag: '$cpf',           value: '328.114.557-09' },
  { tag: '$area',          value: 'Bancário — Revisional' },
  { tag: '$valor_causa',   value: 'R$ 47.200,00' },
  { tag: '$economia_est',  value: 'R$ 9.840,00' },
  { tag: '$banco',         value: 'Banco BV S.A.' },
  { tag: '$origem_lead',   value: 'Instagram Ads' },
];

const DELEGATIONS = [
  { from: 'Camila Borges', to: 'Dra. Mariana Lima', date: '04/06/2026 09:25', reason: 'Triagem → Cível' },
  { from: 'Dra. Mariana Lima', to: 'Dr. Rafael Amorim', date: '05/06/2026 16:40', reason: 'Caso bancário' },
  { from: 'Dr. Rafael Amorim', to: 'Dra. Mariana Lima', date: '06/06/2026 14:05', reason: 'Fechamento de honorários' },
];

Object.assign(window, {
  USERS, CURRENT_USER, STATUS, TAGS, CONV, MESSAGES, ADVBOX, FUNNEL_STAGES, KANBAN,
  DASH, QUICK_REPLIES, DIALOGS, CAMPAIGNS, DEVICES, NOTES, CONTEXT_VARS, DELEGATIONS, AV,
});


/* ===== components.jsx ===== */
/* ============================================================
   Shared components
   ============================================================ */

function Avatar({ name, color, initials, size = 40, img, online }) {
  const fs = Math.round(size * 0.38);
  return (
    <div style={{ position: 'relative', width: size, height: size, flexShrink: 0 }}>
      <div className="av" style={{ width: size, height: size, background: color, fontSize: fs }}>
        {img ? <img src={img} alt={name} /> : (initials || (name || '?').slice(0, 2).toUpperCase())}
      </div>
      {online && <span style={{ position: 'absolute', right: -1, bottom: -1, width: Math.max(9, size * 0.26),
        height: Math.max(9, size * 0.26), borderRadius: '50%', background: '#4FB477',
        border: '2px solid var(--surface)' }} />}
    </div>
  );
}

function StatusBadge({ status, dot = true }) {
  const s = STATUS[status] || STATUS.open;
  return <span className={`badge ${s.cls}`}>{dot && <span className="bdot" />}{s.label}</span>;
}

function Tag({ id, removable, onRemove }) {
  const t = TAGS.find(x => x.id === id) || { name: id, bg: '#eee', fg: '#555' };
  return (
    <span className="chip" style={{ background: t.bg, color: t.fg }}>
      {t.name}
      {removable && <span className="x" onClick={onRemove}><Icon name="plus" size={11} style={{ transform: 'rotate(45deg)' }} /></span>}
    </span>
  );
}

function Toggle({ on, onChange, labels }) {
  return (
    <button onClick={() => onChange && onChange(!on)} className="row"
      style={{ background: 'none', border: 'none', padding: 0, gap: 9 }}>
      <span style={{ width: 40, height: 23, borderRadius: 999, background: on ? 'var(--green-500)' : 'var(--border)',
        position: 'relative', transition: 'background .18s', flexShrink: 0 }}>
        <span style={{ position: 'absolute', top: 2.5, left: on ? 20 : 2.5, width: 18, height: 18, borderRadius: '50%',
          background: '#fff', boxShadow: '0 1px 3px rgba(0,0,0,.25)', transition: 'left .18s' }} />
      </span>
      {labels && <span style={{ fontSize: 13, fontWeight: 700, color: on ? 'var(--green-500)' : 'var(--text-2)' }}>
        {on ? labels[0] : labels[1]}</span>}
    </button>
  );
}

function Segmented({ options, value, onChange }) {
  return (
    <div className="row" style={{ background: 'var(--surface-3)', borderRadius: 9, padding: 3, gap: 2 }}>
      {options.map(o => (
        <button key={o.value} onClick={() => onChange(o.value)}
          style={{ border: 'none', background: value === o.value ? 'var(--surface)' : 'transparent',
            color: value === o.value ? 'var(--text)' : 'var(--text-2)', fontWeight: 700, fontSize: 12.5,
            padding: '6px 12px', borderRadius: 6, boxShadow: value === o.value ? 'var(--shadow-sm)' : 'none',
            display: 'flex', alignItems: 'center', gap: 6 }}>
          {o.icon && <Icon name={o.icon} size={15} />}{o.label}
        </button>
      ))}
    </div>
  );
}

function IconBtn({ name, size = 18, title, onClick, active, badge, danger }) {
  return (
    <button className="btn btn-ghost btn-icon" title={title} onClick={onClick}
      style={{ position: 'relative', borderColor: 'transparent', background: active ? 'var(--green-100)' : 'transparent',
        color: danger ? 'var(--st-open)' : active ? 'var(--green-700)' : 'var(--text-2)' }}>
      <Icon name={name} size={size} />
      {badge != null && <span style={{ position: 'absolute', top: -2, right: -2, minWidth: 16, height: 16, padding: '0 4px',
        borderRadius: 999, background: 'var(--st-open)', color: '#fff', fontSize: 10, fontWeight: 800,
        display: 'grid', placeItems: 'center' }}>{badge}</span>}
    </button>
  );
}

function SectionTitle({ children, sub, action }) {
  return (
    <div className="row" style={{ justifyContent: 'space-between', marginBottom: 14, gap: 12 }}>
      <div>
        <h2 style={{ fontSize: 22, letterSpacing: '-.01em' }}>{children}</h2>
        {sub && <div className="muted" style={{ fontSize: 13, marginTop: 3 }}>{sub}</div>}
      </div>
      {action}
    </div>
  );
}

/* Collapsible block */
function Collapse({ title, icon, defaultOpen = false, children, right }) {
  const [open, setOpen] = React.useState(defaultOpen);
  return (
    <div style={{ borderBottom: '1px solid var(--border)' }}>
      <button onClick={() => setOpen(!open)} className="row"
        style={{ width: '100%', background: 'none', border: 'none', padding: '11px 14px', gap: 9,
          color: 'var(--text)', fontWeight: 700, fontSize: 13 }}>
        {icon && <Icon name={icon} size={16} style={{ color: 'var(--text-2)' }} />}
        <span>{title}</span>
        <span className="spacer" />
        {right}
        <Icon name="chevDown" size={16} style={{ color: 'var(--text-2)', transform: open ? 'rotate(180deg)' : 'none', transition: 'transform .2s' }} />
      </button>
      {open && <div style={{ padding: '2px 14px 14px' }}>{children}</div>}
    </div>
  );
}

function Empty({ icon, title, sub }) {
  return (
    <div className="col" style={{ alignItems: 'center', justifyContent: 'center', padding: '40px 20px', textAlign: 'center', gap: 8, color: 'var(--text-3)' }}>
      <div style={{ width: 54, height: 54, borderRadius: 14, background: 'var(--surface-3)', display: 'grid', placeItems: 'center' }}>
        <Icon name={icon} size={24} style={{ color: 'var(--text-3)' }} />
      </div>
      <div style={{ fontWeight: 700, color: 'var(--text-2)', fontSize: 14 }}>{title}</div>
      {sub && <div className="tiny" style={{ maxWidth: 240 }}>{sub}</div>}
    </div>
  );
}

Object.assign(window, { Avatar, StatusBadge, Tag, Toggle, Segmented, IconBtn, SectionTitle, Collapse, Empty });


/* ===== chrome.jsx ===== */
/* ============================================================
   Chrome — narrow Sidebar (flyouts) + Topbar
   ============================================================ */

const NAV = [
  { id: 'atendimento', icon: 'chat',      label: 'Atendimento' },
  { id: 'funil',       icon: 'funnel',    label: 'Funil' },
  { id: 'dashboard',   icon: 'grid',      label: 'Dashboard' },
  { id: 'respostas',   icon: 'bolt',      label: 'Respostas Rápidas' },
  { id: 'dialogos',    icon: 'bot',       label: 'Diálogos / Chatbot' },
  { id: 'campanhas',   icon: 'megaphone', label: 'Campanhas' },
  { id: 'relatorios',  icon: 'report',    label: 'Relatórios', submenu: [
      'Acessos', 'Diálogos', 'Anotações', 'Chats', 'Mensagens', 'Histórico de Mensagens', 'Relatórios Gráficos' ] },
  { id: 'celulares',   icon: 'phone',     label: 'Celulares' },
  { id: 'tags',        icon: 'tag',       label: 'Tags' },
  { id: 'contatos',    icon: 'contacts',  label: 'Contatos' },
  { id: 'midias',      icon: 'media',     label: 'Mídias' },
  { id: 'integracoes', icon: 'plug',      label: 'Integrações' },
];

function Sidebar({ route, go }) {
  return (
    <nav className="sidebar">
      <div className="sb-logo" title="CACTUS CHAT">
        <CactusLogo size={42} radius={11} bg="var(--green-100)" spine="var(--green-700)" />
      </div>
      <div className="sb-scroll">
        {NAV.map(item => {
          const active = route === item.id || (item.id === 'relatorios' && route === 'relatorios');
          const inner = (
            <button className={`sb-item ${active ? 'active' : ''}`} onClick={() => go(item.id)}>
              <Icon name={item.icon} size={21} stroke={active ? 2.2 : 1.9} />
              {!item.submenu && <span className="sb-flyout">{item.label}</span>}
            </button>
          );
          if (item.submenu) {
            return (
              <div className="sb-itemwrap" key={item.id}>
                {inner}
                <div className="sb-submenu">
                  <div className="sm-title">{item.label}</div>
                  {item.submenu.map(s => (
                    <a key={s} onClick={() => go('relatorios')}>
                      <Icon name="chevRight" size={13} style={{ opacity: .5 }} />{s}
                    </a>
                  ))}
                </div>
              </div>
            );
          }
          return <React.Fragment key={item.id}>{inner}</React.Fragment>;
        })}
      </div>
      <div className="sb-spacer" />
      <button className={`sb-item ${route === 'designsystem' ? 'active' : ''}`} onClick={() => go('designsystem')}>
        <Icon name="layers" size={21} />
        <span className="sb-flyout">Design System</span>
      </button>
      <button className={`sb-item ${route === 'config' ? 'active' : ''}`} onClick={() => go('config')}>
        <Icon name="gear" size={21} />
        <span className="sb-flyout">Configurações</span>
      </button>
    </nav>
  );
}

function Topbar({ theme, toggleTheme, onLogout, go }) {
  const [notifOpen, setNotifOpen] = React.useState(false);
  return (
    <header className="topbar">
      <div className="tb-user">
        <Avatar name={CURRENT_USER.name} color={CURRENT_USER.color} initials={CURRENT_USER.initials} size={34} />
        <div className="col" style={{ lineHeight: 1.15 }}>
          <span className="name">{CURRENT_USER.name}</span>
          <span className="org">{CURRENT_USER.org}</span>
        </div>
      </div>
      <div className="tb-sep" />
      <div className="tb-pill"><Icon name="whatsapp" size={15} /> 4 aparelhos online</div>
      <div className="tb-spacer" />
      <div className="tb-icons">
        <button className="tb-btn" title="WhatsApp Web"><Icon name="whatsapp" size={19} /></button>
        <button className="tb-btn" title="Notificações" onClick={() => setNotifOpen(v => !v)}>
          <Icon name="bell" size={19} /><span className="tb-dot" /><Icon name="chevDown" size={13} className="caret" />
        </button>
        <button className="tb-btn" title="Envios"><Icon name="send" size={18} /><Icon name="chevDown" size={13} className="caret" /></button>
        <button className="tb-btn" title="Brinde / Novidades"><Icon name="gift" size={19} /></button>
        <button className="tb-btn" title="Som das notificações"><Icon name="volume" size={19} /></button>
        <div className="tb-sep" style={{ margin: '0 4px' }} />
        <button className="tb-btn" title={theme === 'dark' ? 'Tema claro' : 'Tema escuro'} onClick={toggleTheme}>
          <Icon name={theme === 'dark' ? 'sun' : 'moon'} size={19} />
        </button>
        <button className="tb-btn" title="Sair" onClick={onLogout}><Icon name="logout" size={19} /></button>
      </div>
    </header>
  );
}

Object.assign(window, { Sidebar, Topbar, NAV });


/* ===== integrations.jsx ===== */
/* ============================================================
   Integration panels — Advbox, ZapSign, Cálculo Bacen, Assistente IA
   ============================================================ */

function PanelHead({ icon, title, sub, accent }) {
  return (
    <div className="row gap10" style={{ marginBottom: 14 }}>
      <div className="integ-logo" style={{ background: accent }}><Icon name={icon} size={20} /></div>
      <div className="col">
        <span style={{ fontWeight: 800, fontSize: 14, fontFamily: 'var(--font-title)' }}>{title}</span>
        <span className="tiny muted">{sub}</span>
      </div>
    </div>
  );
}

/* ---- ADVBOX ---- */
function AdvboxPanel({ conv }) {
  const [data, setData] = React.useState(null);
  const [err, setErr] = React.useState(null);
  React.useEffect(() => {
    let alive = true; setData(null); setErr(null);
    fetch(`/api/conversations/${conv.id}/advbox`).then(r => r.json())
      .then(d => { if (!alive) return; if (d.error) setErr(d.error); else setData(d); })
      .catch(() => alive && setErr('Falha ao consultar o Advbox.'));
    return () => { alive = false; };
  }, [conv.id]);
  return (
    <div className="cp-pad">
      <PanelHead icon="scale" title="Advbox" sub="Sistema jurídico vinculado" accent="#3A6B5E" />
      {err && <div className="tiny" style={{ color: 'var(--st-open)', marginBottom: 10 }}>{err}</div>}
      {!data && !err && <div className="tiny muted">Consultando Advbox…</div>}
      {data && !data.found && <Empty icon="scale" title="Cliente não encontrado no Advbox" sub="Nenhum cadastro com este telefone ou nome." />}
      {data && data.found && (() => { const { client, processes, finance } = data; return (
        <React.Fragment>
          <div className="integ-card">
            <div className="row" style={{ justifyContent: 'space-between' }}>
              <div className="col"><span className="kv-k">Cliente vinculado</span><span style={{ fontWeight: 700 }}>{client.name}</span></div>
              <span className="badge badge-active"><span className="bdot" />{client.code}</span>
            </div>
            <div className="kv-grid" style={{ marginTop: 10 }}>
              <div><span className="kv-k">CPF/CNPJ</span><span className="kv-v">{client.cpf}</span></div>
              <div><span className="kv-k">Cliente desde</span><span className="kv-v">{client.since || '—'}</span></div>
            </div>
          </div>
          <div className="cp-sub">Processos <span className="cp-count">{processes.length}</span></div>
          {processes.length === 0 && <div className="tiny muted" style={{ marginBottom: 10 }}>Nenhum processo cadastrado.</div>}
          {processes.map((p, i) => (
            <div className="integ-card proc" key={i}>
              <div className="row" style={{ justifyContent: 'space-between', gap: 8 }}>
                <span className="proc-num">{p.num}</span>
                <span className={`badge ${p.status === 'done' ? 'badge-done' : 'badge-active'}`}><span className="bdot" />{p.status === 'done' ? 'Encerrado' : 'Ativo'}</span>
              </div>
              <div className="kv-grid" style={{ marginTop: 9 }}>
                <div><span className="kv-k">Área</span><span className="kv-v">{p.area}</span></div>
                <div><span className="kv-k">Fase atual</span><span className="kv-v">{p.phase}</span></div>
              </div>
              <div className="row gap6" style={{ marginTop: 8 }}>
                <Icon name="user" size={13} style={{ color: 'var(--text-3)' }} /><span className="tiny muted">{p.resp}</span>
              </div>
            </div>
          ))}
          <div className="cp-sub">Situação financeira</div>
          <div className="row gap8">
            <div className="fin-tile ok"><span className="kv-k">A vencer</span><span className="fin-val">{finance.onTime}</span></div>
            <div className="fin-tile bad"><span className="kv-k">Em atraso</span><span className="fin-val">{finance.overdue}</span></div>
          </div>
          <div className="tiny muted" style={{ margin: '8px 0 14px' }}>Próximo vencimento: {finance.nextDue}</div>
        </React.Fragment>
      ); })()}
      <button className="btn btn-primary btn-block" onClick={() => window.open('https://app.advbox.com.br', '_blank')}><Icon name="link" size={16} /> Abrir no Advbox</button>
    </div>
  );
}

/* ---- ZAPSIGN ---- */
function ZapsignPanel({ conv }) {
  const [data, setData] = React.useState(null);
  const [err, setErr] = React.useState(null);
  React.useEffect(() => {
    let alive = true; setData(null); setErr(null);
    fetch(`/api/conversations/${conv.id}/zapsign`).then(r => r.json())
      .then(d => { if (!alive) return; if (d.error && !d.contracts) setErr(d.error); else setData(d); })
      .catch(() => alive && setErr('Falha ao consultar o ZapSign.'));
    return () => { alive = false; };
  }, [conv.id]);
  const badgeCls = s => s === 'done' ? 'badge-done' : s === 'wait' ? 'badge-wait' : 'badge-open';
  return (
    <div className="cp-pad">
      <PanelHead icon="signature" title="ZapSign" sub="Contratos de honorários" accent="#5A6E2A" />
      {err && <div className="tiny" style={{ color: 'var(--st-open)', marginBottom: 10 }}>{err}</div>}
      {!data && !err && <div className="tiny muted">Consultando ZapSign…</div>}
      {data && data.contracts && data.contracts.length === 0 && (
        <Empty icon="signature" title="Nenhum contrato encontrado" sub="Este contato não tem contrato no ZapSign (pendente, assinado ou cancelado)." />
      )}
      {data && data.contracts && data.contracts.map((c, i) => (
        <div className="integ-card" key={i} style={{ marginBottom: 10 }}>
          <div className="row" style={{ justifyContent: 'space-between' }}>
            <span style={{ fontWeight: 700 }}>{c.model}</span>
            <span className={`badge ${badgeCls(c.status)}`}><span className="bdot" />{c.statusLabel}</span>
          </div>
          <div className="kv-grid" style={{ marginTop: 10 }}>
            <div><span className="kv-k">Signatário</span><span className="kv-v">{c.name}</span></div>
            <div><span className="kv-k">Envelope</span><span className="kv-v">{c.envelope}</span></div>
          </div>
          {c.when && <div className="tiny muted" style={{ marginTop: 6 }}>{c.when}</div>}
        </div>
      ))}
      <button className="btn btn-accent btn-block" style={{ marginTop: 6 }} onClick={() => data && data.dashboard && window.open(data.dashboard, '_blank')}>
        <Icon name="signature" size={16} /> Abrir painel do ZapSign
      </button>
      <div className="tiny muted" style={{ marginTop: 8 }}>A geração de novo contrato é feita pelo fluxo de fechamento (ZapSign).</div>
    </div>
  );
}

/* ---- CÁLCULO BANCÁRIO (Bacen) ---- */
function CalculoPanel({ conv }) {
  const [val, setVal] = React.useState('38000');
  const [parc, setParc] = React.useState('48');
  const [taxa, setTaxa] = React.useState('3.4');
  const [mod, setMod] = React.useState('pf_aquisicao_veiculos');
  const [loading, setLoading] = React.useState(false);
  const [r, setR] = React.useState(null);
  const [err, setErr] = React.useState(null);
  const money = n => 'R$ ' + Number(n || 0).toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  const calc = () => {
    setLoading(true); setErr(null);
    fetch('/api/bacen/revisional', { method: 'POST', headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ principal: val, taxa_contrato_pct: taxa, n_parcelas: parc, modalidade: mod }) })
      .then(x => x.json()).then(d => { if (d.error) setErr(d.error); else setR(d); })
      .catch(() => setErr('Falha no cálculo Bacen.')).finally(() => setLoading(false));
  };
  return (
    <div className="cp-pad">
      <PanelHead icon="calc" title="Cálculo Bancário" sub="Revisional — taxa média real do BCB" accent="#B8924A" />
      <div className="integ-card">
        <div className="field" style={{ marginBottom: 10 }}><span className="label">Valor financiado (R$)</span>
          <input className="input" value={val} onChange={e => setVal(e.target.value)} /></div>
        <div className="row gap8">
          <div className="field" style={{ flex: 1 }}><span className="label">Parcelas</span>
            <input className="input" value={parc} onChange={e => setParc(e.target.value)} /></div>
          <div className="field" style={{ flex: 1 }}><span className="label">Taxa a.m. contratada (%)</span>
            <input className="input" value={taxa} onChange={e => setTaxa(e.target.value)} /></div>
        </div>
        <div className="field" style={{ margin: '10px 0' }}><span className="label">Modalidade (BCB)</span>
          <select className="select" value={mod} onChange={e => setMod(e.target.value)}>
            <option value="pf_aquisicao_veiculos">PF — Aquisição de veículos</option>
            <option value="pf_credito_pessoal_nao_consignado">PF — Crédito pessoal não consignado</option>
            <option value="pf_credito_pessoal_consignado_inss">PF — Consignado INSS</option>
            <option value="pj_capital_giro_ate_365d">PJ — Capital de giro até 365d</option>
          </select></div>
        <button className="btn btn-gold btn-block" onClick={calc} disabled={loading}><Icon name="calc" size={16} /> {loading ? 'Calculando…' : 'Calcular revisional'}</button>
      </div>
      {err && <div className="tiny" style={{ color: 'var(--st-open)', marginTop: 10 }}>{err}</div>}
      {r && (
        <div className="calc-result">
          <div className="cr-row"><span>Taxa média BCB</span><b>{r.taxaMedia != null ? r.taxaMedia.toLocaleString('pt-BR', { minimumFractionDigits: 2 }) + '% a.m.' : 'indisponível'}</b></div>
          <div className="cr-row"><span>Parcela atual</span><b className="strike">{money(r.parcelaContrato)}</b></div>
          <div className="cr-row"><span>Parcela revisada</span><b style={{ color: 'var(--green-500)' }}>{money(r.parcelaRevisada)}</b></div>
          <div className="divider" style={{ margin: '4px 0' }} />
          <div className="cr-big">
            <span className="kv-k">Economia estimada no contrato</span>
            <span className="cr-econ">{money(r.economia)}</span>
          </div>
          <div className="tiny muted">Base: taxa média BCB da modalidade (Tema 1.061 STJ). Estimativo, sujeito a perícia.</div>
        </div>
      )}
    </div>
  );
}

/* ---- ASSISTENTE IA ---- */
function IAPanel({ conv }) {
  const [tab, setTab] = React.useState('resumo');
  const [loading, setLoading] = React.useState(false);
  const [out, setOut] = React.useState({ resumo: null, sugestao: null });
  const [err, setErr] = React.useState(null);
  const run = (k) => {
    setLoading(true); setErr(null);
    fetch(`/api/conversations/${conv.id}/ai`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ mode: k }) })
      .then(r => r.json())
      .then(d => { if (d.error) setErr(d.error); else setOut(s => ({ ...s, [k]: d.text })); })
      .catch(() => setErr('Falha ao chamar a IA.'))
      .finally(() => setLoading(false));
  };
  const cur = out[tab];
  return (
    <div className="cp-pad">
      <PanelHead icon="sparkle" title="Assistente IA" sub="Inteligência própria do CACTUS CHAT" accent="#7A5A6E" />
      <div style={{ marginBottom: 12 }}>
        <Segmented value={tab} onChange={setTab} options={[
          { value: 'resumo', label: 'Resumir conversa', icon: 'list' },
          { value: 'sugestao', label: 'Sugerir resposta', icon: 'reply' },
        ]} />
      </div>
      {err && <div className="tiny" style={{ color: 'var(--st-open)', marginBottom: 10 }}>{err}</div>}
      {cur ? (
        <div className="ia-card">
          <div className="ia-tag"><Icon name="sparkle" size={13} /> {tab === 'resumo' ? 'Resumo gerado' : 'Sugestão de resposta'}</div>
          <p style={{ margin: '8px 0 10px', lineHeight: 1.5, fontStyle: tab === 'sugestao' ? 'italic' : 'normal', whiteSpace: 'pre-wrap' }}>{cur}</p>
          {tab === 'sugestao' && (
            <div className="row gap8" style={{ marginBottom: 4 }}>
              <button className="btn btn-accent btn-sm" style={{ flex: 1 }} onClick={() => { try { window.__cactusInsertDraft && window.__cactusInsertDraft(cur); } catch (e) {} }}><Icon name="check" size={14} /> Usar resposta</button>
            </div>
          )}
          <button className="btn btn-ghost btn-block" style={{ marginTop: 8 }} onClick={() => run(tab)} disabled={loading}><Icon name="refresh" size={15} /> {loading ? 'Gerando…' : 'Gerar novamente'}</button>
        </div>
      ) : (
        <button className="btn btn-soft btn-block" onClick={() => run(tab)} disabled={loading}><Icon name="sparkle" size={16} /> {loading ? 'Analisando…' : (tab === 'resumo' ? 'Resumir conversa' : 'Sugerir resposta')}</button>
      )}
    </div>
  );
}

Object.assign(window, { AdvboxPanel, ZapsignPanel, CalculoPanel, IAPanel, PanelHead });


/* ===== contactpanel.jsx ===== */
/* ============================================================
   Contact panel (column D) — all tabs
   ============================================================ */

const CONTACT_TABS = [
  { id: 'perfil',    icon: 'user',      label: 'Perfil' },
  { id: 'historico', icon: 'history',   label: 'Histórico de Atendimento' },
  { id: 'anotacoes', icon: 'note',      label: 'Anotações Internas' },
  { id: 'funil',     icon: 'funnel',    label: 'Funil' },
  { id: 'delegados', icon: 'contacts',  label: 'Usuários Delegados' },
  { id: 'dialogos',  icon: 'bot',       label: 'Diálogos / Contexto' },
  { id: 'midias',    icon: 'media',     label: 'Mídias' },
  { id: 'advbox',    icon: 'scale',     label: 'Advbox',          integ: true },
  { id: 'zapsign',   icon: 'signature', label: 'ZapSign',         integ: true },
  { id: 'calculo',   icon: 'calc',      label: 'Cálculo Bancário', integ: true },
  { id: 'ia',        icon: 'sparkle',   label: 'Assistente IA',   integ: true },
];

function PerfilTab({ conv }) {
  const [chatbot, setChatbot] = React.useState(!!conv.chatbot);
  const [archived, setArchived] = React.useState(conv.status === 'done');
  const [ownerId, setOwnerId] = React.useState(conv.owner || null);
  const [stage, setStage] = React.useState(conv.stage || '');
  const [proc, setProc] = React.useState(conv.numProcesso || '');
  const [saving, setSaving] = React.useState(false);
  const [savedMsg, setSavedMsg] = React.useState(null);
  const post = (url, body) => fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
  const assign = (id) => { setOwnerId(id); post(`/api/conversations/${conv.id}/assign`, { assignee_id: id }).catch(() => {}); };
  const toggleChatbot = (v) => { setChatbot(v); post(`/api/conversations/${conv.id}/attributes`, { custom_attributes: { funil_chatbot: v } }).catch(() => {}); };
  const toggleArchive = (v) => { setArchived(v); post(`/api/conversations/${conv.id}/status`, { status: v ? 'done' : 'active' }).catch(() => {}); };
  const saveFields = () => {
    setSaving(true); setSavedMsg(null);
    post(`/api/conversations/${conv.id}/attributes`, { custom_attributes: { funil_estagio: stage, numero_processo: proc } })
      .then(r => setSavedMsg(r.ok ? 'Salvo ✓' : 'Erro ao salvar'))
      .catch(() => setSavedMsg('Erro ao salvar'))
      .finally(() => { setSaving(false); setTimeout(() => setSavedMsg(null), 2500); });
  };
  const addTag = () => {
    const t = prompt('Nome da tag:'); if (!t) return;
    const labels = [...(conv.tags || []), t.trim()];
    post(`/api/conversations/${conv.id}/labels`, { labels }).then(() => { conv.tags = labels; alert('Tag adicionada (recarregue para ver na lista).'); }).catch(() => alert('Falha ao adicionar tag.'));
  };
  return (
    <div className="cp-pad">
      <div className="col" style={{ alignItems: 'center', gap: 8, marginBottom: 16 }}>
        <Avatar name={conv.name} color={conv.color} initials={conv.initials} size={72} online={conv.online} />
        <div className="col" style={{ alignItems: 'center', gap: 2 }}>
          <span style={{ fontFamily: 'var(--font-title)', fontWeight: 700, fontSize: 18 }}>{conv.name}</span>
          <span className="muted" style={{ fontSize: 13 }}>{conv.phone}</span>
        </div>
      </div>

      <div className="cp-rowitem"><span className="row gap8"><Icon name="bot" size={17} style={{ color: 'var(--text-2)' }} /> Chatbot (IA)</span>
        <Toggle on={chatbot} onChange={toggleChatbot} labels={['Sim', 'Não']} /></div>
      <div className="cp-rowitem"><span className="row gap8"><Icon name="archive" size={17} style={{ color: 'var(--text-2)' }} /> Resolver / arquivar</span>
        <Toggle on={archived} onChange={toggleArchive} labels={['Sim', 'Não']} /></div>

      <div className="cp-sub">Responsável</div>
      <select className="select" value={ownerId || ''} onChange={e => assign(e.target.value ? Number(e.target.value) : null)}>
        <option value="">Não atribuído</option>
        {USERS.map(u => <option key={u.id} value={u.id}>{u.name}</option>)}
      </select>
      <button className="btn btn-soft btn-block" style={{ marginTop: 8 }} onClick={() => assign(null)}><Icon name="contacts" size={15} /> Delegar para Fila</button>

      <div className="cp-sub">Tags</div>
      <div className="row" style={{ flexWrap: 'wrap', gap: 6 }}>
        {(conv.tags || []).map(t => <Tag key={t} id={t} />)}
        <button className="tag-add" onClick={addTag}><Icon name="plus" size={13} /> Nova Tag</button>
      </div>

      <div className="cp-sub">Campos Personalizados</div>
      <div className="field" style={{ marginBottom: 10 }}><span className="label">Fase do CRM</span>
        <select className="select" value={stage} onChange={e => setStage(e.target.value)}>
          <option value="">—</option>
          {FUNNEL_STAGES.map(s => <option key={s.name} value={s.name}>{s.name}</option>)}
        </select></div>
      <div className="field" style={{ marginBottom: 10 }}><span className="label">Número do processo</span>
        <input className="input" value={proc} onChange={e => setProc(e.target.value)} placeholder="0000000-00.0000.0.00.0000" /></div>
      <button className="btn btn-accent btn-block" onClick={saveFields} disabled={saving}>{saving ? 'Salvando…' : 'Salvar campos'}</button>
      {savedMsg && <div className="tiny" style={{ textAlign: 'center', marginTop: 6, color: 'var(--green-500)' }}>{savedMsg}</div>}
    </div>
  );
}

function HistoricoTab() {
  const items = [
    { t: '06/06 14:05', u: 'Dra. Mariana Lima', act: 'Iniciou atendimento', st: 'active' },
    { t: '05/06 16:40', u: 'Dr. Rafael Amorim', act: 'Análise do contrato bancário', st: 'active' },
    { t: '04/06 09:25', u: 'Camila Borges', act: 'Triagem inicial — lead Instagram', st: 'open' },
    { t: '04/06 09:20', u: 'Chatbot — Triagem', act: 'Atendimento automático', st: 'wait' },
  ];
  return (
    <div className="cp-pad">
      <div className="cp-sub" style={{ marginTop: 0 }}>Histórico de Atendimento</div>
      <div className="timeline">
        {items.map((it, i) => (
          <div className="tl-item" key={i}>
            <div className="tl-mark" />
            <div className="col" style={{ gap: 3 }}>
              <div className="row gap8"><span style={{ fontWeight: 700, fontSize: 13 }}>{it.act}</span><span className="spacer" /><StatusBadge status={it.st} dot={false} /></div>
              <span className="tiny muted">{it.u} · {it.t}</span>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

function AnotacoesTab({ conv }) {
  const [notes, setNotes] = React.useState(null);
  const [draft, setDraft] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const load = () => fetch(`/api/conversations/${conv.id}/notes`).then(r => r.json()).then(d => setNotes(d.notes || [])).catch(() => setNotes([]));
  React.useEffect(() => { setNotes(null); load(); }, [conv.id]);
  const add = () => {
    const t = draft.trim(); if (!t || busy) return; setBusy(true);
    fetch(`/api/conversations/${conv.id}/notes`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content: t }) })
      .then(r => r.ok ? r.json() : Promise.reject()).then(() => { setDraft(''); load(); })
      .catch(() => alert('Falha ao salvar anotação.')).finally(() => setBusy(false));
  };
  return (
    <div className="cp-pad">
      <div className="col gap8" style={{ marginBottom: 12 }}>
        <textarea className="textarea" rows={3} placeholder="Escreva uma anotação interna (só a equipe vê)…" value={draft} onChange={e => setDraft(e.target.value)} />
        <button className="btn btn-accent btn-sm" onClick={add} disabled={busy} style={{ alignSelf: 'flex-end' }}><Icon name="plus" size={15} /> {busy ? 'Salvando…' : 'Nova anotação'}</button>
      </div>
      {notes === null && <div className="tiny muted">Carregando…</div>}
      {notes && notes.length === 0 && <div className="tiny muted">Nenhuma anotação ainda.</div>}
      {(notes || []).map((n, i) => (
        <div className="note-card" key={i}>
          <div className="row gap8" style={{ marginBottom: 6 }}>
            <span style={{ fontWeight: 800, fontSize: 12.5 }}>{n.author}</span>
            <span className="spacer" /><span className="tiny" style={{ color: '#9A8A4A' }}>{n.date}</span>
          </div>
          <p style={{ margin: 0, fontSize: 13, lineHeight: 1.5, whiteSpace: 'pre-wrap' }}>{n.text}</p>
        </div>
      ))}
    </div>
  );
}

function FunilTab({ conv }) {
  const idx = FUNNEL_STAGES.findIndex(s => s.name === conv.stage);
  return (
    <div className="cp-pad">
      <div className="cp-sub" style={{ marginTop: 0 }}>Funil — VENDAS</div>
      <div className="tiny muted" style={{ marginBottom: 12 }}>Etapa atual do contato no funil comercial.</div>
      <div className="funil-steps">
        {FUNNEL_STAGES.slice(0, 9).map((s, i) => (
          <div key={s.name} className={`fs-row ${i === idx ? 'current' : i < idx ? 'past' : ''}`}>
            <span className="fs-dot">{i < idx ? <Icon name="check" size={12} /> : i === idx ? <span className="fs-pulse" /> : i + 1}</span>
            <span className="fs-name">{s.name}</span>
            {i === idx && <span className="badge badge-active" style={{ marginLeft: 'auto' }}>Atual</span>}
          </div>
        ))}
      </div>
    </div>
  );
}

function DelegadosTab() {
  return (
    <div className="cp-pad">
      <div className="cp-sub" style={{ marginTop: 0 }}>Histórico de Usuários Delegados</div>
      <div className="timeline">
        {DELEGATIONS.map((d, i) => (
          <div className="tl-item" key={i}>
            <div className="tl-mark" />
            <div className="col" style={{ gap: 3 }}>
              <span style={{ fontSize: 13 }}><b>{d.from}</b> <Icon name="chevRight" size={12} style={{ verticalAlign: -1, color: 'var(--text-3)' }} /> <b>{d.to}</b></span>
              <span className="tiny muted">{d.reason} · {d.date}</span>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

function DialogosTab() {
  return (
    <div className="cp-pad">
      <div className="cp-sub" style={{ marginTop: 0 }}>Contexto</div>
      <div className="ctx-table">
        <div className="ctx-head"><span>$TAG</span><span>VALOR</span></div>
        {CONTEXT_VARS.map((c, i) => (
          <div className="ctx-row" key={i}><span className="ctx-tag">{c.tag}</span><span className="ctx-val">{c.value}</span></div>
        ))}
      </div>
      <div className="cp-sub">Diálogos acionados</div>
      {[{ n: 'Triagem inicial', t: '04/06 09:20', s: 'Concluído' }, { n: 'Qualificação bancário', t: '04/06 09:24', s: 'Concluído' }].map((d, i) => (
        <div className="integ-card proc" key={i}>
          <div className="row" style={{ justifyContent: 'space-between' }}><span style={{ fontWeight: 700, fontSize: 13 }}>{d.n}</span><span className="badge badge-done"><span className="bdot" />{d.s}</span></div>
          <span className="tiny muted">{d.t}</span>
        </div>
      ))}
    </div>
  );
}

function MidiasTab() {
  const swatches = ['#3A6B5E', '#B8924A', '#7A5A6E', '#5A6E2A', '#C2683A', '#516170'];
  return (
    <div className="cp-pad">
      <div className="cp-sub" style={{ marginTop: 0 }}>Mídias trocadas <span className="cp-count">9</span></div>
      <div className="media-grid">
        <div className="media-tile doc"><Icon name="doc" size={22} /><span className="tiny">Contrato.pdf</span></div>
        {swatches.map((c, i) => (
          <div className="media-tile" key={i} style={{ background: `linear-gradient(135deg, ${c}, ${c}99)` }}>
            <Icon name="media" size={20} style={{ color: 'rgba(255,255,255,.85)' }} />
          </div>
        ))}
        <div className="media-tile doc"><Icon name="mic" size={20} /><span className="tiny">Áudio 0:42</span></div>
      </div>
    </div>
  );
}

function ContactPanel({ conv, tab, setTab, onClose }) {
  const cur = CONTACT_TABS.find(t => t.id === tab) || CONTACT_TABS[0];
  return (
    <aside className="contact-panel">
      <div className="cp-tabbar">
        {CONTACT_TABS.map(t => (
          <button key={t.id} className={`cp-tab ${tab === t.id ? 'on' : ''} ${t.integ ? 'integ' : ''}`} title={t.label} onClick={() => setTab(t.id)}>
            <Icon name={t.icon} size={18} />
          </button>
        ))}
      </div>
      <div className="cp-content">
        <div className="cp-titlebar">
          <span style={{ fontWeight: 800, fontSize: 13.5 }}>{cur.label}</span>
          {cur.integ && <span className="integ-pill"><Icon name="plug" size={11} /> Integração</span>}
          <span className="spacer" />
          <button className="btn btn-ghost btn-icon" style={{ width: 28, height: 28 }} onClick={onClose}><Icon name="chevRight" size={16} /></button>
        </div>
        <div className="cp-scroll scroll-y">
          {tab === 'perfil' && <PerfilTab conv={conv} />}
          {tab === 'historico' && <HistoricoTab />}
          {tab === 'anotacoes' && <AnotacoesTab conv={conv} />}
          {tab === 'funil' && <FunilTab conv={conv} />}
          {tab === 'delegados' && <DelegadosTab />}
          {tab === 'dialogos' && <DialogosTab />}
          {tab === 'midias' && <MidiasTab />}
          {tab === 'advbox' && <AdvboxPanel conv={conv} />}
          {tab === 'zapsign' && <ZapsignPanel conv={conv} />}
          {tab === 'calculo' && <CalculoPanel conv={conv} />}
          {tab === 'ia' && <IAPanel conv={conv} />}
        </div>
      </div>
    </aside>
  );
}

Object.assign(window, { ContactPanel, CONTACT_TABS });


/* ===== atendimento.jsx ===== */
/* ============================================================
   ATENDIMENTO — column B (conversation list) + column C (messages)
   ============================================================ */

const QUICK_FILTERS = [
  { id: 'unread', label: 'Não lido', icon: 'unread' },
  { id: 'archived', label: 'Arquivado', icon: 'archive' },
  { id: 'broadcast', label: 'Transmissão', icon: 'broadcast' },
  { id: 'fav', label: 'Favorito', icon: 'star' },
  { id: 'scheduled', label: 'Agendado', icon: 'calendar' },
];

function ConvCard({ c, active, onClick }) {
  const owner = USERS.find(u => u.id === c.owner);
  return (
    <button onClick={onClick} className="conv-card" data-active={active || undefined}>
      <Avatar name={c.name} color={c.color} initials={c.initials} size={46} online={c.online} />
      <div className="col" style={{ flex: 1, minWidth: 0, gap: 3 }}>
        <div className="row" style={{ gap: 8 }}>
          <span className="cc-name">{c.name}</span>
          <span className="spacer" />
          <span className="cc-time">{c.time}</span>
        </div>
        <div className="row" style={{ gap: 7 }}>
          <span className="cc-prev">
            {c.last.startsWith('Você:') && <Icon name="checkcheck" size={14} style={{ color: 'var(--st-active)', marginRight: 3, verticalAlign: -2, display: 'inline-block' }} />}
            {c.audio && <Icon name="mic" size={13} style={{ verticalAlign: -2, marginRight: 3, display: 'inline-block' }} />}
            {c.last}
          </span>
          <span className="spacer" />
          {c.unread > 0 && <span className="cc-unread">{c.unread}</span>}
        </div>
        <div className="row" style={{ gap: 6, marginTop: 3 }}>
          <StatusBadge status={c.status} />
          <div className="row" style={{ gap: 4 }}>
            {c.tags.slice(0, 2).map(t => <Tag key={t} id={t} />)}
          </div>
          <span className="spacer" />
          {owner ? (
            <span title={owner.name}><Avatar name={owner.name} color={owner.color} initials={owner.initials} size={20} /></span>
          ) : (
            <span className="cc-unassigned" title="Sem responsável"><Icon name="user" size={13} /></span>
          )}
        </div>
      </div>
    </button>
  );
}

function ConvList({ activeId, onSelect, convs }) {
  const [filtersOpen, setFiltersOpen] = React.useState(false);
  const [quick, setQuick] = React.useState(null);
  const [q, setQ] = React.useState('');
  const source = convs || CONV;
  const list = source.filter(c => {
    if (q && !c.name.toLowerCase().includes(q.toLowerCase())) return false;
    if (quick === 'unread' && !c.unread) return false;
    if (quick === 'fav' && !c.fav) return false;
    return true;
  });
  return (
    <section className="conv-list">
      <div className="cl-top">
        <div className="input-search" style={{ flex: 1 }}>
          <Icon name="search" size={16} />
          <input className="input" placeholder="Pesquisar mensagem" value={q} onChange={e => setQ(e.target.value)} />
        </div>
        <button className="btn btn-primary btn-icon" title="Novo contato"><Icon name="plus" size={18} /></button>
      </div>

      <button className="cl-filtertoggle" onClick={() => setFiltersOpen(v => !v)}>
        <Icon name="filter" size={15} /> Filtros
        <span className="spacer" />
        <Icon name="chevDown" size={15} style={{ transform: filtersOpen ? 'rotate(180deg)' : 'none', transition: 'transform .2s' }} />
      </button>
      {filtersOpen && (
        <div className="cl-filters">
          <div className="ff-grid">
            <div className="field"><span className="label">Nome</span><input className="input" placeholder="Buscar nome" /></div>
            <div className="field"><span className="label">Aparelho</span>
              <select className="select"><option>Todos</option><option>Principal</option><option>Comercial</option></select></div>
            <div className="field"><span className="label">Número WhatsApp</span><input className="input" placeholder="+55…" /></div>
            <div className="field"><span className="label">Tags</span>
              <select className="select"><option>Todas</option>{TAGS.map(t => <option key={t.id}>{t.name}</option>)}</select></div>
            <div className="field"><span className="label">Usuário / Departamento</span>
              <select className="select"><option>Todos</option>{USERS.map(u => <option key={u.id}>{u.name}</option>)}</select></div>
            <div className="field"><span className="label">Etapa do Funil</span>
              <select className="select"><option>Todas</option>{FUNNEL_STAGES.map(s => <option key={s.name}>{s.name}</option>)}</select></div>
            <div className="field"><span className="label">Status</span>
              <select className="select"><option>Todos</option>{Object.values(STATUS).map(s => <option key={s.key}>{s.label}</option>)}</select></div>
            <div className="field"><span className="label">Ordenar Por</span>
              <select className="select"><option>Mais recentes</option><option>Mais antigos</option><option>Não lidos</option></select></div>
          </div>
          <div className="row gap8" style={{ justifyContent: 'flex-end', marginTop: 4 }}>
            <button className="btn btn-ghost btn-sm">Limpar</button>
            <button className="btn btn-accent btn-sm">Aplicar filtros</button>
          </div>
        </div>
      )}

      <div className="cl-quick">
        {QUICK_FILTERS.map(f => (
          <button key={f.id} className={`qf ${quick === f.id ? 'on' : ''}`} onClick={() => setQuick(quick === f.id ? null : f.id)}>
            <Icon name={f.icon} size={14} />{f.label}
          </button>
        ))}
      </div>

      <div className="cl-count">Exibindo <b>{list.length}</b> resultados</div>

      <div className="cl-scroll scroll-y">
        {list.map(c => <ConvCard key={c.id} c={c} active={c.id === activeId} onClick={() => onSelect(c.id)} />)}
      </div>
    </section>
  );
}

/* ---------- Column C: Messages ---------- */
function Bubble({ m }) {
  const out = m.dir === 'out';
  return (
    <div className={`bubrow ${out ? 'out' : 'in'}`}>
      <div className={`bubble ${out ? 'b-out' : 'b-in'}`}>
        {m.file && (
          <div className="bub-file">
            <div className="bf-ic"><Icon name="doc" size={20} /></div>
            <div className="col" style={{ minWidth: 0 }}>
              <span className="bf-name">{m.file.name}</span>
              <span className="bf-size">{m.file.size} · PDF</span>
            </div>
            <Icon name="download" size={17} style={{ color: 'var(--text-2)' }} />
          </div>
        )}
        {m.text && !m.file && <span className="bub-text">{m.text}</span>}
        {m.file && m.text === m.file.name ? null : null}
        <span className="bub-meta">{m.t}{out && <Icon name="checkcheck" size={15} style={{ color: m.read ? '#4F93C4' : 'var(--text-3)' }} />}</span>
      </div>
    </div>
  );
}

const EMOJIS = ['😊', '👍', '🙏', '✅', '❤️', '😅', '📄', '⚖️', '📌', '🗓️', '💰', '📞', '👏', '🤝', '⏰', '✍️', '🎉', '😉', '🔎', '📎'];
function MessagePanel({ conv, status, onStatus, panelTab, setPanelTab, onToggleContact, contactOpen }) {
  const owner = USERS.find(u => u.id === conv.owner);
  const [stOpen, setStOpen] = React.useState(false);
  const [draft, setDraft] = React.useState('');
  const [msgs, setMsgs] = React.useState(null);
  const [sending, setSending] = React.useState(false);
  const [emojiOpen, setEmojiOpen] = React.useState(false);
  const [searchOpen, setSearchOpen] = React.useState(false);
  const [searchQ, setSearchQ] = React.useState('');
  const [canned, setCanned] = React.useState([]);
  const [recording, setRecording] = React.useState(false);
  const [schedOpen, setSchedOpen] = React.useState(false);
  const [schedAt, setSchedAt] = React.useState('');
  const bodyRef = React.useRef(null);
  const fileRef = React.useRef(null);
  const recRef = React.useRef(null);
  const chunksRef = React.useRef([]);
  const firstScroll = React.useRef(true);
  const hm = () => new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' });
  const fetchMsgs = (merge) => fetch(`/api/conversations/${conv.id}/messages`).then(r => r.json()).then(d => {
    const server = d.messages || [];
    setMsgs(prev => merge && prev ? [...server, ...prev.filter(m => m.pending && String(m.id).startsWith('tmp-'))] : server);
  }).catch(() => { setMsgs(p => p || []); });
  React.useEffect(() => {
    firstScroll.current = true; setMsgs(null); fetchMsgs(false);
    fetch(`/api/conversations/${conv.id}/seen`, { method: 'POST' }).catch(() => {});
    const iv = setInterval(() => fetchMsgs(true), 5000);   // tempo real (polling 5s)
    return () => clearInterval(iv);
  }, [conv.id]);
  React.useEffect(() => {
    const el = bodyRef.current; if (!el) return;
    const nearBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 140;
    if (firstScroll.current && msgs) { el.scrollTop = el.scrollHeight; firstScroll.current = false; }
    else if (nearBottom) el.scrollTop = el.scrollHeight;
  }, [msgs]);
  React.useEffect(() => { window.__cactusInsertDraft = (t) => setDraft(t); return () => { if (window.__cactusInsertDraft) delete window.__cactusInsertDraft; }; }, []);
  React.useEffect(() => { fetch('/api/canned').then(r => r.json()).then(d => setCanned(d.items || [])).catch(() => {}); }, []);

  const addOpt = (partial) => { const id = 'tmp-' + Date.now(); setMsgs(m => [...(m || []), { id, dir: 'out', t: hm(), read: false, pending: true, ...partial }]); return id; };
  const settle = (id, ok) => setMsgs(m => (m || []).map(x => x.id === id ? { ...x, pending: false, failed: !ok } : x));

  const send = () => {
    const text = draft.trim(); if (!text || sending) return;
    setSending(true); const id = addOpt({ text }); setDraft(''); setEmojiOpen(false);
    fetch(`/api/conversations/${conv.id}/messages`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content: text }) })
      .then(r => r.ok ? r.json() : Promise.reject()).then(() => settle(id, true)).catch(() => settle(id, false)).finally(() => setSending(false));
  };
  const upload = (file, asAudio) => {
    if (!file) return;
    const id = addOpt(asAudio ? { text: '🎤 Áudio', audio: true } : { file: { name: file.name, size: '' }, text: file.name });
    const fd = new FormData(); fd.append('file', file, file.name || (asAudio ? 'audio.webm' : 'arquivo'));
    fetch(`/api/conversations/${conv.id}/attachment`, { method: 'POST', body: fd })
      .then(r => r.ok ? r.json() : Promise.reject()).then(() => settle(id, true)).catch(() => settle(id, false));
  };
  const onPickFile = (e) => { const f = e.target.files && e.target.files[0]; if (f) upload(f, false); e.target.value = ''; };
  const toggleRec = async () => {
    if (recording) { try { recRef.current && recRef.current.stop(); } catch (e) {} return; }
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      const mr = new MediaRecorder(stream); recRef.current = mr; chunksRef.current = [];
      mr.ondataavailable = (ev) => { if (ev.data && ev.data.size) chunksRef.current.push(ev.data); };
      mr.onstop = () => {
        const blob = new Blob(chunksRef.current, { type: (mr.mimeType || 'audio/webm') });
        upload(new File([blob], 'audio.webm', { type: blob.type }), true);
        stream.getTracks().forEach(t => t.stop()); setRecording(false);
      };
      mr.start(); setRecording(true);
    } catch (e) { alert('Não foi possível acessar o microfone. Permita o acesso no navegador.'); }
  };
  const scheduleSend = () => {
    const text = draft.trim(); if (!text || !schedAt) return;
    fetch(`/api/conversations/${conv.id}/schedule`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content: text, sendAt: new Date(schedAt).toISOString() }) })
      .then(r => r.ok ? r.json() : Promise.reject()).then(() => { setSchedOpen(false); setDraft(''); setSchedAt(''); alert('Mensagem agendada com sucesso.'); }).catch(() => alert('Falha ao agendar.'));
  };
  const slash = draft.startsWith('/') ? draft.slice(1).toLowerCase() : null;
  const cannedMatches = slash !== null ? canned.filter(c => (c.short || '').toLowerCase().includes(slash) || (c.content || '').toLowerCase().includes(slash)).slice(0, 6) : [];
  const shownMsgs = (msgs || []).filter(m => !searchQ || (m.text || '').toLowerCase().includes(searchQ.toLowerCase()));
  const popStyle = { position: 'absolute', bottom: 60, left: 12, right: 12, background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 10, boxShadow: 'var(--shadow-lg)', zIndex: 20, padding: 8 };

  return (
    <section className="msg-panel" style={{ position: 'relative' }}>
      <header className="mp-head">
        <Avatar name={conv.name} color={conv.color} initials={conv.initials} size={42} online={conv.online} />
        <div className="col mp-id" style={{ minWidth: 0, gap: 1 }}>
          <span className="mp-name">{conv.name}</span>
          <span className="mp-phone">{conv.phone}{conv.online && <span style={{ color: '#4FB477', fontWeight: 700 }}> · online</span>}</span>
        </div>
        <div style={{ position: 'relative', marginLeft: 4, flexShrink: 0 }}>
          <button className={`mp-status badge ${STATUS[status].cls}`} onClick={() => setStOpen(v => !v)}>
            <span className="bdot" />{STATUS[status].label}<Icon name="chevDown" size={13} />
          </button>
          {stOpen && (
            <div className="mp-status-menu">
              {Object.values(STATUS).map(s => (
                <button key={s.key} onClick={() => { onStatus(s.key); setStOpen(false); }}>
                  <span className={`badge ${s.cls}`}><span className="bdot" />{s.label}</span>
                </button>
              ))}
            </div>
          )}
        </div>
        <span className="spacer" />
        <IconBtn name="search" title="Buscar na conversa" active={searchOpen} onClick={() => setSearchOpen(v => !v)} />
        <IconBtn name="paperclip" title="Anexar" onClick={() => fileRef.current && fileRef.current.click()} />
        <div className="mp-head-sep" />
        <button className={`mp-tab ${contactOpen ? 'on' : ''}`} title={contactOpen ? 'Ocultar painel do contato' : 'Mostrar painel do contato'}
          onClick={() => onToggleContact(!contactOpen)}>
          <Icon name={contactOpen ? 'chevRight' : 'user'} size={18} />
        </button>
      </header>

      {searchOpen && (
        <div style={{ padding: '8px 14px', borderBottom: '1px solid var(--border)', background: 'var(--surface)' }}>
          <div className="input-search"><Icon name="search" size={15} /><input className="input" autoFocus placeholder="Buscar nesta conversa" value={searchQ} onChange={e => setSearchQ(e.target.value)} /></div>
        </div>
      )}

      <div className="mp-body scroll-y" ref={bodyRef}>
        {msgs === null && <div className="mp-typing" style={{ opacity: .7 }}>Carregando mensagens…</div>}
        {msgs && shownMsgs.length === 0 && <div className="mp-typing" style={{ opacity: .7 }}>{searchQ ? 'Nada encontrado.' : 'Sem mensagens nesta conversa.'}</div>}
        {shownMsgs.map(m => <Bubble key={m.id} m={m} />)}
      </div>

      <input ref={fileRef} type="file" style={{ display: 'none' }} onChange={onPickFile} />
      {emojiOpen && (
        <div style={popStyle}>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>
            {EMOJIS.map(e => <button key={e} onClick={() => setDraft(d => d + e)} style={{ fontSize: 20, width: 36, height: 36, border: 'none', background: 'transparent', borderRadius: 8, cursor: 'pointer' }}>{e}</button>)}
          </div>
        </div>
      )}
      {cannedMatches.length > 0 && (
        <div style={popStyle}>
          <div className="tiny muted" style={{ padding: '2px 6px 6px' }}>Respostas rápidas</div>
          {cannedMatches.map((c, i) => (
            <button key={i} onClick={() => { setDraft(c.content); }} style={{ display: 'block', width: '100%', textAlign: 'left', border: 'none', background: 'transparent', padding: '7px 8px', borderRadius: 7, cursor: 'pointer' }}>
              <b style={{ color: 'var(--green-500)' }}>/{c.short}</b> <span className="tiny muted">{(c.content || '').slice(0, 70)}</span>
            </button>
          ))}
        </div>
      )}
      {schedOpen && (
        <div style={popStyle}>
          <div className="tiny muted" style={{ padding: '2px 6px 8px' }}>Agendar esta mensagem</div>
          <input className="input" type="datetime-local" value={schedAt} onChange={e => setSchedAt(e.target.value)} style={{ marginBottom: 8 }} />
          <button className="btn btn-accent btn-block" onClick={scheduleSend} disabled={!schedAt}><Icon name="calendar" size={15} /> Agendar envio</button>
        </div>
      )}

      <footer className="mp-foot">
        <IconBtn name="emoji" title="Emoji" active={emojiOpen} onClick={() => setEmojiOpen(v => !v)} />
        <IconBtn name="paperclip" title="Anexar arquivo/imagem" onClick={() => fileRef.current && fileRef.current.click()} />
        <div className="mp-inputwrap">
          <input className="mp-input" placeholder="Digite uma mensagem ou use / para atalhos" value={draft} onChange={e => setDraft(e.target.value)} onKeyDown={e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } }} />
        </div>
        <IconBtn name="calendar" title="Agendar envio" active={schedOpen} onClick={() => { if (!draft.trim()) { alert('Digite a mensagem antes de agendar.'); return; } setSchedOpen(v => !v); }} />
        {draft.trim()
          ? <button className="btn btn-accent btn-icon mp-send" title="Enviar" onClick={send} disabled={sending} style={sending ? { opacity: .6 } : null}><Icon name="send" size={18} /></button>
          : <button className={`btn btn-icon ${recording ? 'btn-accent' : 'btn-primary'}`} title={recording ? 'Parar e enviar áudio' : 'Gravar áudio'} onClick={toggleRec}><Icon name={recording ? 'check' : 'mic'} size={18} /></button>}
      </footer>
    </section>
  );
}

Object.assign(window, { ConvList, MessagePanel, QUICK_FILTERS });


/* ===== atendimento_screen.jsx ===== */
/* ============================================================
   ATENDIMENTO screen composer (B + C + D)
   ============================================================ */
function Atendimento() {
  const [convs, setConvs] = React.useState(() => CONV);
  const [activeId, setActiveId] = React.useState(() => (CONV[0] && CONV[0].id) || null);
  const [statusMap, setStatusMap] = React.useState(() => Object.fromEntries(CONV.map(c => [c.id, c.status])));
  const [contactOpen, setContactOpen] = React.useState(true);
  const [panelTab, setPanelTab] = React.useState('perfil');
  React.useEffect(() => {
    const load = () => fetch('/api/conversations').then(r => r.json()).then(d => { if (Array.isArray(d.conversations)) { setConvs(d.conversations); CONV = d.conversations; } }).catch(() => {});
    const iv = setInterval(load, 8000);   // lista ao vivo (polling 8s)
    return () => clearInterval(iv);
  }, []);
  const conv = convs.find(c => c.id === activeId);
  const status = statusMap[activeId] || (conv && conv.status) || 'open';
  return (
    <div className="atendimento">
      <ConvList activeId={activeId} onSelect={setActiveId} convs={convs} />
      {conv ? (
        <React.Fragment>
          <MessagePanel
            key={activeId}
            conv={conv}
            status={status}
            onStatus={(s) => { setStatusMap(m => ({ ...m, [activeId]: s })); fetch(`/api/conversations/${activeId}/status`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ status: s }) }).catch(() => {}); }}
            panelTab={panelTab} setPanelTab={setPanelTab}
            contactOpen={contactOpen} onToggleContact={setContactOpen}
          />
          {contactOpen && <ContactPanel conv={conv} tab={panelTab} setTab={setPanelTab} onClose={() => setContactOpen(false)} />}
        </React.Fragment>
      ) : (
        <div className="msg-panel" style={{ display: 'grid', placeItems: 'center', color: 'var(--text-3)' }}>Selecione uma conversa</div>
      )}
    </div>
  );
}
Object.assign(window, { Atendimento });


/* ===== funil.jsx ===== */
/* ============================================================
   FUNIL — funnel chart + Kanban
   ============================================================ */
function FunnelChart() {
  const stages = FUNNEL_STAGES.slice(0, 9);
  const max = stages[0].count;
  const colors = ['#2B3616','#3A4A1E','#46591F','#5A6E2A','#6E8430','#7BA05B','#8FB06E','#A6C089','#BFD2A6'];
  return (
    <div className="funnel-chart">
      {stages.map((s, i) => {
        const w = 40 + (s.count / max) * 60;
        const conv = i > 0 ? Math.round((s.count / stages[i - 1].count) * 100) : 100;
        return (
          <div className="fc-row" key={s.name}>
            <div className="fc-label"><span className="fc-name">{s.name}</span><span className="fc-conv">{conv}%</span></div>
            <div className="fc-bar-wrap">
              <div className="fc-bar" style={{ width: w + '%', background: colors[i] }}>
                <span className="fc-count">{s.count}</span>
              </div>
            </div>
          </div>
        );
      })}
    </div>
  );
}

function KanbanCard({ id, onDragStart }) {
  const c = CONV.find(x => x.id === id);
  if (!c) return null;
  const owner = USERS.find(u => u.id === c.owner);
  return (
    <div className="kb-card" draggable onDragStart={e => onDragStart(e, id)}>
      <div className="row gap8" style={{ marginBottom: 8 }}>
        <Avatar name={c.name} color={c.color} initials={c.initials} size={32} />
        <div className="col" style={{ minWidth: 0 }}>
          <span style={{ fontWeight: 700, fontSize: 13, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{c.name}</span>
          <span className="tiny muted">{c.phone}</span>
        </div>
      </div>
      <p className="kb-prev">{c.last.replace('Você: ', '')}</p>
      <div className="row gap6" style={{ flexWrap: 'wrap', marginBottom: 8 }}>{c.tags.slice(0, 2).map(t => <Tag key={t} id={t} />)}</div>
      <div className="row gap8"><StatusBadge status={c.status} />
        <span className="spacer" />
        {owner && <Avatar name={owner.name} color={owner.color} initials={owner.initials} size={20} />}</div>
    </div>
  );
}

function Kanban() {
  const [cols, setCols] = React.useState(() => KANBAN.map(k => ({ ...k, cards: [...k.cards] })));
  const drag = React.useRef(null);
  const onDragStart = (e, id) => { drag.current = id; e.dataTransfer.effectAllowed = 'move'; };
  const onDrop = (stage) => {
    const id = drag.current; if (!id) return;
    setCols(prev => prev.map(c => ({ ...c, cards: c.cards.filter(x => x !== id) }))
      .map(c => c.stage === stage ? { ...c, cards: [...c.cards, id] } : c));
    drag.current = null;
  };
  return (
    <div className="kanban">
      {cols.map(col => (
        <div className="kb-col" key={col.stage}
          onDragOver={e => { e.preventDefault(); e.currentTarget.classList.add('over'); }}
          onDragLeave={e => e.currentTarget.classList.remove('over')}
          onDrop={e => { e.currentTarget.classList.remove('over'); onDrop(col.stage); }}>
          <div className="kb-colhead"><span className="kb-coltitle">{col.stage}</span><span className="cp-count">{col.cards.length}</span></div>
          <div className="kb-list">
            {col.cards.map(id => <KanbanCard key={id} id={id} onDragStart={onDragStart} />)}
            {col.cards.length === 0 && <div className="kb-empty">Arraste cards aqui</div>}
          </div>
        </div>
      ))}
    </div>
  );
}

function Funil() {
  const [view, setView] = React.useState('grafico');
  return (
    <div className="page route-anim">
      <div className="page-inner">
        <SectionTitle sub="Acompanhe a jornada comercial dos contatos por etapa."
          action={<div className="row gap10">
            <Segmented value={view} onChange={setView} options={[{ value: 'grafico', label: 'Gráfico', icon: 'funnel' }, { value: 'kanban', label: 'Kanban', icon: 'grid' }]} />
            <button className="btn btn-primary"><Icon name="plus" size={16} /> Criar novo funil</button>
          </div>}>Funil</SectionTitle>

        {view === 'grafico' ? (
          <div className="card card-pad funnel-card">
            <div className="row" style={{ justifyContent: 'space-between', marginBottom: 18 }}>
              <div className="row gap10"><span className="funnel-badge">VENDAS</span><span className="muted tiny">Atualizado há 5 min</span></div>
              <div className="row gap16">
                <div className="fk-stat"><span className="fk-val">466</span><span className="fk-lbl">contatos no funil</span></div>
                <div className="fk-stat"><span className="fk-val" style={{ color: 'var(--green-500)' }}>28</span><span className="fk-lbl">contratos enviados</span></div>
                <div className="fk-stat"><span className="fk-val" style={{ color: 'var(--gold)' }}>10%</span><span className="fk-lbl">conversão geral</span></div>
              </div>
            </div>
            <FunnelChart />
          </div>
        ) : <Kanban />}
      </div>
    </div>
  );
}
Object.assign(window, { Funil });


/* ===== dashboard.jsx ===== */
/* ============================================================
   DASHBOARD de gestão — chats não resolvidos por usuário
   ============================================================ */
function Dashboard() {
  const tot = DASH.reduce((a, r) => ({ open: a.open + r.open, active: a.active + r.active, wait: a.wait + r.wait, total: a.total + r.total }), { open: 0, active: 0, wait: 0, total: 0 });
  return (
    <div className="page route-anim">
      <div className="page-inner">
        <SectionTitle sub="Chats não resolvidos / em aberto por atendente e departamento."
          action={<div className="row gap10">
            <select className="select" style={{ width: 180 }}><option>Todos os departamentos</option><option>Cível</option><option>Bancário</option></select>
            <button className="btn btn-ghost"><Icon name="download" size={16} /> Exportar</button>
          </div>}>Dashboard</SectionTitle>

        <div className="dash-kpis">
          {[{ k: 'Total em aberto', v: tot.total, c: 'var(--text)', ic: 'chat' },
            { k: 'Aberto', v: tot.open, c: 'var(--st-open)', ic: 'flame' },
            { k: 'Em atendimento', v: tot.active, c: 'var(--st-active)', ic: 'reply' },
            { k: 'Aguardando', v: tot.wait, c: 'var(--st-wait)', ic: 'clock' }].map(x => (
            <div className="kpi-card" key={x.k}>
              <div className="kpi-ic" style={{ color: x.c, background: `color-mix(in srgb, ${x.c} 12%, transparent)` }}><Icon name={x.ic} size={20} /></div>
              <div className="col"><span className="kpi-val" style={{ color: x.c }}>{x.v}</span><span className="kpi-lbl">{x.k}</span></div>
            </div>
          ))}
        </div>

        <div className="card dash-table">
          <div className="dt-head">
            <span className="dt-c-user">Atendente</span>
            <span className="dt-pill" style={{ background: 'color-mix(in srgb, var(--st-open) 15%, transparent)', color: 'var(--st-open)' }}>Aberto</span>
            <span className="dt-pill" style={{ background: 'color-mix(in srgb, var(--st-active) 15%, transparent)', color: 'var(--st-active)' }}>Em atendimento</span>
            <span className="dt-pill" style={{ background: 'color-mix(in srgb, var(--st-wait) 22%, transparent)', color: '#b1842f' }}>Aguardando</span>
            <span className="dt-pill dt-total">Total</span>
          </div>
          {DASH.map(r => (
            <div className="dt-row" key={r.user.id}>
              <div className="dt-c-user row gap10">
                <Avatar name={r.user.name} color={r.user.color} initials={r.user.initials} size={38} />
                <div className="col" style={{ minWidth: 0 }}>
                  <span style={{ fontWeight: 700, fontSize: 13.5 }}>{r.user.name}</span>
                  <span className="tiny muted">{r.user.email} · {r.user.dept}</span>
                </div>
              </div>
              <span className="dt-cell" style={{ background: r.open ? 'color-mix(in srgb, var(--st-open) 10%, transparent)' : 'transparent', color: r.open ? 'var(--st-open)' : 'var(--text-3)' }}>{r.open}</span>
              <span className="dt-cell" style={{ background: r.active ? 'color-mix(in srgb, var(--st-active) 10%, transparent)' : 'transparent', color: r.active ? 'var(--st-active)' : 'var(--text-3)' }}>{r.active}</span>
              <span className="dt-cell" style={{ background: r.wait ? 'color-mix(in srgb, var(--st-wait) 16%, transparent)' : 'transparent', color: r.wait ? '#b1842f' : 'var(--text-3)' }}>{r.wait}</span>
              <span className="dt-cell dt-total">{r.total}</span>
            </div>
          ))}
          <div className="dt-row dt-foot">
            <div className="dt-c-user" style={{ fontWeight: 800 }}>Total geral</div>
            <span className="dt-cell" style={{ color: 'var(--st-open)' }}>{tot.open}</span>
            <span className="dt-cell" style={{ color: 'var(--st-active)' }}>{tot.active}</span>
            <span className="dt-cell" style={{ color: '#b1842f' }}>{tot.wait}</span>
            <span className="dt-cell dt-total">{tot.total}</span>
          </div>
        </div>
      </div>
    </div>
  );
}
Object.assign(window, { Dashboard });


/* ===== morescreens.jsx ===== */
/* ============================================================
   Cadastro screens: Respostas, Diálogos, Campanhas, Relatórios, Celulares, Tags
   ============================================================ */

function Respostas() {
  return (
    <div className="page route-anim"><div className="page-inner">
      <SectionTitle sub="Atalhos de texto para agilizar o atendimento. Digite / no chat para usar.">Respostas Rápidas</SectionTitle>
      <div className="two-col">
        <div className="card card-pad">
          <h3 style={{ fontSize: 16, marginBottom: 14 }}>Criar Resposta Rápida</h3>
          <div className="field" style={{ marginBottom: 12 }}><span className="label">Atalho</span>
            <div className="row" style={{ position: 'relative' }}><span className="slash">/</span><input className="input" style={{ paddingLeft: 26 }} placeholder="honorarios" /></div></div>
          <div className="field" style={{ marginBottom: 12 }}><span className="label">Título</span><input className="input" placeholder="Proposta de honorários" /></div>
          <div className="field" style={{ marginBottom: 14 }}><span className="label">Texto da resposta</span>
            <textarea className="textarea" rows={5} placeholder="Digite o conteúdo. Use $nome para personalizar."></textarea></div>
          <button className="btn btn-primary btn-block"><Icon name="check" size={16} /> Salvar resposta</button>
        </div>
        <div className="card card-pad how-card">
          <h3 style={{ fontSize: 15, marginBottom: 10 }}>Como utilizar</h3>
          <ul className="how-list">
            <li>No chat, digite <code>/</code> seguido do atalho.</li>
            <li>Selecione a resposta na lista que aparece.</li>
            <li>Use variáveis como <code>$nome</code> e <code>$processo</code> para personalizar.</li>
            <li>O texto é inserido na caixa antes do envio — você pode editar.</li>
          </ul>
        </div>
      </div>
      <div className="card" style={{ marginTop: 18, overflow: 'hidden' }}>
        <div className="tbl">
          <div className="tbl-head" style={{ gridTemplateColumns: '140px 1fr 2fr 90px' }}><span>Atalho</span><span>Título</span><span>Texto</span><span>Ações</span></div>
          {QUICK_REPLIES.map(r => (
            <div className="tbl-row" key={r.sh} style={{ gridTemplateColumns: '140px 1fr 2fr 90px' }}>
              <span><code className="code-chip">{r.sh}</code></span>
              <span style={{ fontWeight: 700 }}>{r.title}</span>
              <span className="muted ellip">{r.text}</span>
              <span className="row gap6"><button className="btn btn-ghost btn-icon" style={{ width: 30, height: 30 }}><Icon name="edit" size={15} /></button><button className="btn btn-ghost btn-icon" style={{ width: 30, height: 30, color: 'var(--st-open)' }}><Icon name="trash" size={15} /></button></span>
            </div>
          ))}
        </div>
      </div>
    </div></div>
  );
}

function Dialogos() {
  const [tab, setTab] = React.useState('dialogos');
  return (
    <div className="page route-anim"><div className="page-inner">
      <SectionTitle sub="Fluxos automáticos do chatbot do escritório."
        action={<button className="btn btn-primary"><Icon name="plus" size={16} /> Novo diálogo</button>}>Diálogos / Chatbot</SectionTitle>
      <div className="row gap16" style={{ marginBottom: 16, justifyContent: 'space-between' }}>
        <Segmented value={tab} onChange={setTab} options={[{ value: 'dialogos', label: 'Diálogos' }, { value: 'intencoes', label: 'Intenções' }, { value: 'entidades', label: 'Entidades' }]} />
        <div className="input-search" style={{ width: 280 }}><Icon name="search" size={15} /><input className="input" placeholder="Buscar diálogo" /></div>
      </div>
      <div className="card" style={{ overflow: 'hidden' }}>
        <div className="tbl">
          <div className="tbl-head" style={{ gridTemplateColumns: '36px 1.4fr 1fr 130px 130px' }}>
            <span><input type="checkbox" /></span><span>Diálogo</span><span>Grupo</span><span>Status</span><span>Atualizado</span></div>
          {DIALOGS.map(d => (
            <div className="tbl-row" key={d.name} style={{ gridTemplateColumns: '36px 1.4fr 1fr 130px 130px' }}>
              <span><input type="checkbox" /></span>
              <span className="row gap10"><span className="dlg-ic"><Icon name="bot" size={16} /></span><b>{d.name}</b></span>
              <span className="muted">{d.group}</span>
              <span><span className={`badge ${d.status === 'CONTÍNUO' ? 'badge-done' : 'badge-wait'}`}><span className="bdot" />{d.status}</span></span>
              <span className="muted tiny">{d.updated}</span>
            </div>
          ))}
        </div>
      </div>
    </div></div>
  );
}

function Campanhas() {
  const stMap = { 'Concluída': 'badge-done', 'Em andamento': 'badge-active', 'Agendada': 'badge-wait', 'Pausada': 'badge-open' };
  return (
    <div className="page route-anim"><div className="page-inner">
      <SectionTitle sub="Disparos em massa segmentados por diálogo."
        action={<button className="btn btn-primary"><Icon name="plus" size={16} /> Nova Campanha</button>}>Campanhas</SectionTitle>
      <div className="card" style={{ overflow: 'hidden' }}>
        <div className="tbl">
          <div className="tbl-head" style={{ gridTemplateColumns: '1.6fr 120px 1fr 110px 1.2fr 110px 110px' }}>
            <span>Campanha</span><span>Status</span><span>Progresso</span><span>Recipientes</span><span>Diálogo</span><span>Início</span><span>Criação</span></div>
          {CAMPAIGNS.map(c => (
            <div className="tbl-row" key={c.name} style={{ gridTemplateColumns: '1.6fr 120px 1fr 110px 1.2fr 110px 110px' }}>
              <span className="row gap10"><span className="dlg-ic" style={{ background: 'var(--green-100)', color: 'var(--green-700)' }}><Icon name="megaphone" size={16} /></span><b>{c.name}</b></span>
              <span><span className={`badge ${stMap[c.status]}`}><span className="bdot" />{c.status}</span></span>
              <span><div className="prog"><div className="prog-bar" style={{ width: c.prog + '%' }} /></div><span className="tiny muted">{c.prog}%</span></span>
              <span style={{ fontWeight: 700 }}>{c.recip.toLocaleString('pt-BR')}</span>
              <span className="muted">{c.dialog}</span>
              <span className="muted tiny">{c.start}</span>
              <span className="muted tiny">{c.created}</span>
            </div>
          ))}
        </div>
      </div>
    </div></div>
  );
}

function Celulares() {
  const stMap = { connected: { l: 'Conectado', c: 'var(--st-done)' }, syncing: { l: 'Sincronizando', c: 'var(--st-wait)' }, offline: { l: 'Desconectado', c: 'var(--st-open)' } };
  return (
    <div className="page route-anim"><div className="page-inner">
      <SectionTitle sub="Aparelhos WhatsApp conectados ao CACTUS CHAT."
        action={<button className="btn btn-primary"><Icon name="plus" size={16} /> Conectar aparelho</button>}>Celulares</SectionTitle>
      <div className="dev-grid">
        {DEVICES.map(d => { const s = stMap[d.status]; return (
          <div className="card card-pad dev-card" key={d.num}>
            <div className="row" style={{ justifyContent: 'space-between', marginBottom: 12 }}>
              <div className="row gap10"><div className="dev-ic"><Icon name="whatsapp" size={22} /></div>
                <div className="col"><span style={{ fontWeight: 800, fontSize: 14 }}>{d.num}</span><span className="tiny muted">{d.label}</span></div></div>
              <span className="badge" style={{ color: s.c, background: `color-mix(in srgb, ${s.c} 13%, transparent)` }}><span className="bdot" />{s.l}</span>
            </div>
            <div className="dev-meta">
              <div><span className="kv-k">Mensagens na fila</span><span className="kv-v">{d.queue}</span></div>
              <div><span className="kv-k">Bateria</span><span className="kv-v">{d.battery ? d.battery + '%' : '—'}</span></div>
            </div>
            <div className="row gap8" style={{ marginTop: 14 }}>
              <button className="btn btn-accent btn-sm" style={{ flex: 1 }}><Icon name="qr" size={15} /> Ler QR-Code</button>
              <button className="btn btn-ghost btn-icon" style={{ width: 34, height: 34 }} title="Reiniciar"><Icon name="refresh" size={16} /></button>
              <button className="btn btn-ghost btn-icon" style={{ width: 34, height: 34, color: 'var(--st-open)' }} title="Desativar"><Icon name="power" size={16} /></button>
            </div>
          </div>
        ); })}
      </div>
    </div></div>
  );
}

function Tags() {
  const [bg, setBg] = React.useState('#E8EDD8'); const [fg, setFg] = React.useState('#5A6E2A');
  return (
    <div className="page route-anim"><div className="page-inner">
      <SectionTitle sub="Organize os contatos com etiquetas coloridas.">Tags</SectionTitle>
      <div className="two-col">
        <div className="card card-pad">
          <h3 style={{ fontSize: 16, marginBottom: 14 }}>Cadastrar Tag</h3>
          <div className="field" style={{ marginBottom: 12 }}><span className="label">Nome</span><input className="input" placeholder="Ex: Revisional" /></div>
          <div className="row gap12" style={{ marginBottom: 14 }}>
            <div className="field" style={{ flex: 1 }}><span className="label">Cor de fundo</span>
              <div className="color-row"><input type="color" value={bg} onChange={e => setBg(e.target.value)} /><span className="mono">{bg}</span></div></div>
            <div className="field" style={{ flex: 1 }}><span className="label">Cor do texto</span>
              <div className="color-row"><input type="color" value={fg} onChange={e => setFg(e.target.value)} /><span className="mono">{fg}</span></div></div>
          </div>
          <div className="field" style={{ marginBottom: 14 }}><span className="label">Pré-visualização</span>
            <div><span className="chip" style={{ background: bg, color: fg }}>Revisional</span></div></div>
          <button className="btn btn-primary btn-block"><Icon name="check" size={16} /> Salvar tag</button>
        </div>
        <div className="card" style={{ overflow: 'hidden' }}>
          <div className="tbl">
            <div className="tbl-head" style={{ gridTemplateColumns: '40px 1fr 1fr 90px' }}><span></span><span>Tag</span><span>Cores</span><span>Ações</span></div>
            {TAGS.map(t => (
              <div className="tbl-row" key={t.id} style={{ gridTemplateColumns: '40px 1fr 1fr 90px' }}>
                <span className="drag-handle"><Icon name="dots" size={16} /></span>
                <span><span className="chip" style={{ background: t.bg, color: t.fg }}>{t.name}</span></span>
                <span className="row gap6"><span className="sw" style={{ background: t.bg }} /><span className="sw" style={{ background: t.fg }} /></span>
                <span className="row gap6"><button className="btn btn-ghost btn-icon" style={{ width: 30, height: 30 }}><Icon name="edit" size={15} /></button><button className="btn btn-ghost btn-icon" style={{ width: 30, height: 30, color: 'var(--st-open)' }}><Icon name="trash" size={15} /></button></span>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div></div>
  );
}

Object.assign(window, { Respostas, Dialogos, Campanhas, Celulares, Tags });


/* ===== relatorios.jsx ===== */
/* ============================================================
   RELATÓRIOS — Acesso + Gráficos
   ============================================================ */
function BarChart({ data, color }) {
  const max = Math.max(...data.map(d => d.v));
  return (
    <div className="bar-chart">
      {data.map(d => (
        <div className="bc-col" key={d.l}>
          <div className="bc-track"><div className="bc-fill" style={{ height: (d.v / max * 100) + '%', background: color }}><span className="bc-val">{d.v}</span></div></div>
          <span className="bc-lbl">{d.l}</span>
        </div>
      ))}
    </div>
  );
}

function Donut({ segments }) {
  let acc = 0; const R = 54, C = 2 * Math.PI * R;
  return (
    <div className="donut-wrap">
      <svg width="140" height="140" viewBox="0 0 140 140">
        <circle cx="70" cy="70" r={R} fill="none" stroke="var(--surface-3)" strokeWidth="18" />
        {segments.map((s, i) => {
          const len = (s.v / 100) * C; const off = acc; acc += len;
          return <circle key={i} cx="70" cy="70" r={R} fill="none" stroke={s.c} strokeWidth="18"
            strokeDasharray={`${len} ${C - len}`} strokeDashoffset={-off} transform="rotate(-90 70 70)" strokeLinecap="butt" />;
        })}
        <text x="70" y="66" textAnchor="middle" fontSize="26" fontWeight="800" fill="var(--text)" fontFamily="var(--font-title)">466</text>
        <text x="70" y="84" textAnchor="middle" fontSize="11" fill="var(--text-2)">contatos</text>
      </svg>
      <div className="donut-legend">
        {segments.map(s => <div className="dl-row" key={s.l}><span className="dl-dot" style={{ background: s.c }} /><span>{s.l}</span><span className="spacer" /><b>{s.v}%</b></div>)}
      </div>
    </div>
  );
}

function Relatorios() {
  const [view, setView] = React.useState('acesso');
  return (
    <div className="page route-anim"><div className="page-inner">
      <SectionTitle sub="Métricas de acesso, atendimento e produtividade."
        action={<Segmented value={view} onChange={setView} options={[{ value: 'acesso', label: 'Relatório de Acesso', icon: 'doc' }, { value: 'graficos', label: 'Relatórios Gráficos', icon: 'report' }]} />}>Relatórios</SectionTitle>

      {view === 'acesso' ? (
        <div className="card card-pad">
          <h3 style={{ fontSize: 16, marginBottom: 16 }}>Relatório de Acesso</h3>
          <div className="rel-filters">
            <div className="field"><span className="label">Usuário</span><select className="select"><option>Todos os usuários</option>{USERS.map(u => <option key={u.id}>{u.name}</option>)}</select></div>
            <div className="field"><span className="label">Data de</span><input className="input" type="date" defaultValue="2026-06-01" /></div>
            <div className="field"><span className="label">Data até</span><input className="input" type="date" defaultValue="2026-06-06" /></div>
          </div>
          <div className="row gap10" style={{ marginTop: 16 }}>
            <button className="btn btn-accent"><Icon name="eye" size={16} /> Ver Relatório</button>
            <button className="btn btn-ghost"><Icon name="download" size={16} /> Exportar Relatório</button>
          </div>
          <div className="card" style={{ marginTop: 18, overflow: 'hidden', boxShadow: 'none' }}>
            <div className="tbl">
              <div className="tbl-head" style={{ gridTemplateColumns: '1.4fr 1fr 1fr 1fr' }}><span>Usuário</span><span>Último acesso</span><span>Sessões</span><span>Tempo online</span></div>
              {USERS.map((u, i) => (
                <div className="tbl-row" key={u.id} style={{ gridTemplateColumns: '1.4fr 1fr 1fr 1fr' }}>
                  <span className="row gap10"><Avatar name={u.name} color={u.color} initials={u.initials} size={32} /><b>{u.name}</b></span>
                  <span className="muted">{['06/06 14:38', '06/06 13:50', '06/06 14:21', '05/06 18:02', '06/06 09:15'][i]}</span>
                  <span>{[42, 38, 51, 27, 63][i]}</span>
                  <span className="muted">{['38h 12m', '31h 40m', '44h 05m', '22h 18m', '51h 30m'][i]}</span>
                </div>
              ))}
            </div>
          </div>
        </div>
      ) : (
        <div>
          <div className="dash-kpis" style={{ marginBottom: 18 }}>
            {[{ k: 'Atendimentos no mês', v: '1.284', d: '+12%', c: 'var(--green-500)' },
              { k: 'Tempo médio de 1ª resposta', v: '2m 14s', d: '-18%', c: 'var(--st-active)' },
              { k: 'Taxa de resolução', v: '87%', d: '+4%', c: 'var(--gold)' },
              { k: 'Contratos fechados', v: '28', d: '+6', c: 'var(--green-700)' }].map(x => (
              <div className="kpi-card" key={x.k}>
                <div className="col"><span className="kpi-val" style={{ color: x.c }}>{x.v}</span><span className="kpi-lbl">{x.k}</span></div>
                <span className="kpi-delta">{x.d}</span>
              </div>
            ))}
          </div>
          <div className="two-col">
            <div className="card card-pad"><h3 style={{ fontSize: 15, marginBottom: 18 }}>Atendimentos por dia da semana</h3>
              <BarChart color="var(--green-500)" data={[{ l: 'Seg', v: 214 }, { l: 'Ter', v: 268 }, { l: 'Qua', v: 245 }, { l: 'Qui', v: 281 }, { l: 'Sex', v: 196 }, { l: 'Sáb', v: 80 }]} /></div>
            <div className="card card-pad"><h3 style={{ fontSize: 15, marginBottom: 18 }}>Distribuição por área jurídica</h3>
              <Donut segments={[{ l: 'Bancário', v: 38, c: '#3A6B5E' }, { l: 'Cível', v: 27, c: '#5A6E2A' }, { l: 'Trabalhista', v: 21, c: '#7A5A6E' }, { l: 'Previdenciário', v: 14, c: '#B8924A' }]} /></div>
          </div>
        </div>
      )}
    </div></div>
  );
}
Object.assign(window, { Relatorios });


/* ===== login_home.jsx ===== */
/* ============================================================
   LOGIN + HOME
   ============================================================ */
function Login({ onLogin }) {
  const [show, setShow] = React.useState(false);
  const [email, setEmail] = React.useState('');
  const [password, setPassword] = React.useState('');
  const [err, setErr] = React.useState(null);
  const [busy, setBusy] = React.useState(false);
  const submit = (e) => {
    e.preventDefault(); if (busy) return;
    setBusy(true); setErr(null);
    fetch('/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) })
      .then(r => r.json().then(d => ({ ok: r.ok, d })))
      .then(({ ok, d }) => { if (ok) { window.location.reload(); } else { setErr(d.error || 'Falha no login.'); setBusy(false); } })
      .catch(() => { setErr('Erro de conexão.'); setBusy(false); });
  };
  return (
    <div className="login-wrap">
      <div className="login-left">
        <div className="ll-deco" />
        <div className="ll-content">
          <CactusLogo size={64} radius={16} bg="rgba(255,255,255,.08)" spine="#9CC178" />
          <div className="ll-brand">CACTUS<span>CHAT</span></div>
          <h1 className="ll-title">SEJA BEM-VINDO<br />AO CACTUS CHAT</h1>
          <p className="ll-sub">Plataforma de atendimento por WhatsApp do<br />Lima Amorim &amp; Advogados Associados.</p>
        </div>
        <div className="ll-foot"><CactusLogo size={28} radius={8} bg="rgba(255,255,255,.1)" spine="#9CC178" /><span>Lima Amorim &amp; Advogados Associados</span></div>
      </div>
      <div className="login-right">
        <form className="login-form" onSubmit={submit}>
          <h2 className="lf-title">Acessar conta</h2>
          <p className="lf-sub">Entre com seu e-mail e senha do escritório.</p>
          <div className="field" style={{ marginBottom: 16 }}><span className="label">E-mail</span>
            <div className="input-search"><Icon name="user" size={16} /><input className="input" type="email" autoFocus value={email} onChange={e => setEmail(e.target.value)} placeholder="voce@limaamorim.com.br" /></div></div>
          <div className="field" style={{ marginBottom: 8 }}><span className="label">Senha</span>
            <div className="input-search"><Icon name="plug" size={16} /><input className="input" type={show ? 'text' : 'password'} value={password} onChange={e => setPassword(e.target.value)} style={{ paddingRight: 40 }} />
              <button type="button" className="pw-toggle" onClick={() => setShow(s => !s)}><Icon name="eye" size={16} /></button></div></div>
          {err && <div className="tiny" style={{ color: 'var(--st-open)', marginBottom: 12 }}>{err}</div>}
          <button className="btn btn-primary btn-block" type="submit" disabled={busy} style={{ padding: '12px', fontSize: 14, marginTop: 8 }}>{busy ? 'Entrando…' : 'Acessar'}</button>
          <div className="lf-footnote">© 2026 CACTUS CHAT · Lima Amorim &amp; Advogados</div>
        </form>
      </div>
    </div>
  );
}

function Home({ go }) {
  const shortcuts = [
    { id: 'atendimento', icon: 'chat', label: 'Atendimento', desc: 'Conversas ativas', n: '7 em aberto' },
    { id: 'funil', icon: 'funnel', label: 'Funil', desc: 'Jornada comercial', n: '466 contatos' },
    { id: 'dashboard', icon: 'grid', label: 'Dashboard', desc: 'Gestão de atendimento', n: '92 não resolvidos' },
    { id: 'campanhas', icon: 'megaphone', label: 'Campanhas', desc: 'Disparos em massa', n: '2 ativas' },
  ];
  return (
    <div className="page route-anim"><div className="page-inner home-inner">
      <div className="home-hero">
        <div className="hh-deco"><CactusLogo size={120} radius={28} bg="var(--green-100)" spine="var(--green-700)" /></div>
        <div className="hh-text">
          <span className="hh-eyebrow">CACTUS CHAT · Lima Amorim &amp; Advogados</span>
          <h1 className="hh-title">Bom dia, Dra. Mariana.</h1>
          <p className="hh-sub">Você tem <b>7 atendimentos em aberto</b> e <b>3 contratos aguardando assinatura</b>. Tenha um ótimo dia de trabalho.</p>
          <div className="row gap10"><button className="btn btn-primary" onClick={() => go('atendimento')}><Icon name="chat" size={16} /> Ir para Atendimento</button>
            <button className="btn btn-ghost" onClick={() => go('dashboard')}><Icon name="grid" size={16} /> Ver Dashboard</button></div>
        </div>
      </div>
      <div className="home-grid">
        {shortcuts.map(s => (
          <button className="home-card" key={s.id} onClick={() => go(s.id)}>
            <div className="hc-ic"><Icon name={s.icon} size={22} /></div>
            <span className="hc-label">{s.label}</span>
            <span className="hc-desc">{s.desc}</span>
            <span className="hc-n">{s.n}</span>
          </button>
        ))}
      </div>
    </div></div>
  );
}
Object.assign(window, { Login, Home });


/* ===== designsystem.jsx ===== */
/* ============================================================
   DESIGN SYSTEM page
   ============================================================ */
function Swatch({ name, val, hex, dark }) {
  return (
    <div className="ds-swatch">
      <div className="ds-chip" style={{ background: val, color: dark ? '#fff' : 'var(--text)' }}>{hex}</div>
      <span className="ds-sw-name">{name}</span>
    </div>
  );
}
function DSBlock({ title, children, full }) {
  return (
    <div className={`ds-block ${full ? 'full' : ''}`}>
      <div className="ds-block-title">{title}</div>
      <div className="ds-block-body">{children}</div>
    </div>
  );
}

function DesignSystem() {
  return (
    <div className="page route-anim"><div className="page-inner">
      <SectionTitle sub="Paleta, tipografia e biblioteca de componentes do CACTUS CHAT.">Design System</SectionTitle>

      <div className="ds-grid">
        <DSBlock title="Marca">
          <div className="row gap16" style={{ flexWrap: 'wrap', alignItems: 'flex-end' }}>
            <div className="col" style={{ alignItems: 'center', gap: 8 }}><CactusLogo size={72} radius={18} /><span className="tiny muted">Claro / quadrado</span></div>
            <div className="col" style={{ alignItems: 'center', gap: 8 }}><CactusLogo size={72} radius={18} bg="var(--green-100)" spine="var(--green-700)" /><span className="tiny muted">Invertido</span></div>
            <div className="col" style={{ alignItems: 'center', gap: 8 }}><div style={{ background: '#16200C', padding: 14, borderRadius: 18 }}><CactusLogo size={48} radius={12} bg="rgba(255,255,255,.08)" spine="#9CC178" /></div><span className="tiny muted">Sobre escuro</span></div>
            <div className="col" style={{ gap: 4, marginLeft: 8 }}><span className="ds-wordmark">CACTUS<b>CHAT</b></span><span className="tiny muted">Wordmark</span></div>
          </div>
        </DSBlock>

        <DSBlock title="Cores da marca">
          <div className="ds-swatches">
            <Swatch name="Primária" val="#2B3616" hex="#2B3616" dark />
            <Swatch name="Realce" val="#5A6E2A" hex="#5A6E2A" dark />
            <Swatch name="Acento cacto" val="#7BA05B" hex="#7BA05B" dark />
            <Swatch name="Realce claro" val="#E8EDD8" hex="#E8EDD8" />
            <Swatch name="Premium" val="#B8924A" hex="#B8924A" dark />
            <Swatch name="Fundo" val="#F5F6F2" hex="#F5F6F2" />
          </div>
        </DSBlock>

        <DSBlock title="Status">
          <div className="ds-swatches">
            <Swatch name="Aberto" val="#C2683A" hex="#C2683A" dark />
            <Swatch name="Em atendimento" val="#3A6B5E" hex="#3A6B5E" dark />
            <Swatch name="Aguardando" val="#D9A84E" hex="#D9A84E" dark />
            <Swatch name="Resolvido" val="#5A6E2A" hex="#5A6E2A" dark />
          </div>
          <div className="row gap8" style={{ marginTop: 14, flexWrap: 'wrap' }}>
            {Object.keys(STATUS).map(k => <StatusBadge key={k} status={k} />)}
          </div>
        </DSBlock>

        <DSBlock title="Tipografia">
          <div className="ds-type"><span className="tiny muted">Playfair Display · Títulos</span>
            <div style={{ fontFamily: 'var(--font-title)', fontWeight: 700, fontSize: 34, lineHeight: 1.1 }}>Lima Amorim</div>
            <div style={{ fontFamily: 'var(--font-title)', fontWeight: 700, fontSize: 22 }}>Atendimento jurídico</div>
          </div>
          <div className="ds-type" style={{ marginTop: 12 }}><span className="tiny muted">Lato · Corpo</span>
            <div style={{ fontSize: 15 }}>A advocacia que resolve, direto ao ponto.</div>
            <div className="muted" style={{ fontSize: 13 }}>Texto secundário · 13px · descrições e metadados.</div>
          </div>
        </DSBlock>

        <DSBlock title="Botões">
          <div className="row gap8" style={{ flexWrap: 'wrap' }}>
            <button className="btn btn-primary">Primário</button>
            <button className="btn btn-accent">Realce</button>
            <button className="btn btn-soft">Suave</button>
            <button className="btn btn-gold">Premium</button>
            <button className="btn btn-ghost">Secundário</button>
          </div>
        </DSBlock>

        <DSBlock title="Inputs">
          <div className="field" style={{ marginBottom: 10 }}><span className="label">Campo de texto</span><input className="input" placeholder="Digite aqui" /></div>
          <div className="input-search"><Icon name="search" size={15} /><input className="input" placeholder="Buscar" /></div>
        </DSBlock>

        <DSBlock title="Tags">
          <div className="row gap6" style={{ flexWrap: 'wrap' }}>{TAGS.slice(0, 6).map(t => <Tag key={t.id} id={t.id} />)}</div>
        </DSBlock>

        <DSBlock title="Bolhas de chat">
          <div style={{ background: 'var(--chat-bg)', borderRadius: 10, padding: 14 }}>
            <div className="bubrow in"><div className="bubble b-in"><span className="bub-text">Boa tarde, gostaria de revisar meu financiamento.</span><span className="bub-meta">14:02</span></div></div>
            <div className="bubrow out"><div className="bubble b-out"><span className="bub-text">Claro! Vou te ajudar com isso.</span><span className="bub-meta">14:05<Icon name="checkcheck" size={14} style={{ color: '#4F93C4' }} /></span></div></div>
          </div>
        </DSBlock>

        <DSBlock title="Card de conversa" full>
          <div style={{ maxWidth: 360, border: '1px solid var(--border)', borderRadius: 12, overflow: 'hidden' }}>
            <ConvCard c={CONV[0]} active onClick={() => {}} />
          </div>
        </DSBlock>

        <DSBlock title="Cards de dashboard">
          <div className="kpi-card" style={{ marginBottom: 10 }}><div className="kpi-ic" style={{ color: 'var(--st-active)', background: 'color-mix(in srgb, var(--st-active) 12%, transparent)' }}><Icon name="reply" size={20} /></div><div className="col"><span className="kpi-val" style={{ color: 'var(--st-active)' }}>25</span><span className="kpi-lbl">Em atendimento</span></div></div>
        </DSBlock>

        <DSBlock title="Gráfico de funil" full>
          <div style={{ maxWidth: 520 }}><FunnelChart /></div>
        </DSBlock>
      </div>
    </div></div>
  );
}
Object.assign(window, { DesignSystem });


/* ===== app.jsx ===== */
/* ============================================================
   APP — router + theme
   ============================================================ */
const { useState, useEffect } = React;

function Placeholder({ route }) {
  const meta = {
    contatos: { icon: 'contacts', t: 'Contatos', s: 'Base de contatos do escritório.' },
    midias: { icon: 'media', t: 'Mídias', s: 'Biblioteca de arquivos enviados e recebidos.' },
    integracoes: { icon: 'plug', t: 'Integrações', s: 'Advbox, ZapSign, Cálculo Bacen e Assistente IA.' },
    config: { icon: 'gear', t: 'Configurações', s: 'Preferências da conta e do escritório.' },
  }[route] || { icon: 'grid', t: route, s: '' };
  return (
    <div className="page route-anim"><div className="page-inner">
      <SectionTitle sub={meta.s}>{meta.t}</SectionTitle>
      <div className="card card-pad"><Empty icon={meta.icon} title={`${meta.t} — em construção`} sub="Esta seção segue o mesmo padrão visual das demais telas do CACTUS CHAT." /></div>
    </div></div>
  );
}

function App() {
  const [theme, setTheme] = useState(() => localStorage.getItem('cc-theme') || 'light');
  const [logged, setLogged] = useState(() => localStorage.getItem('cc-logged') === '1');
  const [route, setRoute] = useState(() => localStorage.getItem('cc-route') || 'home');

  useEffect(() => { document.documentElement.setAttribute('data-theme', theme); localStorage.setItem('cc-theme', theme); }, [theme]);
  useEffect(() => { localStorage.setItem('cc-logged', logged ? '1' : '0'); }, [logged]);
  useEffect(() => { localStorage.setItem('cc-route', route); }, [route]);

  const go = (r) => setRoute(r);
  const toggleTheme = () => setTheme(t => t === 'dark' ? 'light' : 'dark');

  if (!logged) return <Login onLogin={() => { setLogged(true); setRoute('home'); }} />;

  const isAtendimento = route === 'atendimento';
  return (
    <div className="app">
      <Topbar theme={theme} toggleTheme={toggleTheme} onLogout={() => { fetch('/api/logout', { method: 'POST' }).finally(() => { try { localStorage.setItem('cc-logged', '0'); } catch (e) {} window.location.reload(); }); }} go={go} />
      <div className="app-body">
        <Sidebar route={route} go={go} extraTheme={theme} onTheme={toggleTheme} />
        <div className="main-area">
          {route === 'home' && <Home go={go} />}
          {isAtendimento && <Atendimento />}
          {route === 'funil' && <Funil />}
          {route === 'dashboard' && <Dashboard />}
          {route === 'respostas' && <Respostas />}
          {route === 'dialogos' && <Dialogos />}
          {route === 'campanhas' && <Campanhas />}
          {route === 'relatorios' && <Relatorios />}
          {route === 'celulares' && <Celulares />}
          {route === 'tags' && <Tags />}
          {route === 'designsystem' && <DesignSystem />}
          {['contatos', 'midias', 'integracoes', 'config'].includes(route) && <Placeholder route={route} />}
        </div>
      </div>
    </div>
  );
}

/* ===== CACTUS CHAT — live data boot (Chatwoot bridge) ===== */
(function () {
  const rootEl = document.getElementById('root');
  rootEl.innerHTML = '<div style="height:100vh;display:grid;place-items:center;color:#5A6E2A;font-family:Lato,system-ui,sans-serif;font-weight:700">Carregando CACTUS CHAT…</div>';
  const mount = () => ReactDOM.createRoot(rootEl).render(<App />);
  const initials = n => (n || '?').trim().split(/\s+/).filter(Boolean).map(x => x[0]).slice(0, 2).join('').toUpperCase();
  fetch('/api/me').then(r => r.ok ? r.json() : null).then(function (me) {
    if (!me) { try { localStorage.setItem('cc-logged', '0'); } catch (e) {} mount(); return; }
    try { localStorage.setItem('cc-logged', '1'); } catch (e) {}
    CURRENT_USER = { name: me.name, org: 'Lima Amorim & Advogados', color: (window.AV ? AV.green : '#5A6E2A'), initials: initials(me.name) };
    window.__ME = me;
    const r = localStorage.getItem('cc-route');
    if (!r || r === 'home') { try { localStorage.setItem('cc-route', 'atendimento'); } catch (e) {} }
    Promise.all([
      fetch('/api/bootstrap').then(x => x.json()).catch(() => null),
      fetch('/api/conversations').then(x => x.json()).catch(() => null),
    ]).then(function (res) {
      const boot = res[0], convs = res[1];
      if (boot) {
        if (Array.isArray(boot.users) && boot.users.length) USERS = boot.users;
        if (Array.isArray(boot.tags)) TAGS = boot.tags;
        if (Array.isArray(boot.funnelStages) && boot.funnelStages.length) FUNNEL_STAGES = boot.funnelStages;
        DASH = boot.dash || USERS.map(u => ({ user: u, open: 0, active: 0, wait: 0, total: 0 }));
      }
      if (convs && Array.isArray(convs.conversations)) CONV = convs.conversations;
      Object.assign(window, { CONV, USERS, TAGS, CURRENT_USER, FUNNEL_STAGES, DASH });
      mount();
    }).catch(mount);
  }).catch(function () { try { localStorage.setItem('cc-logged', '0'); } catch (e) {} mount(); });
})();

