/* screen_marketing_inicio.jsx
   Dashboard central do módulo Marketing — KPIs, aprovações, insights, chat Digi AI.
   Expõe window.MktInicioScreen. Nomes JSX prefixados MktInicio* (âmbito global Babel).
*/

async function mktInicioApi(url, options = {}) {
  const p = new URLSearchParams(window.location.search || '');
  const qIdx = url.indexOf('?');
  const base = qIdx >= 0 ? url.slice(0, qIdx) : url;
  if (qIdx >= 0) new URLSearchParams(url.slice(qIdx + 1)).forEach((v, k) => p.set(k, v));
  const email = window.currentUser?.email || '';
  if (email && !p.get('email')) p.set('email', email);
  const qs = p.toString();
  const full = qs ? `${base}?${qs}` : base;
  let res;
  try {
    res = await fetch(full, { headers: { 'Content-Type': 'application/json' }, ...options });
  } catch (e) {
    throw new Error(`Erro de rede: ${e.message}`);
  }
  if (!res.ok) {
    let body = {};
    try { body = await res.json(); } catch {}
    throw new Error(body.error || `HTTP ${res.status}`);
  }
  if (res.headers.get('content-type')?.includes('text/event-stream')) return res;
  return res.json();
}

function mktInicioTimeAgo(iso) {
  if (!iso) return '';
  const ms = Date.now() - new Date(iso).getTime();
  const m = Math.max(0, Math.floor(ms / 60000));
  if (m < 60) return `há ${m} min`;
  const h = Math.floor(m / 60);
  if (h < 24) return `há ${h}h`;
  return `há ${Math.floor(h / 24)}d`;
}

function mktInicioSaudacao() {
  const hour = new Date().getHours();
  return hour < 12 ? 'Bom dia' : hour < 19 ? 'Boa tarde' : 'Boa noite';
}

function mktInicioDiaLabel(iso) {
  const raw = String(iso || '').slice(0, 10);
  if (!raw) return '';
  const [y, mo, d] = raw.split('-').map(Number);
  const dt = new Date(y, (mo || 1) - 1, d || 1);
  return ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'][dt.getDay()];
}

function mktInicioIco(name, size, extra) {
  return window.Icon ? <Icon name={name} size={size} style={extra} /> : null;
}

const MKT_INICIO_PRI = {
  critica: { color: 'var(--danger)',  bg: 'color-mix(in oklch, var(--danger) 12%, transparent)' },
  alta:    { color: 'var(--warning)', bg: 'color-mix(in oklch, var(--warning) 12%, transparent)' },
  normal:  { color: 'var(--text-muted)', bg: 'var(--bg-sunken)' },
  baixa:   { color: 'var(--text-dim)', bg: 'var(--bg-sunken)' },
};

const MKT_INICIO_PINSIGHT = {
  p0: { color: 'var(--danger)',  label: 'P0' },
  p1: { color: 'var(--warning)', label: 'P1' },
  p2: { color: 'var(--text-dim)', label: 'P2' },
};

const MKT_INICIO_FASES = [
  { id: 'estrategia',  label: 'Estratégia' },
  { id: 'conceito',    label: 'Conceito' },
  { id: 'orcamento',   label: 'Orçamento' },
  { id: 'segmentacao', label: 'Segmentação' },
  { id: 'planeamento', label: 'Planeamento' },
  { id: 'funil',       label: 'Funil' },
  { id: 'aprovacao',   label: 'Aprovação' },
];

const MKT_INICIO_TIPO = {
  briefing: { label: 'Briefing', icon: 'doc' },
  copy:     { label: 'Copy',     icon: 'copy' },
  prompt:   { label: 'Prompt',   icon: 'sparkle' },
  peca:     { label: 'Peça',     icon: 'image' },
};

function mktInicioNav(setSub, dest, extra = {}) {
  try {
    if (extra.campanhaId) localStorage.setItem('mkt-open-campanha-id', String(extra.campanhaId));
    if (extra.briefingId) localStorage.setItem('mkt-open-briefing-id', String(extra.briefingId));
    if (extra.conteudoId) localStorage.setItem('mkt-open-conteudo-id', String(extra.conteudoId));
    if (extra.filterEstado) localStorage.setItem('mkt-inicio-filter-estado', extra.filterEstado);
    if (extra.filterCol) localStorage.setItem('mkt-inicio-filter-col', extra.filterCol);
    if (extra.conteudoTab) localStorage.setItem('mkt-inicio-conteudo-tab', extra.conteudoTab);
    if (extra.clippingId) localStorage.setItem('mkt-open-clipping-id', String(extra.clippingId));
    if (extra.filterCriticas) localStorage.setItem('mkt-inicio-clipping-criticas', '1');
    if (extra.openHouseId) localStorage.setItem('mkt-open-oh-id', String(extra.openHouseId));
    if (extra.novoBriefing) { localStorage.setItem('mkt-inicio-novo-briefing', '1'); window.__mktInicioNovoBriefing = true; }
    if (extra.novaOh) { localStorage.setItem('mkt-inicio-nova-oh', '1'); window.__mktInicioNovaOh = true; }
    if (extra.novaMencao) { localStorage.setItem('mkt-inicio-nova-mencao', '1'); window.__mktInicioNovaMencao = true; }
  } catch {}
  if (typeof setSub === 'function') setSub(dest);
}

function mktInicioEur(v) {
  if (v == null || !Number.isFinite(Number(v))) return '—';
  const n = Number(v);
  if (Math.abs(n) >= 1e6) return '€' + (n / 1e6).toFixed(1).replace('.', ',') + 'M';
  if (Math.abs(n) >= 1000) return '€' + Math.round(n).toLocaleString('pt-PT');
  return '€' + n.toFixed(0);
}
function mktInicioN(v) {
  if (v == null || !Number.isFinite(Number(v))) return '—';
  return Math.round(Number(v)).toLocaleString('pt-PT');
}
function mktInicioPct(v) {
  if (v == null || !Number.isFinite(Number(v))) return '—';
  return Number(v).toFixed(0).replace('.', ',') + '%';
}

const MKT_INICIO_LIGHT = {
  verde: 'var(--success)',
  amarelo: 'var(--warning)',
  vermelho: 'var(--danger)',
};

const MktInicioSparkline = ({ points, color = 'var(--ai-500)', height = 32 }) => {
  const vals = (points || []).map(p => Number(p.valor != null ? p.valor : p) || 0);
  if (vals.length < 2) {
    return <div style={{ height, fontSize: 10, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)' }}>sem série</div>;
  }
  const max = Math.max(...vals, 1);
  const min = Math.min(...vals, 0);
  const span = max - min || 1;
  const w = 120, h = height;
  const d = vals.map((v, i) => {
    const x = (i / (vals.length - 1)) * w;
    const y = h - ((v - min) / span) * (h - 4) - 2;
    return `${i ? 'L' : 'M'}${x.toFixed(1)},${y.toFixed(1)}`;
  }).join(' ');
  return (
    <svg width="100%" height={h} viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" style={{ display: 'block' }}>
      <path d={d} fill="none" stroke={color} strokeWidth="1.6" />
    </svg>
  );
};

const MktInicioHBars = ({ rows, valueKey = 'spend', labelKey = 'nome', color = 'var(--ai-500)' }) => {
  const list = (rows || []).slice(0, 8);
  const max = Math.max(...list.map(r => Number(r[valueKey]) || 0), 1);
  if (!list.length) return <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>Sem campanhas no ar.</div>;
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      {list.map((r, i) => {
        const v = Number(r[valueKey]) || 0;
        const w = Math.max(4, (v / max) * 100);
        return (
          <div key={r.meta_id || r.id || i}>
            <div style={{ display: 'flex', justifyContent: 'space-between', gap: 8, fontSize: 11, marginBottom: 2 }}>
              <span style={{ fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{r[labelKey]}</span>
              <span style={{ fontFamily: 'var(--font-mono)', color: 'var(--text-muted)', flexShrink: 0 }}>{mktInicioEur(v)}</span>
            </div>
            <div style={{ height: 8, background: 'var(--bg-sunken)', borderRadius: 4, overflow: 'hidden', border: '1px solid var(--border)' }}>
              <div style={{ width: `${w}%`, height: '100%', background: r.leads === 0 && v > 0 ? 'var(--danger)' : color, opacity: 0.85 }} />
            </div>
          </div>
        );
      })}
    </div>
  );
};

const MktInicioGauge = ({ pct, light }) => {
  const p = Number.isFinite(Number(pct)) ? Math.max(0, Number(pct)) : null;
  if (p == null) return <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>sem objectivo</div>;
  const color = (light && MKT_INICIO_LIGHT[light]) || 'var(--ai-500)';
  const r = 42, cx = 56, cy = 52;
  const circ = Math.PI * r;
  const dash = (Math.min(100, p) / 100) * circ;
  return (
    <svg viewBox="0 0 112 70" width="100%" style={{ display: 'block', maxWidth: 180, margin: '0 auto' }}>
      <path d={`M ${cx - r} ${cy} A ${r} ${r} 0 0 1 ${cx + r} ${cy}`} fill="none" stroke="var(--border)" strokeWidth="8" strokeLinecap="round" />
      <path d={`M ${cx - r} ${cy} A ${r} ${r} 0 0 1 ${cx + r} ${cy}`} fill="none" stroke={color} strokeWidth="8" strokeLinecap="round"
        strokeDasharray={`${dash} ${circ}`} />
      <text x={cx} y={cy - 2} textAnchor="middle" fontSize="16" fontFamily="var(--font-display)" fontWeight="600" fill="var(--text)">{Math.round(p)}%</text>
    </svg>
  );
};

const MktInicioHeat14 = ({ dias, selected, onSelect, hoje }) => {
  const list = dias || [];
  const max = Math.max(...list.map(d => (d.n_comm || 0) + (d.n_peca || 0) + (d.n_oh || 0)), 1);
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 4 }}>
      {list.map(d => {
        const n = (d.n_comm || 0) + (d.n_peca || 0) + (d.n_oh || 0);
        const intens = n / max;
        const isSel = selected === d.ymd;
        const isHoje = d.ymd === hoje;
        return (
          <button key={d.ymd} type="button" onClick={() => onSelect(d.ymd)} title={`${d.ymd} · ${n}`} style={{
            height: 28, borderRadius: 4, cursor: 'pointer',
            border: isSel || isHoje ? '2px solid var(--ai-500)' : '1px solid var(--border)',
            background: n ? `color-mix(in oklch, var(--ai-500) ${Math.round(18 + intens * 55)}%, transparent)` : 'var(--bg-sunken)',
            fontSize: 10, fontFamily: 'var(--font-mono)', color: 'var(--text)',
          }}>{String(d.ymd).slice(8)}</button>
        );
      })}
    </div>
  );
};

const MktInicioDayBars = ({ dias }) => {
  const list = dias || [];
  const max = Math.max(...list.map(d => (d.n_comm || 0) + (d.n_peca || 0) + (d.n_oh || 0)), 1);
  return (
    <div style={{ display: 'flex', alignItems: 'flex-end', gap: 3, height: 36, marginTop: 8 }}>
      {list.map(d => {
        const n = (d.n_comm || 0) + (d.n_peca || 0) + (d.n_oh || 0);
        const h = Math.max(n ? 4 : 2, (n / max) * 36);
        return (
          <div key={d.ymd} title={`${d.ymd} · ${n}`} style={{
            flex: 1, height: h, borderRadius: 2,
            background: n ? 'var(--ai-500)' : 'var(--border)', opacity: n ? 0.85 : 1,
          }} />
        );
      })}
    </div>
  );
};

const MktInicioMonthBars = ({ mensal }) => {
  const list = mensal || [];
  if (list.length < 1) return <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>sem série</div>;
  const max = Math.max(...list.flatMap(m => [Number(m.bp) || 0, Number(m.real) || 0]), 1);
  return (
    <div style={{ display: 'flex', alignItems: 'flex-end', gap: 6, height: 88 }}>
      {list.map(m => {
        const bpH = Math.max(2, ((Number(m.bp) || 0) / max) * 80);
        const realH = Math.max(2, ((Number(m.real) || 0) / max) * 80);
        return (
          <div key={m.mes} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4 }}>
            <div style={{ display: 'flex', alignItems: 'flex-end', gap: 2, height: 80, width: '100%', justifyContent: 'center' }}>
              <div style={{ width: '38%', height: bpH, background: 'var(--text-dim)', opacity: 0.35, borderRadius: 2 }} />
              <div style={{ width: '38%', height: realH, background: 'var(--ai-500)', borderRadius: 2 }} />
            </div>
            <div style={{ fontSize: 9, fontFamily: 'var(--font-mono)', color: 'var(--text-dim)' }}>{m.mes}</div>
          </div>
        );
      })}
    </div>
  );
};

const MktInicioFunnelBars = ({ contrib }) => {
  const etapas = [
    { k: 'leads', l: 'Leads', v: contrib?.leads },
    { k: 'mql', l: 'MQL', v: contrib?.mql },
    { k: 'sql', l: 'SQL', v: contrib?.sql },
    { k: 'won', l: 'WON', v: contrib?.won },
  ];
  if (etapas.every(e => !e.v)) return null;
  const max = Math.max(...etapas.map(e => Number(e.v) || 0), 1);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
      {etapas.map(e => (
        <div key={e.k}>
          <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 11, marginBottom: 2 }}>
            <span>{e.l}</span>
            <span style={{ fontFamily: 'var(--font-mono)', color: 'var(--text-muted)' }}>{mktInicioN(e.v)}</span>
          </div>
          <div style={{ height: 8, background: 'var(--bg-sunken)', borderRadius: 4, overflow: 'hidden', border: '1px solid var(--border)' }}>
            <div style={{ width: `${Math.max(4, ((Number(e.v) || 0) / max) * 100)}%`, height: '100%', background: 'var(--ai-500)', opacity: 0.8 }} />
          </div>
        </div>
      ))}
    </div>
  );
};

const MktInicioKpiTile = ({ label, value, spark, sparkColor }) => (
  <div style={{ padding: '10px 12px', borderRadius: 8, background: 'var(--bg-sunken)', border: '1px solid var(--border)', minWidth: 0 }}>
    <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', letterSpacing: '0.06em', color: 'var(--text-dim)', marginBottom: 4 }}>{label}</div>
    <div className="font-display" style={{ fontSize: 20, fontWeight: 600, letterSpacing: '-0.02em', lineHeight: 1.1 }}>{value}</div>
    {spark ? <div style={{ marginTop: 6 }}><MktInicioSparkline points={spark} color={sparkColor} height={28} /></div> : null}
  </div>
);

const MktInicioPriBadge = ({ prioridade }) => {
  const cfg = MKT_INICIO_PRI[prioridade] || MKT_INICIO_PRI.normal;
  return (
    <span style={{
      fontSize: 9, fontFamily: 'var(--font-mono)', letterSpacing: '0.08em', fontWeight: 700,
      textTransform: 'uppercase', padding: '2px 7px', borderRadius: 4, flexShrink: 0,
      color: cfg.color, background: cfg.bg,
      border: `1px solid color-mix(in oklch, ${cfg.color} 28%, transparent)`,
    }}>{prioridade || 'normal'}</span>
  );
};

const MKT_INICIO_ORIGEM = {
  peca_falhou:      { label: 'Publicação', icon: 'alert' },
  clipping_critica: { label: 'Clipping',   icon: 'flag' },
  insight_p0:       { label: 'Insight',    icon: 'sparkle' },
  briefing:         { label: 'Briefing',   icon: 'doc' },
  copy:             { label: 'Copy',       icon: 'copy' },
  prompt:           { label: 'Prompt',     icon: 'sparkle' },
  peca:             { label: 'Peça',       icon: 'image' },
  oh:               { label: 'Open House', icon: 'calendar' },
  plano_atraso:     { label: 'Plano',      icon: 'doc' },
  plano_item:       { label: 'Plano',      icon: 'doc' },
  notificacao:      { label: 'Aviso',      icon: 'bell' },
  comm_plan:        { label: 'Calendário', icon: 'calendar' },
  peca_agendada:    { label: 'Agendada',   icon: 'calendar' },
  peca_publicada:   { label: 'No ar',      icon: 'check' },
  peca_agendar:     { label: 'Agendar',    icon: 'flag' },
  peca_rever:       { label: 'Rever',      icon: 'image' },
};

const MKT_INICIO_PULSE_TONE = {
  critico: { color: 'var(--danger)',  bg: 'color-mix(in oklch, var(--danger) 10%, transparent)' },
  atencao: { color: 'var(--warning)', bg: 'color-mix(in oklch, var(--warning) 10%, transparent)' },
  ok:      { color: 'var(--success)', bg: 'transparent' },
};

function mktInicioDayNum(ymd) {
  const n = String(ymd || '').slice(8, 10);
  return n.replace(/^0/, '') || n;
}

const MktInicioInboxRow = ({ item, onOpen, onDismiss }) => {
  const meta = MKT_INICIO_ORIGEM[item.origem] || MKT_INICIO_ORIGEM[item.tipo] || { label: item.origem || item.tipo, icon: 'flag' };
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 12, padding: '11px 14px',
      borderBottom: '1px solid var(--border)',
    }}>
      <button type="button" onClick={() => onOpen(item)} style={{
        display: 'flex', alignItems: 'center', gap: 12, flex: 1, minWidth: 0,
        textAlign: 'left', background: 'transparent', border: 0, padding: 0, cursor: 'pointer', color: 'inherit',
      }}>
        <div style={{
          width: 28, height: 28, borderRadius: 7, background: 'var(--bg-sunken)',
          display: 'grid', placeItems: 'center', color: 'var(--text-muted)', flexShrink: 0,
        }}>{mktInicioIco(meta.icon, 13)}</div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, minWidth: 0 }}>
            <span style={{
              fontSize: 9, fontFamily: 'var(--font-mono)', letterSpacing: '0.06em', textTransform: 'uppercase',
              color: 'var(--text-dim)', flexShrink: 0,
            }}>{meta.label}</span>
            <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--text)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{item.titulo}</div>
          </div>
          <div style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 2, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
            {(item.marca || '').toUpperCase()}{item.marca && item.sub ? ' · ' : ''}{item.sub || ''}{item.idade ? ` · ${mktInicioTimeAgo(item.idade)}` : ''}
          </div>
        </div>
      </button>
      <MktInicioPriBadge prioridade={item.prioridade} />
      <button className="btn btn-sm" onClick={() => onOpen(item)}>{item.cta || 'Abrir'}</button>
      {item.dismissable && (
        <button className="btn btn-sm btn-ghost" title="Dispensar" onClick={() => onDismiss(item)}>{mktInicioIco('close', 12) || '×'}</button>
      )}
    </div>
  );
};

const MktInicioEventRow = ({ item, onOpen }) => {
  const meta = MKT_INICIO_ORIGEM[item.tipo] || { label: item.tipo, icon: 'calendar' };
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 12, padding: '10px 14px',
      borderBottom: '1px solid var(--border)',
    }}>
      <button type="button" onClick={() => onOpen(item)} style={{
        display: 'flex', alignItems: 'center', gap: 12, flex: 1, minWidth: 0,
        textAlign: 'left', background: 'transparent', border: 0, padding: 0, cursor: 'pointer', color: 'inherit',
      }}>
        <div style={{
          width: 44, flexShrink: 0, fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 600,
          color: item.hora ? 'var(--text)' : 'var(--text-dim)', letterSpacing: '0.02em',
        }}>{item.hora || '—'}</div>
        <div style={{
          width: 28, height: 28, borderRadius: 7, background: 'var(--bg-sunken)',
          display: 'grid', placeItems: 'center', color: 'var(--text-muted)', flexShrink: 0,
        }}>{mktInicioIco(meta.icon, 13)}</div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, minWidth: 0 }}>
            <span style={{
              fontSize: 9, fontFamily: 'var(--font-mono)', letterSpacing: '0.06em', textTransform: 'uppercase',
              color: item.atrasado ? 'var(--warning)' : 'var(--text-dim)', flexShrink: 0,
            }}>{item.atrasado ? 'Atrasado' : meta.label}</span>
            <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--text)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{item.titulo}</div>
          </div>
          <div style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 2, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
            {(item.marca || '').toUpperCase()}{item.marca && item.sub ? ' · ' : ''}{item.sub || ''}
          </div>
        </div>
      </button>
      <button className="btn btn-sm" onClick={() => onOpen(item)}>{item.cta || 'Abrir'}</button>
    </div>
  );
};

const MktInicioWeekStrip = ({ semana, selected, onSelect }) => (
  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, minmax(0, 1fr))', gap: 6 }}>
    {(semana || []).map(d => {
      const active = d.ymd === selected;
      const tone = d.n_atrasado ? 'var(--warning)' : (d.hoje ? 'var(--ai-500)' : 'var(--border)');
      return (
        <button key={d.ymd} type="button" onClick={() => onSelect(d.ymd)} style={{
          padding: '8px 4px 10px', borderRadius: 8, cursor: 'pointer',
          background: active ? 'color-mix(in oklch, var(--ai-500) 12%, var(--bg-elev))' : 'var(--bg-elev)',
          border: `1px solid ${active ? 'var(--ai-500)' : tone}`,
          color: 'inherit', textAlign: 'center',
        }}>
          <div style={{ fontSize: 9, fontFamily: 'var(--font-mono)', letterSpacing: '0.08em', textTransform: 'uppercase', color: d.hoje ? 'var(--ai-500)' : 'var(--text-dim)' }}>
            {d.label}{d.hoje ? ' · hoje' : ''}
          </div>
          <div className="font-display" style={{ fontSize: 18, fontWeight: 600, marginTop: 2, color: 'var(--text)' }}>{mktInicioDayNum(d.ymd)}</div>
          <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', color: d.n_atrasado ? 'var(--warning)' : 'var(--text-muted)', marginTop: 2 }}>
            {d.n ? `${d.n}` : '—'}
          </div>
        </button>
      );
    })}
  </div>
);

const MktInicioPulseMini = ({ pulse, onOpen }) => {
  const tone = MKT_INICIO_PULSE_TONE[pulse.status] || MKT_INICIO_PULSE_TONE.ok;
  return (
    <button type="button" onClick={() => onOpen(pulse)} style={{
      display: 'flex', alignItems: 'center', gap: 10, width: '100%', textAlign: 'left', cursor: 'pointer',
      background: tone.bg, border: `1px solid color-mix(in oklch, ${tone.color} 28%, var(--border))`,
      borderRadius: 8, padding: '10px 12px', color: 'inherit', minWidth: 0,
    }}>
      <span style={{ width: 8, height: 8, borderRadius: '50%', background: tone.color, flexShrink: 0 }} />
      <div style={{ minWidth: 0, flex: 1 }}>
        <div style={{ fontSize: 9, fontFamily: 'var(--font-mono)', letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--text-dim)' }}>{pulse.label}</div>
        <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--text)', marginTop: 2, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{pulse.headline}</div>
      </div>
      <div className="font-display" style={{ fontSize: 18, fontWeight: 600, color: 'var(--text)', flexShrink: 0 }}>{pulse.value ?? '—'}</div>
    </button>
  );
};

function mktInicioDigiQs(userEmail) {
  const p = new URLSearchParams(window.location.search || '');
  const email = userEmail || window.currentUser?.email || '';
  if (email && !p.get('email')) p.set('email', email);
  const s = p.toString();
  return s ? `?${s}` : '';
}

function MktInicioDigiChanIcon({ ch, size = 12 }) {
  const s = size;
  if (ch === 'wa') return (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="var(--success)">
      <path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347z"/><path d="M12 0C5.373 0 0 5.373 0 12c0 2.122.555 4.112 1.524 5.84L0 24l6.324-1.499A11.94 11.94 0 0 0 12 24c6.627 0 12-5.373 12-12S18.627 0 12 0zm0 21.818a9.81 9.81 0 0 1-5.002-1.369l-.36-.213-3.714.88.923-3.583-.234-.375A9.818 9.818 0 1 1 12 21.818z"/>
    </svg>
  );
  if (ch === 'email') return (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="var(--ai-500)" strokeWidth="2">
      <rect x="2" y="4" width="20" height="16" rx="2"/><path d="m2 7 10 7 10-7"/>
    </svg>
  );
  return (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="var(--ai-500)" strokeWidth="2">
      <rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/>
      <rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/>
    </svg>
  );
}

const MKT_INICIO_DIGI_PRI_C = { p0: 'var(--danger)', p1: 'var(--warning)', p2: 'var(--ai-500)' };
const MKT_INICIO_DIGI_PRI_L = { p0: 'Crítico', p1: 'Alto', p2: 'Info' };

const MktInicioDigiInsightCard = ({ id, priority = 'p1', category = 'nova_campanha', title, summary, onDismiss, onAccept }) => {
  const pc = MKT_INICIO_DIGI_PRI_C[priority] || MKT_INICIO_DIGI_PRI_C.p2;
  const catL = { nova_campanha: 'Nova campanha', melhoria_live: 'Melhoria live', alerta_crm: 'Alerta CRM', reactivacao: 'Reactivação', campanha_sugerida: 'Campanha', hot_sem_t0: 'Leads HOT', externos_pendentes: 'Matching', audiencia_inactiva: 'Audiência' };
  return (
    <div className="mkt-inicio-digi-msg" style={{ border: `1px solid color-mix(in oklch, ${pc} 30%, transparent)`, borderRadius: 8, padding: '10px 12px', background: `color-mix(in oklch, ${pc} 6%, transparent)`, marginTop: 6 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 5 }}>
        <span style={{ fontSize: 9, fontWeight: 700, fontFamily: 'var(--font-mono)', padding: '2px 6px', borderRadius: 4, background: `color-mix(in oklch, ${pc} 15%, transparent)`, color: pc, textTransform: 'uppercase', letterSpacing: '.06em' }}>{MKT_INICIO_DIGI_PRI_L[priority] || priority}</span>
        <span style={{ fontSize: 10, color: 'var(--text-muted)', fontFamily: 'var(--font-mono)' }}>{catL[category] || category}</span>
      </div>
      <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--text)', marginBottom: 4 }}>{title}</div>
      <div style={{ fontSize: 11, color: 'var(--text-muted)', lineHeight: 1.4, marginBottom: 8 }}>{summary}</div>
      <div style={{ display: 'flex', gap: 5 }}>
        {(category === 'reactivacao' || category === 'campanha_sugerida' || category === 'melhoria_live' || category === 'nova_campanha') && (
          <button className="btn btn-xs btn-ai" onClick={onAccept}>Criar briefing</button>
        )}
        {category === 'hot_sem_t0' && <button className="btn btn-xs btn-ai" onClick={onAccept}>Ver leads HOT</button>}
        {category === 'externos_pendentes' && <button className="btn btn-xs btn-ai" onClick={onAccept}>Fazer matching</button>}
        {category === 'audiencia_inactiva' && <button className="btn btn-xs" onClick={onAccept}>Refrescar audiências</button>}
        {!['reactivacao', 'campanha_sugerida', 'melhoria_live', 'nova_campanha', 'hot_sem_t0', 'externos_pendentes', 'audiencia_inactiva'].includes(category) && (
          <button className="btn btn-xs btn-ai" onClick={onAccept}>Aceitar</button>
        )}
        <button className="btn btn-xs" onClick={onDismiss}>Dispensar</button>
      </div>
    </div>
  );
};

const MktInicioDigiWaSendCard = ({ action, msgId, onSent, userEmail }) => {
  const initial = action.sent ? 'sent' : (action.cancelled ? 'cancelled' : 'pending');
  const [state, setState] = React.useState(initial);
  const names = { fabio: 'Fábio Costa', paulino: 'João Paulino', rui: 'Rui Leitão', armando: 'Armando Mota', bruno: 'Bruno Rosa' };
  const send = async () => {
    setState('sending');
    try {
      const r = await fetch(`/api/marketing/digi/wa/send${mktInicioDigiQs(userEmail)}`, {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ to: action.to, message: action.message }),
      });
      if (!r.ok) throw new Error('Erro');
      setState('sent');
      if (onSent) onSent(msgId);
    } catch (_) { setState('error'); }
  };
  return (
    <div style={{ border: '1px solid color-mix(in oklch, var(--success) 35%, transparent)', borderRadius: 8, padding: '10px 12px', marginTop: 6, background: 'color-mix(in oklch, var(--success) 6%, transparent)' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 7, marginBottom: 6 }}>
        <MktInicioDigiChanIcon ch="wa" size={14} />
        <span style={{ fontSize: 11, fontWeight: 700, color: 'var(--success)', fontFamily: 'var(--font-mono)', textTransform: 'uppercase', letterSpacing: '.06em' }}>Enviar WA</span>
        <span style={{ fontSize: 10, color: 'var(--text-muted)', fontFamily: 'var(--font-mono)', marginLeft: 4 }}>para {names[action.to] || action.to}</span>
      </div>
      <div style={{ fontSize: 11, color: 'var(--text)', lineHeight: 1.5, marginBottom: 8, padding: '6px 8px', background: 'var(--bg-elev)', borderRadius: 6, fontStyle: 'italic' }}>
        "{action.message}"
      </div>
      {state === 'pending' && (
        <div style={{ display: 'flex', gap: 6 }}>
          <button className="btn btn-xs btn-ai" onClick={send}>Confirmar e enviar</button>
          <button className="btn btn-xs" onClick={() => setState('cancelled')}>Cancelar</button>
        </div>
      )}
      {state === 'sending' && <div style={{ fontSize: 11, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)' }}>A enviar...</div>}
      {state === 'sent' && <div style={{ fontSize: 11, color: 'var(--success)', fontFamily: 'var(--font-mono)' }}>Enviado.</div>}
      {state === 'error' && <div style={{ fontSize: 11, color: 'var(--danger)', fontFamily: 'var(--font-mono)' }}>Erro ao enviar. Verifica o backend.</div>}
      {state === 'cancelled' && <div style={{ fontSize: 11, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)' }}>Cancelado.</div>}
    </div>
  );
};

const MktInicioDigiMsgBubble = ({ msg, showHeader = true, onWaSent, userEmail }) => {
  const isUser = msg.role === 'user';
  return (
    <div className="mkt-inicio-digi-msg" style={{ display: 'flex', flexDirection: 'column', alignItems: isUser ? 'flex-end' : 'flex-start', marginBottom: 6 }}>
      {!isUser && showHeader && (
        <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 3 }}>
          <div style={{ width: 18, height: 18, borderRadius: '50%', background: 'var(--ai-500)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
            <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="var(--text-on-ai, #fff)" strokeWidth="1.8">
              <path d="M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96-.46 2.5 2.5 0 0 1-2.96-3.08 3 3 0 0 1-.34-5.58 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 4.44-1.14Z"/>
              <path d="M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96-.46 2.5 2.5 0 0 0 2.96-3.08 3 3 0 0 0 .34-5.58 2.5 2.5 0 0 0-1.32-4.24 2.5 2.5 0 0 0-4.44-1.14Z"/>
            </svg>
          </div>
          <span style={{ fontSize: 10, fontWeight: 700, color: 'var(--ai-500)', fontFamily: 'var(--font-mono)', textTransform: 'uppercase', letterSpacing: '.06em' }}>Digi AI</span>
        </div>
      )}
      {!!(msg.text || '') && (
        <div style={{
          maxWidth: '90%', padding: isUser ? '7px 12px' : '8px 12px',
          background: isUser ? 'var(--ai-500)' : 'var(--bg-elev)',
          color: isUser ? 'var(--text-on-ai, #fff)' : 'var(--text)',
          borderRadius: isUser ? '12px 12px 4px 12px' : '4px 12px 12px 12px',
          fontSize: 12, lineHeight: 1.6,
          border: isUser ? 'none' : '1px solid var(--border)',
        }}>
          {(msg.text || '').split('\n\n').map((para, pi) => (
            <p key={pi} style={{ margin: pi === 0 ? 0 : '7px 0 0' }}>
              {para.split('\n').map((line, li) => li === 0 ? line : [React.createElement('br', { key: li }), line])}
            </p>
          ))}
        </div>
      )}
      {msg.ts && (
        <div style={{ fontSize: 9, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)', marginTop: 3, alignSelf: isUser ? 'flex-end' : 'flex-start' }}>
          {new Date(msg.ts).toLocaleDateString('pt-PT', { day: '2-digit', month: '2-digit' })} {new Date(msg.ts).toLocaleTimeString('pt-PT', { hour: '2-digit', minute: '2-digit' })}
        </div>
      )}
      {!isUser && msg.waAction && (
        <MktInicioDigiWaSendCard action={msg.waAction} msgId={msg.id} onSent={onWaSent} userEmail={userEmail} />
      )}
    </div>
  );
};

const MktInicioDigiTimelineDay = ({ day, events }) => (
  <div style={{ marginBottom: 18 }}>
    <div style={{ fontSize: 10, fontWeight: 700, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)', textTransform: 'uppercase', letterSpacing: '.08em', marginBottom: 8, paddingBottom: 4, borderBottom: '1px solid var(--border)' }}>{day}</div>
    {events.map((ev, i) => (
      <div key={i} style={{ display: 'flex', gap: 10, alignItems: 'flex-start', marginBottom: 8 }}>
        <div style={{ width: 26, height: 26, borderRadius: '50%', background: 'var(--bg-elev)', border: '1px solid var(--border)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
          <MktInicioDigiChanIcon ch={ev.channel} size={13} />
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
            <span style={{ fontSize: 11, color: 'var(--text)', fontWeight: 500, flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{ev.summary}</span>
            <span style={{ fontSize: 10, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)', flexShrink: 0 }}>{ev.time}</span>
          </div>
          <div style={{ fontSize: 10, color: 'var(--text-muted)', fontFamily: 'var(--font-mono)', marginTop: 2 }}>{ev.typeLabel}</div>
        </div>
      </div>
    ))}
  </div>
);

const MktInicioDigiChat = ({ userName, userEmail, dashboardState, seedInsights, onInsightDismissed, onInsightAccepted }) => {
  const [open, setOpen] = React.useState(false);
  const [expanded, setExpanded] = React.useState(false);
  const [mode, setMode] = React.useState('chat');
  const [msgs, setMsgs] = React.useState([]);
  const [inp, setInp] = React.useState('');
  const [loading, setLoad] = React.useState(false);
  const _sessKey = `digi_inicio_sess_${(userEmail || userName || 'anon').replace(/\s+/g, '_')}`;
  const [sessId, setSessId] = React.useState(() => {
    try { return localStorage.getItem(_sessKey) || null; } catch { return null; }
  });
  const panelRef = React.useRef(null);
  const fabRef = React.useRef(null);
  const timeoutsRef = React.useRef([]);
  const [insights, setInsights] = React.useState(() => seedInsights || []);
  const [timelineEvs, setTimeline] = React.useState(null);
  const bodyRef = React.useRef(null);
  const qs = mktInicioDigiQs(userEmail);

  React.useEffect(() => {
    if (open && mode === 'chat' && bodyRef.current) {
      bodyRef.current.scrollTop = bodyRef.current.scrollHeight;
    }
  }, [msgs, open, mode]);

  React.useEffect(() => {
    if (!open) return;
    let cancelled = false;
    const saudacao = mktInicioSaudacao();
    const firstName = (userName || '').split(' ')[0] || '';
    const nameStr = firstName ? `, ${firstName}` : '';

    fetch(`/api/marketing/digi/events${qs}`)
      .then(r => r.ok ? r.json() : { events: [] })
      .then(d => { if (!cancelled) setTimeline(d.events || []); })
      .catch(() => { if (!cancelled) setTimeline([]); });

    const storedSess = (() => { try { return localStorage.getItem(_sessKey); } catch { return null; } })();
    const sessionPromise = storedSess
      ? fetch(`/api/marketing/digi/sessions/${storedSess}${qs}`).then(r => r.ok ? r.json() : null).catch(() => null)
      : Promise.resolve(null);
    const insightsPromise = fetch(`/api/marketing/digi/insights${qs}`)
      .then(r => r.ok ? r.json() : { insights: [] })
      .catch(() => ({ insights: [] }));

    Promise.all([sessionPromise, insightsPromise]).then(([sessionData, insightsData]) => {
      if (cancelled) return;
      const ins = insightsData.insights || [];
      setInsights(ins);
      const restored = sessionData?.messages?.length
        ? sessionData.messages.filter(m => m.role !== 'system').map((m, i) => ({
            id: `hist_${i}`, role: m.role === 'assistant' ? 'digi' : 'user', text: m.content, ts: m.ts,
          }))
        : [];
      setMsgs(prev => {
        if (prev.length > 0) return prev;
        if (restored.length > 0) return restored;
        const p0 = ins.filter(i => i.priority === 'p0').length;
        const n = dashboardState?.pending_approvals || 0;
        let text;
        if (p0 > 0) text = `${saudacao}${nameStr}. Tenho ${p0} alerta${p0 > 1 ? 's' : ''} crítico${p0 > 1 ? 's' : ''} que precisam de atenção imediata.`;
        else if (ins.length) text = `${saudacao}${nameStr}. Tenho ${ins.length} insight${ins.length > 1 ? 's' : ''} com oportunidades — vê abaixo.`;
        else if (n > 0) text = `${saudacao}${nameStr}. Tens ${n} aprovação${n !== 1 ? 'ões' : ''} à espera. Por onde queres começar?`;
        else text = `${saudacao}${nameStr}. Dashboard sincronizado. Em que posso ajudar?`;
        return [{ id: 'greeting', role: 'digi', text, ts: new Date().toISOString() }];
      });
    });
    return () => { cancelled = true; };
  }, [open]);

  React.useEffect(() => {
    if (!open) return;
    const onKey = (e) => {
      if (e.key === 'Escape') {
        if (expanded) setExpanded(false);
        else setOpen(false);
      }
    };
    const onClick = (e) => {
      if (expanded) return;
      if (panelRef.current && !panelRef.current.contains(e.target) &&
          fabRef.current && !fabRef.current.contains(e.target)) {
        setOpen(false);
      }
    };
    document.addEventListener('keydown', onKey);
    document.addEventListener('mousedown', onClick);
    return () => {
      document.removeEventListener('keydown', onKey);
      document.removeEventListener('mousedown', onClick);
    };
  }, [open, expanded]);

  React.useEffect(() => {
    if (!open) {
      timeoutsRef.current.forEach(clearTimeout);
      timeoutsRef.current = [];
    }
  }, [open]);

  const parseWaAction = (str) => {
    const start = str.indexOf('[WA_SEND:');
    if (start < 0) return { action: null, cleanStart: -1, cleanEnd: -1 };
    let depth = 0, i = start + 9;
    const jsonStart = i;
    for (; i < str.length; i++) {
      if (str[i] === '{') depth++;
      else if (str[i] === '}') { depth--; if (depth === 0) { i++; break; } }
    }
    if (str[i] !== ']') return { action: null, cleanStart: -1, cleanEnd: -1 };
    try {
      const action = JSON.parse(str.slice(jsonStart, i));
      return { action, cleanStart: start, cleanEnd: i + 1 };
    } catch (_) { return { action: null, cleanStart: -1, cleanEnd: -1 }; }
  };

  const handleSend = async (text) => {
    const t = (text || inp).trim();
    if (!t || loading) return;
    setMsgs(m => [...m, { id: Date.now(), role: 'user', text: t, ts: new Date().toISOString() }]);
    setInp('');
    setLoad(true);
    try {
      const resp = await fetch(`/api/marketing/digi/crm/chat${qs}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          message: t,
          session_id: sessId,
          context: {
            tab: 'marketing-inicio',
            user_email: userEmail || undefined,
            dashboard_state: dashboardState || {},
          },
        }),
      });
      if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
      const reader = resp.body.getReader();
      const decoder = new TextDecoder();
      let buf = '', accumulated = '';
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        buf += decoder.decode(value, { stream: true });
        const lines = buf.split('\n');
        buf = lines.pop() || '';
        for (const line of lines) {
          if (!line.startsWith('data: ')) continue;
          try {
            const evt = JSON.parse(line.slice(6));
            if (evt.type === 'delta') accumulated += evt.text;
            else if (evt.type === 'done') {
              setSessId(evt.session_id);
              try { localStorage.setItem(_sessKey, evt.session_id); } catch {}
              const { action: waAction, cleanStart, cleanEnd } = parseWaAction(accumulated);
              const cleanText = cleanStart >= 0
                ? (accumulated.slice(0, cleanStart) + accumulated.slice(cleanEnd)).trim()
                : accumulated;
              const paras = (cleanText || accumulated).split('\n\n').map(p => p.trim()).filter(Boolean);
              if (paras.length === 0 && !waAction) { setLoad(false); return; }
              const base = Date.now();
              const tsNow = new Date().toISOString();
              if (paras[0]) setMsgs(m => [...m, { id: base, role: 'digi', text: paras[0], ts: tsNow }]);
              for (let i = 1; i < paras.length; i++) {
                const idx = i;
                const tid = setTimeout(() => {
                  setMsgs(m => [...m, { id: base + idx, role: 'digi', text: paras[idx], ts: new Date().toISOString() }]);
                  if (idx === paras.length - 1 && !waAction) setLoad(false);
                }, idx * 420);
                timeoutsRef.current.push(tid);
              }
              const lastDelay = paras.length > 1 ? (paras.length - 1) * 420 : 0;
              if (waAction) {
                const tid = setTimeout(() => {
                  setMsgs(m => [...m, {
                    id: base + 9999, role: 'digi', text: '',
                    waAction: { to: waAction.to, message: waAction.message, sent: false },
                    ts: new Date().toISOString(),
                  }]);
                  setLoad(false);
                }, lastDelay + 100);
                timeoutsRef.current.push(tid);
              } else if (paras.length <= 1) {
                setLoad(false);
              }
            } else if (evt.type === 'error') {
              setMsgs(m => [...m, { id: Date.now() + 1, role: 'digi', text: `Erro: ${evt.message}`, ts: new Date().toISOString() }]);
              setLoad(false);
              await reader.cancel().catch(() => {});
              return;
            }
          } catch (_) {}
        }
      }
    } catch (e) {
      setMsgs(m => [...m, { id: Date.now() + 1, role: 'digi', text: 'Sem ligação ao servidor. Verifica que o backend está activo.' }]);
      setLoad(false);
    }
  };

  const handleKey = (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend(); } };

  const mBtn = (active) => ({
    padding: '3px 11px', borderRadius: 6, border: 'none', cursor: 'pointer',
    fontSize: 11, fontFamily: 'var(--font-mono)', fontWeight: 600, letterSpacing: '.04em',
    background: active ? 'var(--ai-500)' : 'transparent',
    color: active ? 'var(--text-on-ai, #fff)' : 'var(--text-muted)', transition: 'all .15s',
  });

  const iconBtn = (title, onClick, children) => (
    <button title={title} onClick={onClick} style={{
      width: 28, height: 28, borderRadius: 6, border: '1px solid var(--border)',
      background: 'transparent', color: 'var(--text-dim)', cursor: 'pointer',
      display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, transition: 'all .15s',
    }}
      onMouseEnter={e => { e.currentTarget.style.borderColor = 'var(--ai-500)'; e.currentTarget.style.color = 'var(--ai-500)'; }}
      onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--border)'; e.currentTarget.style.color = 'var(--text-dim)'; }}>
      {children}
    </button>
  );

  const quickActs = ['O que rever hoje?', 'Insights P0', 'Campanhas em curso', 'Ajuda'];

  const DigiHeader = ({ isExpanded }) => (
    <div style={{ padding: isExpanded ? '14px 20px 12px' : '12px 16px 10px', borderBottom: '1px solid var(--border)', background: 'var(--bg-elev)', flexShrink: 0 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
        <div style={{ width: 32, height: 32, borderRadius: 10, background: 'var(--ai-500)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, boxShadow: '0 2px 8px color-mix(in oklch, var(--ai-500) 35%, transparent)' }}>
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--text-on-ai, #fff)" strokeWidth="1.8">
            <path d="M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96-.46 2.5 2.5 0 0 1-2.96-3.08 3 3 0 0 1-.34-5.58 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 4.44-1.14Z"/>
            <path d="M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96-.46 2.5 2.5 0 0 0 2.96-3.08 3 3 0 0 0 .34-5.58 2.5 2.5 0 0 0-1.32-4.24 2.5 2.5 0 0 0-4.44-1.14Z"/>
          </svg>
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: isExpanded ? 14 : 13, fontWeight: 700, color: 'var(--text)', letterSpacing: '.01em', display: 'flex', alignItems: 'center', gap: 6 }}>
            Digi AI
            <span style={{ fontSize: 9, fontWeight: 700, fontFamily: 'var(--font-mono)', padding: '2px 7px', borderRadius: 4, background: 'color-mix(in oklch, var(--ai-500) 14%, transparent)', color: 'var(--ai-500)', letterSpacing: '.08em', textTransform: 'uppercase' }}>Início</span>
          </div>
          <div style={{ fontSize: 10, color: 'var(--text-muted)', fontFamily: 'var(--font-mono)', marginTop: 1 }}>Dashboard · contexto do dia</div>
        </div>
        <div style={{ display: 'flex', gap: 2, background: 'var(--bg-sunken)', borderRadius: 8, padding: 3, flexShrink: 0 }}>
          <button style={mBtn(mode === 'chat')} onClick={() => setMode('chat')}>Chat</button>
          <button style={mBtn(mode === 'timeline')} onClick={() => setMode('timeline')}>Timeline</button>
        </div>
        <div style={{ display: 'flex', gap: 4, marginLeft: 2 }}>
          {iconBtn(isExpanded ? 'Reduzir' : 'Expandir', () => setExpanded(e => !e),
            isExpanded
              ? <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polyline points="4 14 10 14 10 20"/><polyline points="20 10 14 10 14 4"/><line x1="10" y1="14" x2="3" y2="21"/><line x1="21" y1="3" x2="14" y2="10"/></svg>
              : <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>
          )}
          {isExpanded && iconBtn('Fechar', () => { setOpen(false); setExpanded(false); },
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M18 6 6 18M6 6l12 12"/></svg>
          )}
        </div>
      </div>
    </div>
  );

  const DigiChat = ({ isExpanded }) => (
    <>
      <div ref={bodyRef} className="scrollbar" style={{ flex: 1, overflowY: 'auto', padding: isExpanded ? '18px 20px 8px' : '14px 14px 6px', minHeight: 0 }}>
        {insights.length > 0 && (
          <div style={{ marginBottom: 10 }}>
            <div style={{ fontSize: 10, fontWeight: 700, fontFamily: 'var(--font-mono)', color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: 8 }}>
              {insights.length} insight{insights.length > 1 ? 's' : ''} activo{insights.length > 1 ? 's' : ''}
            </div>
            {insights.map(ins => (
              <MktInicioDigiInsightCard
                key={ins.id}
                id={ins.id}
                priority={ins.priority}
                category={ins.category}
                title={ins.title}
                summary={ins.summary}
                onDismiss={async () => {
                  const prev = insights;
                  setInsights(p => p.filter(i => i.id !== ins.id));
                  const r = await fetch(`/api/marketing/digi/insights/${ins.id}/dismiss${qs}`, { method: 'POST' }).catch(() => null);
                  if (!r || !r.ok) setInsights(prev);
                  else if (onInsightDismissed) onInsightDismissed(ins.id);
                }}
                onAccept={async () => {
                  const prev = insights;
                  setInsights(p => p.filter(i => i.id !== ins.id));
                  const r = await fetch(`/api/marketing/digi/insights/${ins.id}/accept${qs}`, { method: 'POST' }).catch(() => null);
                  if (!r || !r.ok) setInsights(prev);
                  else if (onInsightAccepted) onInsightAccepted(ins);
                }}
              />
            ))}
          </div>
        )}
        {msgs.map((m, i) => (
          <MktInicioDigiMsgBubble key={m.id} msg={m}
            showHeader={m.role !== 'user' && (i === 0 || msgs[i - 1].role === 'user')}
            userEmail={userEmail}
            onWaSent={(id) => setMsgs(prev => prev.map(x => x.id === id ? { ...x, waAction: { ...x.waAction, sent: true } } : x))}
          />
        ))}
        {loading && (
          <div style={{ display: 'flex', alignItems: 'center', gap: 7, marginBottom: 12 }}>
            <div style={{ width: 20, height: 20, borderRadius: '50%', background: 'var(--ai-500)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
              <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="var(--text-on-ai, #fff)" strokeWidth="1.8">
                <path d="M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96-.46 2.5 2.5 0 0 1-2.96-3.08 3 3 0 0 1-.34-5.58 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 4.44-1.14Z"/>
                <path d="M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96-.46 2.5 2.5 0 0 0 2.96-3.08 3 3 0 0 0 .34-5.58 2.5 2.5 0 0 0-1.32-4.24 2.5 2.5 0 0 0-4.44-1.14Z"/>
              </svg>
            </div>
            <div style={{ display: 'flex', gap: 4 }}>
              {[0, 1, 2].map(i => (
                <div key={i} style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--ai-500)', opacity: 0.5, animation: `mkt-inicio-digi-dot ${0.7 + i * 0.18}s ease-in-out infinite alternate` }} />
              ))}
            </div>
          </div>
        )}
      </div>
      <div style={{ padding: isExpanded ? '6px 20px 0' : '6px 14px 0', display: 'flex', gap: 5, flexWrap: 'wrap', flexShrink: 0 }}>
        {quickActs.map(a => (
          <button key={a} onClick={() => handleSend(a)} style={{ fontSize: 11, padding: '4px 10px', borderRadius: 999, border: '1px solid var(--border)', background: 'var(--bg-elev)', color: 'var(--text-muted)', cursor: 'pointer', transition: 'all .15s' }}
            onMouseEnter={e => { e.currentTarget.style.borderColor = 'var(--ai-500)'; e.currentTarget.style.color = 'var(--ai-500)'; }}
            onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--border)'; e.currentTarget.style.color = 'var(--text-muted)'; }}>
            {a}
          </button>
        ))}
      </div>
      <div style={{ padding: isExpanded ? '8px 20px 16px' : '8px 14px 14px', display: 'flex', gap: 8, alignItems: 'flex-end', flexShrink: 0 }}>
        <textarea value={inp} onChange={e => setInp(e.target.value)} onKeyDown={handleKey}
          placeholder="Pergunta ou instrução... (Enter envia)" rows={2}
          style={{ flex: 1, resize: 'none', padding: '8px 12px', borderRadius: 10, border: '1px solid var(--border)', background: 'var(--bg)', color: 'var(--text)', fontSize: 12, fontFamily: 'var(--font-body)', lineHeight: 1.5, outline: 'none', transition: 'border-color .15s' }}
          onFocus={e => e.target.style.borderColor = 'var(--ai-500)'}
          onBlur={e => e.target.style.borderColor = 'var(--border)'}
        />
        <button onClick={() => handleSend()} disabled={!inp.trim() || loading} style={{
          width: 38, height: 38, borderRadius: 10, border: 'none', cursor: inp.trim() && !loading ? 'pointer' : 'default',
          background: inp.trim() && !loading ? 'var(--ai-500)' : 'var(--bg-sunken)',
          color: inp.trim() && !loading ? 'var(--text-on-ai, #fff)' : 'var(--text-dim)',
          display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, transition: 'all .15s',
        }}>
          <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="m22 2-7 20-4-9-9-4 20-7z"/></svg>
        </button>
      </div>
    </>
  );

  const DigiTimeline = () => {
    let grouped = null;
    if (timelineEvs && timelineEvs.length > 0) {
      const today = new Date(); today.setHours(0, 0, 0, 0);
      const yest = new Date(today); yest.setDate(today.getDate() - 1);
      const days = {};
      for (const ev of timelineEvs) {
        const d = new Date(ev.created_at); d.setHours(0, 0, 0, 0);
        let label;
        if (d.getTime() === today.getTime()) label = 'Hoje';
        else if (d.getTime() === yest.getTime()) label = 'Ontem';
        else label = new Date(ev.created_at).toLocaleDateString('pt-PT', { weekday: 'long', day: 'numeric', month: 'short' });
        if (!days[label]) days[label] = [];
        days[label].push({
          channel: ev.channel,
          time: new Date(ev.created_at).toLocaleTimeString('pt-PT', { hour: '2-digit', minute: '2-digit' }),
          summary: ev.summary,
          typeLabel: ev.event_type,
        });
      }
      grouped = days;
    }
    return (
      <div ref={bodyRef} className="scrollbar" style={{ flex: 1, overflowY: 'auto', padding: expanded ? '18px 20px' : '14px', minHeight: 0 }}>
        <div style={{ fontSize: 10, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)', marginBottom: 14, textTransform: 'uppercase', letterSpacing: '.06em' }}>
          Actividade Digi · últimos 7 dias · todos os canais
        </div>
        {!timelineEvs && (
          <div style={{ fontSize: 11, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)', textAlign: 'center', paddingTop: 24 }}>A carregar...</div>
        )}
        {timelineEvs && (!grouped || Object.keys(grouped).length === 0) && (
          <div style={{ fontSize: 11, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)', textAlign: 'center', paddingTop: 24 }}>
            Sem actividade registada nos últimos 7 dias.
          </div>
        )}
        {grouped && Object.entries(grouped).map(([day, evs]) => (
          <MktInicioDigiTimelineDay key={day} day={day} events={evs} />
        ))}
      </div>
    );
  };

  React.useEffect(() => {
    if (!open && Array.isArray(seedInsights) && seedInsights.length && !insights.length) {
      setInsights(seedInsights);
    }
  }, [seedInsights, open]);

  const INSIGHT_COUNT = insights.length;

  return (
    <>
      {!expanded && (
        <div ref={fabRef} style={{ position: 'fixed', bottom: 28, right: 28, zIndex: 200 }}>
          {INSIGHT_COUNT > 0 && !open && (
            <div style={{
              position: 'absolute', top: -5, right: -5, zIndex: 201,
              width: 19, height: 19, borderRadius: '50%',
              background: 'var(--warning)', color: 'var(--text-on-ai, #fff)', border: '2px solid var(--bg)',
              fontSize: 10, fontWeight: 700, display: 'flex', alignItems: 'center', justifyContent: 'center',
              animation: 'mkt-inicio-digi-pulse 2.4s ease-in-out infinite',
            }}>{INSIGHT_COUNT > 9 ? '9+' : INSIGHT_COUNT}</div>
          )}
          <button className="mkt-inicio-digi-fab" onClick={() => setOpen(o => !o)} title="Digi AI" style={{
            width: 52, height: 52, borderRadius: '50%', border: 'none', cursor: 'pointer',
            background: open ? 'var(--brand-900)' : 'var(--ai-500)', color: 'var(--text-on-ai, #fff)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            boxShadow: open ? 'none' : '0 4px 18px color-mix(in oklch, var(--ai-500) 38%, transparent)',
            transition: 'all .2s',
          }}>
            {open
              ? <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M18 6 6 18M6 6l12 12"/></svg>
              : <svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8">
                  <path d="M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96-.46 2.5 2.5 0 0 1-2.96-3.08 3 3 0 0 1-.34-5.58 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 4.44-1.14Z"/>
                  <path d="M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96-.46 2.5 2.5 0 0 0 2.96-3.08 3 3 0 0 0 .34-5.58 2.5 2.5 0 0 0-1.32-4.24 2.5 2.5 0 0 0-4.44-1.14Z"/>
                </svg>
            }
          </button>
        </div>
      )}

      {open && !expanded && (
        <div ref={panelRef} className="mkt-inicio-digi-panel" style={{
          position: 'fixed', bottom: 92, right: 28, width: 420, height: 640, maxHeight: 'calc(100vh - 120px)', zIndex: 199,
          background: 'var(--bg-elev)', border: '1px solid var(--border)', borderRadius: 16,
          boxShadow: '0 20px 60px color-mix(in oklch, var(--ai-500) 14%, transparent)',
          display: 'flex', flexDirection: 'column', overflow: 'hidden',
        }}>
          {DigiHeader({ isExpanded: false })}
          {mode === 'chat' ? DigiChat({ isExpanded: false }) : <DigiTimeline />}
        </div>
      )}

      {open && expanded && ReactDOM.createPortal(
        <>
          <div className="mkt-inicio-digi-backdrop" onClick={() => setExpanded(false)} style={{
            position: 'fixed', inset: 0, background: 'color-mix(in oklch, var(--text) 54%, transparent)', zIndex: 298,
          }} />
          <div className="mkt-inicio-digi-modal" style={{
            position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%,-50%)',
            width: 'min(1040px, 92vw)', height: '82vh', zIndex: 299,
            background: 'var(--bg-elev)', border: '1px solid var(--border)', borderRadius: 18,
            boxShadow: 'var(--shadow-lg)',
            display: 'flex', flexDirection: 'column', overflow: 'hidden',
          }}>
            {DigiHeader({ isExpanded: true })}
            {mode === 'chat' ? DigiChat({ isExpanded: true }) : <DigiTimeline />}
          </div>
        </>,
        document.body
      )}

      <style>{`
        @keyframes mkt-inicio-digi-pulse { 0%,100%{transform:scale(1)} 50%{transform:scale(1.18)} }
        @keyframes mkt-inicio-digi-dot { from{opacity:.3;transform:translateY(0)} to{opacity:1;transform:translateY(-3px)} }
        @keyframes mkt-inicio-digi-panel-in { from { opacity:0; transform:translateY(12px) scale(.96); } to { opacity:1; transform:translateY(0) scale(1); } }
        @keyframes mkt-inicio-digi-modal-in { from { opacity:0; transform:translate(-50%,-50%) scale(.94); } to { opacity:1; transform:translate(-50%,-50%) scale(1); } }
        @keyframes mkt-inicio-digi-backdrop-in { from { opacity:0; } to { opacity:1; } }
        @keyframes mkt-inicio-digi-msg-in { from { opacity:0; transform:translateY(6px); } to { opacity:1; transform:translateY(0); } }
        @keyframes mkt-inicio-digi-fab-in { from { opacity:0; transform:scale(.5); } to { opacity:1; transform:scale(1); } }
        .mkt-inicio-digi-fab { animation: mkt-inicio-digi-fab-in .28s cubic-bezier(.34,1.56,.64,1); }
        .mkt-inicio-digi-fab:hover { transform: scale(1.08); }
        .mkt-inicio-digi-panel { animation: mkt-inicio-digi-panel-in .22s cubic-bezier(.2,.9,.3,1); transform-origin: bottom right; }
        .mkt-inicio-digi-backdrop { animation: mkt-inicio-digi-backdrop-in .18s ease-out; }
        .mkt-inicio-digi-modal { animation: mkt-inicio-digi-modal-in .24s cubic-bezier(.2,.9,.3,1); }
        .mkt-inicio-digi-msg { animation: mkt-inicio-digi-msg-in .22s cubic-bezier(.2,.9,.3,1); }
      `}</style>
    </>
  );
};

const MktInicioDashHead = ({ title, extra }) => (
  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '12px 14px', borderBottom: '1px solid var(--border)', gap: 8 }}>
    <div className="font-display" style={{ fontSize: 14, fontWeight: 650 }}>{title}</div>
    {extra || null}
  </div>
);

const MktInicioSentBar = ({ pos = 0, neu = 0, neg = 0 }) => {
  const t = pos + neu + neg;
  const w = (n) => t ? `${(n / t) * 100}%` : '0%';
  return (
    <div title={`${pos} pos · ${neu} neu · ${neg} neg`} style={{
      display: 'flex', height: 8, borderRadius: 99, overflow: 'hidden',
      background: 'var(--bg-sunken)', minWidth: 72, marginTop: 8,
    }}>
      <div style={{ width: w(pos), background: 'var(--success)' }} />
      <div style={{ width: w(neu), background: 'var(--text-dim)', opacity: 0.45 }} />
      <div style={{ width: w(neg), background: 'var(--danger)' }} />
    </div>
  );
};

const MktInicioWeekLeads = ({ serie }) => {
  const rows = Array.isArray(serie) ? serie : [];
  if (!rows.length) return <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>Sem série neste período.</div>;
  const max = Math.max(1, ...rows.map(r => Number(r.leads) || 0));
  const w = 320;
  const h = 72;
  const pad = 6;
  const step = rows.length > 1 ? (w - pad * 2) / (rows.length - 1) : 0;
  const pts = rows.map((r, i) => {
    const x = pad + i * step;
    const y = h - pad - ((Number(r.leads) || 0) / max) * (h - pad * 2);
    return `${x},${y}`;
  }).join(' ');
  return (
    <div>
      <svg width="100%" viewBox={`0 0 ${w} ${h}`} role="img" aria-label="Leads por semana" style={{ display: 'block' }}>
        <polyline fill="none" stroke="var(--ai-500)" strokeWidth="2" points={pts} />
      </svg>
      <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 10, color: 'var(--text-dim)', marginTop: 4 }}>
        <span>{String(rows[0].semana || '').slice(0, 10)}</span>
        <span>{String(rows[rows.length - 1].semana || '').slice(0, 10)}</span>
      </div>
    </div>
  );
};

const MktInicioProdBars = ({ rows, onPick }) => {
  const list = (rows || []).filter(r => Number(r.v) > 0);
  if (!list.length) return <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>Nada em produção neste momento.</div>;
  const max = Math.max(1, ...list.map(r => Number(r.v) || 0));
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
      {list.map(r => (
        <button key={r.id} type="button" onClick={() => onPick && onPick(r)} style={{
          textAlign: 'left', background: 'transparent', border: 0, padding: 0, cursor: 'pointer', color: 'inherit', width: '100%',
        }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', gap: 8, fontSize: 12 }}>
            <span style={{ fontWeight: 600 }}>{r.label}</span>
            <span style={{ fontFamily: 'var(--font-mono)', color: 'var(--text-muted)' }}>{resFmtN(r.v)}</span>
          </div>
          <div style={{ height: 8, borderRadius: 99, background: 'var(--surface-muted)', marginTop: 6, overflow: 'hidden' }}>
            <div style={{ width: `${Math.max(4, (Number(r.v) / max) * 100)}%`, height: '100%', borderRadius: 99, background: r.danger ? 'var(--danger)' : 'linear-gradient(90deg, #d6e2f0, #3859D0)' }} />
          </div>
        </button>
      ))}
    </div>
  );
};

const MktInicioQaRow = ({ item, onOpen }) => (
  <button type="button" onClick={() => onOpen(item)} style={{
    display: 'flex', alignItems: 'center', gap: 10, width: '100%', textAlign: 'left',
    padding: '10px 14px', background: 'transparent', border: 0, borderBottom: '1px solid var(--border)',
    cursor: 'pointer', color: 'inherit',
  }}>
    <div style={{
      width: 28, height: 28, borderRadius: 7, background: 'var(--bg-sunken)',
      display: 'grid', placeItems: 'center', color: 'var(--text-muted)', flexShrink: 0,
    }}>{mktInicioIco(item.icon || 'flag', 13)}</div>
    <div style={{ flex: 1, minWidth: 0 }}>
      <div style={{ fontSize: 13, fontWeight: 600 }}>{item.title}</div>
      {item.sub && <div style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 2 }}>{item.sub}</div>}
    </div>
    <span style={{ color: 'var(--text-dim)', flexShrink: 0 }}>{mktInicioIco('chevron-right', 14) || '→'}</span>
  </button>
);

function mktInicioIsDev() {
  try {
    const port = String(window.location.port || '');
    const host = String(window.location.hostname || '').toLowerCase();
    if (port === '3008' || port === '3009') return false;
    if (port === '3010') return true;
    if (host === 'marketing.farben-holding.ai') return true;
    if (host === 'localhost' || host === '127.0.0.1') return true;
    return false;
  } catch { return false; }
}

const MKT_INICIO_DEV_MODS = [
  { id: 'objectivos', label: 'Objectivos', estado: 'stub', done: 0, total: 1, dest: 'objectivos' },
  { id: 'budget', label: 'Budget', estado: 'parcial', done: 1, total: 2, dest: 'budget' },
  { id: 'briefings', label: 'Briefings', estado: 'parcial', done: 0, total: 10, dest: 'briefings' },
  { id: 'activacao', label: 'Activação owned', estado: 'parcial', done: 2, total: 7, dest: 'publicacao' },
  { id: 'sdr', label: 'SDR', estado: 'parcial', done: 4, total: 9, dest: 'sdr' },
];

const MKT_INICIO_DEV_NEXT = [
  { id: 'd1', title: 'Objectivos · BP vs real', sub: 'Stub · dados comerciais já no Postgres', dest: 'objectivos', icon: 'flag' },
  { id: 'd2', title: 'Activação · envio owned', sub: '2 de 7 · Brevo / WhatsApp neste VPS', dest: 'publicacao', icon: 'check' },
  { id: 'd3', title: 'Briefings · Fase 1', sub: 'Bugs de status e PUT que apaga', dest: 'briefings', icon: 'doc' },
  { id: 'd4', title: 'SDR · Visão geral', sub: 'Painel todas as SPs, estilo Resultados', dest: 'sdr', icon: 'sparkle' },
  { id: 'd5', title: 'Budget · outras categorias', sub: 'Paid Media ligado · faltam ferramentas e fornecedores', dest: 'budget', icon: 'alert' },
];

const MktInicioDevBars = ({ rows, onPick }) => {
  const list = rows || [];
  if (!list.length) return null;
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
      {list.map(r => {
        const tot = Math.max(1, Number(r.total) || 1);
        const done = Number(r.done) || 0;
        const pct = Math.min(100, (done / tot) * 100);
        const stub = r.estado === 'stub';
        return (
          <button key={r.id} type="button" onClick={() => onPick && onPick(r)} style={{
            textAlign: 'left', background: 'transparent', border: 0, padding: 0, cursor: 'pointer', color: 'inherit', width: '100%',
          }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', gap: 8, fontSize: 12 }}>
              <span style={{ fontWeight: 600 }}>{r.label}</span>
              <span style={{ fontFamily: 'var(--font-mono)', color: stub ? 'var(--warning)' : 'var(--text-muted)' }}>
                {stub ? 'stub' : `${done} / ${tot}`}
              </span>
            </div>
            <div style={{ height: 8, borderRadius: 99, background: 'var(--surface-muted)', marginTop: 6, overflow: 'hidden' }}>
              <div style={{
                width: `${stub ? 6 : Math.max(4, pct)}%`, height: '100%', borderRadius: 99,
                background: stub ? 'var(--warning)' : 'var(--ai-500)',
              }} />
            </div>
          </button>
        );
      })}
    </div>
  );
};

const MKT_INICIO_STRATEGIST_EMAILS = new Set(['carlos.alves@decal.pt']);

function mktInicioEhStrategist(userEmail, userName) {
  try {
    const q = new URLSearchParams(window.location.search || '');
    if (q.get('mkt_role') === 'strategist' || q.get('dev') === 'carlos') return true;
  } catch {}
  const email = String(userEmail || window.currentUser?.email || '').toLowerCase();
  if (MKT_INICIO_STRATEGIST_EMAILS.has(email)) return true;
  const nome = String(userName || window.currentUser?.nome_apresentar || window.currentUser?.nome || '').trim().toLowerCase();
  return nome === 'carlos alves';
}

const MktInicioStrategist = ({ setSub, nome, data, error, loading, onRefresh }) => {
  const [mod, setMod] = React.useState('tudo');
  const [esperaAberta, setEsperaAberta] = React.useState(false);
  const bp = window.useBreakpoint ? window.useBreakpoint() : { isMobile: false };
  const isMobile = !!bp.isMobile;
  const primeiro = String(nome || 'Carlos').split(' ')[0];
  const modulos = data?.modulos || [];
  const alteracoes = data?.alteracoes || [];
  const lista = mod === 'tudo' ? (data?.fazer || []) : ((data?.por_modulo || {})[mod] || []);
  const esperaN = Number(data?.espera_n) || (data?.espera || []).length;
  const pill = (active) => ({
    padding: '8px 10px', borderRadius: 8, border: '1px solid var(--border)', cursor: 'pointer', textAlign: 'left',
    background: active ? 'var(--bg-elev)' : 'var(--bg)', color: 'inherit', minWidth: 0,
  });

  return (
    <div className="scrollbar" style={{ flex: 1, overflowY: 'auto', minHeight: 0, padding: isMobile ? '16px 16px 96px' : '20px 28px 96px' }}>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 16, marginBottom: 16, flexWrap: 'wrap' }}>
        <div>
          <div style={{ fontSize: 10, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)', letterSpacing: '0.08em' }}>MARKETING · INÍCIO</div>
          <h1 className="font-display" style={{ margin: '6px 0 4px', fontSize: 26, fontWeight: 650, letterSpacing: '-0.015em' }}>O que fazer</h1>
          <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>{primeiro} · Strategist · Briefings, Campanhas, Conteúdos, Activação e Open Houses</div>
        </div>
        <button type="button" className="btn btn-sm" onClick={onRefresh}>{mktInicioIco('refresh', 13)}Actualizar</button>
      </div>

      {error && (
        <div style={{
          marginBottom: 12, padding: '10px 14px', borderRadius: 8,
          background: 'color-mix(in oklch, var(--danger) 10%, transparent)',
          border: '1px solid color-mix(in oklch, var(--danger) 28%, transparent)',
          color: 'var(--danger)', fontSize: 12,
        }}>{error}</div>
      )}
      {loading && <div style={{ color: 'var(--text-muted)', fontSize: 12, marginBottom: 12 }}>A preparar o que tens de fazer…</div>}

      <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr 1fr' : 'repeat(5, minmax(0, 1fr))', gap: 8, marginBottom: 16 }}>
        {modulos.map(m => (
          <button key={m.id} type="button" onClick={() => setMod(mod === m.id ? 'tudo' : m.id)} style={pill(mod === m.id)}>
            <div style={{ fontSize: 18, fontWeight: 650, color: m.id === 'briefings' && alteracoes.length ? '#b45309' : 'inherit' }}>{m.n || 0}</div>
            <div style={{ fontSize: 11, color: m.id === 'briefings' && alteracoes.length ? '#b45309' : 'var(--text-muted)' }}>{m.label}</div>
          </button>
        ))}
      </div>

      {alteracoes.length > 0 && (
        <div className="card" style={{ padding: 0, overflow: 'hidden', marginBottom: 12, border: '1px solid #fcd34d' }}>
          <div style={{ padding: '12px 14px', background: 'rgba(217,119,6,0.10)' }}>
            <div className="font-display" style={{ fontSize: 14, fontWeight: 650, color: '#b45309' }}>
              {alteracoes.length === 1 ? 'Tens alterações para fazer' : `Tens ${alteracoes.length} briefings com alterações para fazer`}
            </div>
            <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 2 }}>Abre o briefing, corrige e submete novamente.</div>
          </div>
          {alteracoes.map(item => (
            <MktInicioQaRow key={item.id} item={{ ...item, title: item.titulo }} onOpen={it => mktInicioNav(setSub, it.dest, it.extra || {})} />
          ))}
        </div>
      )}

      <div className="card" style={{ padding: 0, overflow: 'hidden', marginBottom: 12 }}>
        <MktInicioDashHead title={mod === 'tudo' ? 'Para tratar agora' : (modulos.find(m => m.id === mod)?.label || 'Para tratar')} />
        {!loading && !lista.length ? (
          <div style={{ padding: 16, fontSize: 13, color: 'var(--text-muted)' }}>
            {mod === 'tudo' ? 'Não há nada parado na execução.' : 'Nada parado neste módulo.'}
          </div>
        ) : lista.map(item => (
          <MktInicioQaRow key={item.id} item={{ ...item, title: item.titulo }} onOpen={it => mktInicioNav(setSub, it.dest, it.extra || {})} />
        ))}
      </div>

      {esperaN > 0 && (
        <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
          <button type="button" onClick={() => setEsperaAberta(v => !v)} style={{
            display: 'flex', alignItems: 'center', justifyContent: 'space-between', width: '100%',
            padding: '12px 14px', background: 'transparent', border: 0, cursor: 'pointer', color: 'inherit', textAlign: 'left',
          }}>
            <span className="font-display" style={{ fontSize: 14, fontWeight: 650 }}>À espera de outros</span>
            <span style={{ fontSize: 12, color: 'var(--text-muted)' }}>{esperaAberta ? 'Fechar' : esperaN}</span>
          </button>
          {esperaAberta && (data?.espera || []).map(item => (
            <MktInicioQaRow key={item.id} item={{ ...item, title: item.titulo }} onOpen={it => mktInicioNav(setSub, it.dest, it.extra || {})} />
          ))}
        </div>
      )}
    </div>
  );
};

const MKT_INICIO_PERIODS = [
  { id: 'last_30d', label: '30d' },
  { id: 'ytd', label: 'YTD' },
];
const MKT_INICIO_NAV_KEY = 'mkt-resultados-nav-v2';
const MKT_INICIO_ANOS = [2022, 2023, 2024, 2025, 2026];

function mktInicioLerNav() {
  try { return JSON.parse(localStorage.getItem(MKT_INICIO_NAV_KEY) || '{}'); } catch { return {}; }
}

function mktInicioGravarNav(patch) {
  const nav = { ...mktInicioLerNav(), ...patch };
  try { localStorage.setItem(MKT_INICIO_NAV_KEY, JSON.stringify(nav)); } catch {}
  return nav;
}

const MktInicioScreen = ({ setSub, userName, userEmail }) => {
  const [data, setData] = React.useState(null);
  const [overview, setOverview] = React.useState(null);
  const [ovErr, setOvErr] = React.useState('');
  const [ovLoading, setOvLoading] = React.useState(true);
  const [error, setError] = React.useState('');
  const [toast, setToast] = React.useState('');
  const email = userEmail || window.currentUser?.email || '';
  const rawName = userName || (window.currentUser && (window.currentUser.nome_apresentar || window.currentUser.nome)) || '';
  const strategist = mktInicioEhStrategist(email, rawName);
  window.useMktZoneLoading(strategist ? (!data && !error) : (ovLoading && !overview));
  const navInicial = mktInicioLerNav();
  const [periodo, setPeriodo] = React.useState(navInicial.periodo || 'ytd');
  const [navTick, setNavTick] = React.useState(0);
  const bp = window.useBreakpoint ? window.useBreakpoint() : { isDesktop: true, isMobile: false };
  const isMobile = !!bp.isMobile;
  const brandApi = window.useMktBrand ? window.useMktBrand() : { brand: 'todas', isAll: true, setBrand: () => {} };
  const { brand, isAll } = brandApi;

  const loadDash = React.useCallback(() => {
    setError('');
    const url = email
      ? `/api/marketing/dashboard?email=${encodeURIComponent(email)}`
      : '/api/marketing/dashboard';
    mktInicioApi(url)
      .then(d => { setData(d); })
      .catch(e => setError(e.message || 'Erro a carregar dashboard'));
  }, [email]);

  const loadOverview = React.useCallback(() => {
    setOvLoading(true);
    setOvErr('');
    const nav = mktInicioLerNav();
    const year = MKT_INICIO_ANOS.includes(Number(nav.year)) ? Number(nav.year) : new Date().getFullYear();
    const per = periodo || nav.periodo || 'ytd';
    const canal = nav.canal || 'todos';
    const estado = nav.estado || 'todas';
    const marca = isAll ? '' : `&marca=${encodeURIComponent(brand)}`;
    const datas = per === 'custom' && nav.inicio && nav.fim ? `&inicio=${nav.inicio}&fim=${nav.fim}` : '';
    mktInicioApi(`/api/marketing/resultados/v2/overview?periodo=${encodeURIComponent(per)}&year=${year}&estado=${encodeURIComponent(estado)}&canal=${encodeURIComponent(canal)}${datas}${marca}`)
      .then(d => { setOverview(d); setOvLoading(false); })
      .catch(e => { setOvErr(e.message); setOvLoading(false); });
  }, [periodo, brand, isAll, navTick]);

  React.useEffect(() => { loadDash(); }, [loadDash]);
  React.useEffect(() => {
    if (strategist) { setOvLoading(false); return; }
    loadOverview();
  }, [loadOverview, strategist]);
  React.useEffect(() => {
    const sync = () => {
      const nav = mktInicioLerNav();
      if (nav.periodo && nav.periodo !== periodo) setPeriodo(nav.periodo);
      setNavTick(t => t + 1);
    };
    window.addEventListener('focus', sync);
    window.addEventListener('storage', sync);
    return () => {
      window.removeEventListener('focus', sync);
      window.removeEventListener('storage', sync);
    };
  }, [periodo]);

  const showToast = (msg) => { setToast(msg); setTimeout(() => setToast(''), 2800); };

  const onAcceptInsight = async (ins) => {
    try {
      if (ins?.persistido === false || !ins?.id || String(ins.id).startsWith('bp_gap:')) {
        mktInicioNav(setSub, 'briefings', { novoBriefing: true });
        return;
      }
      const r = await mktInicioApi(`/api/marketing/digi/insights/${ins.id}/suggest-briefing`, { method: 'POST' });
      setData(d => d ? {
        ...d,
        insights_activos: (d.insights_activos || []).filter(x => x.id !== ins.id),
        recomendacoes: (d.recomendacoes || []).filter(x => String(x.id) !== String(ins.id)),
        inbox: (d.inbox || []).filter(x => !(x.origem === 'insight_p0' && String(x.id) === String(ins.id))),
        roadmap: d.roadmap ? {
          ...d.roadmap,
          bloqueios: (d.roadmap.bloqueios || []).filter(x => !(x.origem === 'insight_p0' && String(x.id) === String(ins.id))),
        } : d.roadmap,
      } : d);
      showToast(r?.suggestion?.titulo_campanha ? `Briefing sugerido: ${r.suggestion.titulo_campanha}` : 'Insight aceite');
      mktInicioNav(setSub, 'briefings', { novoBriefing: true });
    } catch (e) { showToast(e.message); }
  };

  const onOpenItem = async (item) => {
    if (item.origem === 'notificacao') {
      mktInicioApi(`/api/marketing/notificacoes/${item.id}/read`, { method: 'POST' }).catch(() => {});
    }
    mktInicioNav(setSub, item.dest || 'inicio', item.extra || {});
  };

  const k = data?.kpis || {};
  const sl = data?.social_live || {};
  const tot = sl.totais_7d || {};
  const ov = overview || {};
  const ok = ov.kpis || {};
  const seoN = data?.seo_criticos || 0;
  const noAr = (ov.campanhas || []).filter(c => c.estado === 'no_ar').slice(0, 6);

  const dashState = {
    pending_approvals: (data?.aprovacoes_pendentes || []).length,
    insights_p0: k.insights_criticos_p0 || 0,
    insights: (data?.insights_activos || []).map(i => ({ id: i.id, priority: i.priority, title: i.title })),
    tarefas_hoje: (data?.tarefas_hoje || []).map(t => ({ id: t.id, tipo: t.tipo, titulo: t.titulo, prioridade: t.prioridade })),
    inbox: (data?.inbox || []).slice(0, 8).map(i => ({ origem: i.origem, titulo: i.titulo, prioridade: i.prioridade })),
    social_live: { n: tot.n, spend: tot.spend, leads: tot.leads, erro: sl.erro },
    kpis: {
      briefings: k.briefings_pendentes, copies: k.copies_aguarda_aprovacao,
      prompts: k.prompts_aguarda_aprovacao, campanhas: k.campanhas_activas,
      clipping: k.clipping_criticas, open_houses: k.open_houses_proximos,
      pecas_falhou: k.pecas_falhou, plano_atrasados: k.plano_atrasados,
    },
  };

  const qa = [];
  if (k.pecas_falhou) qa.push({ id: 'falhou', title: 'Publicação falhou', sub: `${k.pecas_falhou} peça${k.pecas_falhou === 1 ? '' : 's'}`, dest: 'publicacao', extra: {}, icon: 'alert' });
  if (k.clipping_criticas) qa.push({ id: 'clip', title: 'Clipping crítico', sub: `${k.clipping_criticas} por rever`, dest: 'clipping', extra: { filterCriticas: true }, icon: 'flag' });
  if (k.sdr_hot_sem_t0) qa.push({ id: 'hot', title: 'HOT sem T0', sub: `${k.sdr_hot_sem_t0} leads`, dest: 'crm', extra: {}, icon: 'sparkle' });
  if (seoN) qa.push({ id: 'seo', title: 'SEO crítico', sub: `${seoN} issues abertos`, dest: 'seo', extra: {}, icon: 'alert' });
  if (k.plano_atrasados) qa.push({ id: 'plano', title: 'Plano atrasado', sub: `${k.plano_atrasados} ${k.plano_atrasados === 1 ? 'item' : 'itens'}`, dest: 'plano-comunicacao', extra: {}, icon: 'flag' });
  if (k.briefings_pendentes) qa.push({ id: 'br', title: 'Rever aprovações', sub: `${k.briefings_pendentes} briefings`, dest: 'briefings', extra: {}, icon: 'doc' });
  if (k.copies_aguarda_aprovacao || k.pecas_aguarda_revisao) qa.push({ id: 'prod', title: 'Produzir', sub: `${(k.copies_aguarda_aprovacao || 0) + (k.pecas_aguarda_revisao || 0)} em fila`, dest: 'conteudos', extra: {}, icon: 'image' });
  qa.push({ id: 'act', title: 'Activar', sub: 'Peças prontas a publicar', dest: 'publicacao', extra: {}, icon: 'check' });
  qa.push({ id: 'nb', title: 'Novo briefing', sub: 'Começar uma campanha', dest: 'briefings', extra: { novoBriefing: true }, icon: 'doc' });
  const qaShow = qa.slice(0, 5);

  const twoCols = isMobile ? '1fr' : '1fr 1fr';
  const resPill = (active) => ({
    padding: '5px 10px', borderRadius: 6, fontSize: 11, fontFamily: 'var(--font-display)', fontWeight: 600,
    border: 'none', cursor: 'pointer',
    background: active ? 'var(--bg-elev)' : 'transparent',
    color: active ? 'var(--text)' : 'var(--text-muted)',
  });

  const onOpenCampanhaRes = (c) => {
    if (c?.id) mktInicioNav(setSub, 'resultados', {});
    else mktInicioNav(setSub, 'resultados', {});
  };

  const [, setVizTick] = React.useState(0);
  React.useEffect(() => {
    if (strategist || (window.ResFunil && window.ResObjectivoCards)) return undefined;
    let n = 0;
    const t = setInterval(() => {
      n += 1;
      if ((window.ResFunil && window.ResObjectivoCards) || n > 80) {
        clearInterval(t);
        setVizTick(v => v + 1);
      }
    }, 50);
    return () => clearInterval(t);
  }, [strategist]);
  const FunilCmp = window.ResFunil;
  const ObjCards = window.ResObjectivoCards;
  const sectorFunil = window.resSectorFunil;
  const showDev = mktInicioIsDev();

  if (strategist) {
    const fila = data?.perfil === 'strategist' ? data : null;
    const stratState = {
      perfil: 'strategist',
      alteracoes: (fila?.alteracoes || []).map(i => ({ titulo: i.titulo, sub: i.sub })),
      fazer: (fila?.fazer || []).map(i => ({ modulo: i.modulo, titulo: i.titulo, sub: i.sub })),
      espera: fila?.espera_n || 0,
    };
    return (
      <div style={{ display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0, overflow: 'hidden' }}>
        <MktInicioStrategist
          setSub={setSub}
          nome={fila?.nome || rawName || 'Carlos Alves'}
          data={fila}
          error={error || (data && data.perfil !== 'strategist' ? 'Não consegui abrir a fila de execução.' : '')}
          loading={!data && !error}
          onRefresh={loadDash}
        />
        <MktInicioDigiChat
          userName={rawName || fila?.nome || 'Carlos Alves'}
          userEmail={email}
          dashboardState={stratState}
          seedInsights={[]}
          onInsightDismissed={() => {}}
          onInsightAccepted={() => {}}
        />
        {toast && (
          <div style={{
            position: 'fixed', bottom: 24, left: '50%', transform: 'translateX(-50%)', zIndex: 220,
            padding: '8px 14px', borderRadius: 8, background: 'var(--bg-elev)', border: '1px solid var(--border)',
            boxShadow: 'var(--shadow-md)', fontSize: 12, color: 'var(--text)',
          }}>{toast}</div>
        )}
      </div>
    );
  }

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0, overflow: 'hidden' }}>
      <div className="scrollbar" style={{ flex: 1, overflowY: 'auto', minHeight: 0, padding: isMobile ? '16px 16px 96px' : '20px 28px 96px' }}>
        <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 16, marginBottom: 14, flexWrap: 'wrap' }}>
          <div>
            <div style={{ fontSize: 10, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)', letterSpacing: '0.08em' }}>MARKETING · INÍCIO</div>
            <h1 className="font-display" style={{ margin: '6px 0 4px', fontSize: 26, fontWeight: 650, letterSpacing: '-0.015em' }}>Resultados e campanhas no ar</h1>
            <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>
              {ov.periodo?.label || 'YTD'}
              {' · no ar: em Activação com peça publicada, ou activa na Meta'}
              {ov.atualizado_em ? ` · actualizado ${new Date(ov.atualizado_em).toLocaleString('pt-PT')}` : ''}
            </div>
          </div>
          <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
            <div style={{ display: 'inline-flex', background: 'var(--bg-sunken)', padding: 3, borderRadius: 8, border: '1px solid var(--border)' }}>
              {MKT_INICIO_PERIODS.map(p => (
                <button key={p.id} type="button" onClick={() => { setPeriodo(p.id); mktInicioGravarNav({ periodo: p.id, year: p.id === 'last_30d' ? new Date().getFullYear() : (mktInicioLerNav().year || new Date().getFullYear()) }); }} style={resPill(periodo === p.id)}>{p.label}</button>
              ))}
            </div>
            <button type="button" className="btn btn-sm" onClick={() => { loadDash(); loadOverview(); }}>{mktInicioIco('refresh', 13)}Actualizar</button>
          </div>
        </div>

        {(error || ovErr) && (
          <div style={{
            marginBottom: 12, padding: '10px 14px', borderRadius: 8,
            background: 'color-mix(in oklch, var(--danger) 10%, transparent)',
            border: '1px solid color-mix(in oklch, var(--danger) 28%, transparent)',
            color: 'var(--danger)', fontSize: 12,
          }}>{error || ovErr}</div>
        )}
        {ovLoading && !overview && <div style={{ color: 'var(--text-muted)', fontSize: 12, marginBottom: 12 }}>A consolidar resultados…</div>}

        {overview && (
          <>
            <div onClick={() => mktInicioNav(setSub, 'resultados', {})} style={{ cursor: 'pointer' }}>
              {FunilCmp ? <FunilCmp
                kpis={ok}
                sector={sectorFunil(isAll ? 'todas' : brand, isAll)}
                marca={isAll ? 'todas' : brand}
                pronto={!ovLoading}
                periodo={ov.periodo?.label}
                campanhasNoAr={ok.campanhas_no_ar}
                gidPrefix="inicio-funil-"
                altura={220}
              /> : null}
            </div>
            {ObjCards ? <ObjCards
              kpis={ok}
              campanhas={ov.campanhas || []}
              brand={isAll ? 'todas' : brand}
              isAll={isAll}
              isMobile={isMobile}
              cta={{
                label: 'Resultados',
                title: 'Ver todos',
                sub: `${mktInicioN((ov.campanhas || []).length)} campanhas · detalhe por canal e marca`,
                onClick: (e) => { if (e && e.stopPropagation) e.stopPropagation(); mktInicioNav(setSub, 'resultados', {}); },
              }}
            /> : null}
            {window.ResAnaliseResumo ? <window.ResAnaliseResumo marca={isAll ? 'todas' : brand} compacto setSub={setSub} /> : null}
          </>
        )}

        <div style={{ display: 'grid', gridTemplateColumns: twoCols, gap: 12, marginBottom: 18, alignItems: 'stretch' }}>
          <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
            <MktInicioDashHead title="Campanhas no ar" extra={
              <button type="button" className="btn btn-sm btn-ghost" onClick={() => mktInicioNav(setSub, 'resultados', {})}>Resultados</button>
            } />
            <div style={{ padding: 12 }}>
              {!noAr.length ? (
                <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>
                  Não há campanhas no ar neste momento.
                  {ov.campanhas ? ` ${resFmtN(ov.campanhas.length)} no período · ${resFmtN(ok.campanhas_portal)} portal · ${resFmtN(ok.campanhas_meta)} Meta.` : ''}
                </div>
              ) : noAr.map(c => (
                <button key={c.id} type="button" onClick={() => onOpenCampanhaRes(c)} className="card" style={{
                  display: 'block', width: '100%', textAlign: 'left', padding: 10, marginBottom: 8, cursor: 'pointer', color: 'inherit',
                }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', gap: 8 }}>
                    <strong style={{ fontSize: 13 }}>{c.titulo}</strong>
                    <span style={{ fontSize: 12, color: 'var(--text-muted)', flexShrink: 0 }}>{resFmtEur(c.spend_eur)}</span>
                  </div>
                  <div style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 4 }}>
                    {c.marca_nome} · {resFmtN((c.etapas || []).find(e => e.key === 'leads')?.real)} leads
                  </div>
                </button>
              ))}
              {sl.erro ? <div style={{ fontSize: 11, color: 'var(--warning)', marginTop: 6 }}>{sl.erro}</div> : null}
              {tot.n ? <div style={{ fontSize: 11, color: 'var(--text-dim)', marginTop: 6 }}>Meta ACTIVE {resFmtN(tot.n)} · {resFmtEur(tot.spend)} / 7d</div> : null}
            </div>
          </div>

          <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
            <MktInicioDashHead title="Acções rápidas" />
            {qaShow.map(item => (
              <MktInicioQaRow key={item.id} item={item} onOpen={it => mktInicioNav(setSub, it.dest, it.extra || {})} />
            ))}
          </div>
        </div>

        {showDev ? (
          <div style={{ display: 'grid', gridTemplateColumns: twoCols, gap: 12, marginBottom: 18, alignItems: 'stretch' }}>
            <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
              <MktInicioDashHead title="Projecto DEV · módulos" extra={
                <span style={{ fontSize: 10, fontFamily: 'var(--font-mono)', letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--text-dim)' }}>Marketing DEV</span>
              } />
              <div style={{ padding: 12 }}>
                <MktInicioDevBars rows={MKT_INICIO_DEV_MODS} onPick={r => mktInicioNav(setSub, r.dest, {})} />
              </div>
            </div>
            <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
              <MktInicioDashHead title="Próximo a implementar" />
              {MKT_INICIO_DEV_NEXT.map(item => (
                <MktInicioQaRow key={item.id} item={item} onOpen={it => mktInicioNav(setSub, it.dest, {})} />
              ))}
            </div>
          </div>
        ) : null}
      </div>

      <MktInicioDigiChat
        userName={rawName}
        userEmail={email}
        dashboardState={dashState}
        seedInsights={data?.insights_activos || []}
        onInsightDismissed={(id) => {
          setData(d => d ? {
            ...d,
            insights_activos: (d.insights_activos || []).filter(x => x.id !== id),
            inbox: (d.inbox || []).filter(x => !(x.origem === 'insight_p0' && String(x.id) === String(id))),
            roadmap: d.roadmap ? {
              ...d.roadmap,
              bloqueios: (d.roadmap.bloqueios || []).filter(x => !(x.origem === 'insight_p0' && String(x.id) === String(id))),
            } : d.roadmap,
          } : d);
        }}
        onInsightAccepted={(ins) => {
          setData(d => d ? {
            ...d,
            insights_activos: (d.insights_activos || []).filter(x => x.id !== ins.id),
            inbox: (d.inbox || []).filter(x => !(x.origem === 'insight_p0' && String(x.id) === String(ins.id))),
            roadmap: d.roadmap ? {
              ...d.roadmap,
              bloqueios: (d.roadmap.bloqueios || []).filter(x => !(x.origem === 'insight_p0' && String(x.id) === String(ins.id))),
            } : d.roadmap,
          } : d);
          if (ins && ['reactivacao', 'campanha_sugerida', 'melhoria_live', 'nova_campanha'].includes(ins.category)) {
            onAcceptInsight(ins);
          } else if (ins && ins.category === 'hot_sem_t0') {
            mktInicioNav(setSub, 'crm', {});
          }
        }}
      />

      {toast && (
        <div style={{
          position: 'fixed', bottom: 24, left: '50%', transform: 'translateX(-50%)', zIndex: 220,
          padding: '8px 14px', borderRadius: 8, background: 'var(--bg-elev)', border: '1px solid var(--border)',
          boxShadow: 'var(--shadow-md)', fontSize: 12, color: 'var(--text)',
        }}>{toast}</div>
      )}
    </div>
  );
};

window.MktInicioScreen = MktInicioScreen;
