/* Comercial · Dashboard (HOME)
 * ========================================================================
 * Nova home do Comercial — painel resumido de todas as sub-secções.
 *
 * Design System: applies the official Digidelta Portal DS (UKO base + Digidelta brand).
 * Root wrapped in .dgd-design-system → Montserrat + light navy-and-blue UKO aesthetic.
 * Tokens: portal/public/design-system/tokens.css (loaded by screen_comercial_wrapper.jsx).
 * Skill ref: ~/.claude/skills/digidelta-portal-design/.
 *
 * Estrutura (scroll vertical, arejado):
 *   1. Hero — saudação Digi + estado BP
 *   2. BP destacado — cartão grande com gap projectado + CTA
 *   3. 3 acções urgentes hoje (Carteira · OPs · Prospecção · Financeiro · SAT)
 *   4. Pulse 4 secções (Clientes · Carteira · Prospecção · OPs) com sparklines/donuts
 *   5. Input "Pergunta à Digi…" com chips
 * ======================================================================== */

// ============================================================================
// PIPELINE HOOK — fetches /api/pipeline/:vendedorId, caches in-component
// ============================================================================
const usePipeline = (vendedorId) => {
  const [state, setState] = React.useState({ data: null, loading: false, error: null });

  React.useEffect(() => {
    if (!vendedorId) return;
    setState(s => ({ ...s, loading: true, error: null }));
    fetch(`/api/pipeline/${vendedorId}`)
      .then(r => r.json())
      .then(json => {
        if (json.error) throw new Error(json.error);
        setState({ data: json, loading: false, error: null });
      })
      .catch(err => {
        console.warn('[Dashboard] pipeline fetch failed:', err.message);
        setState({ data: null, loading: false, error: err.message });
      });
  }, [vendedorId]);

  return state;
};

// Formatação de valores monetários — disponível em todo o ficheiro
const fmtE = (n) => {
  if (n == null) return '****';
  if (n >= 1000000) return `€${(n / 1000000).toFixed(2)}M`;
  if (n >= 1000)    return `€${Math.round(n / 1000)}k`;
  return `€${Math.round(n)}`;
};

// ============================================================================
// MICRO-VIS: sparkline e donut SVG
// ============================================================================
const Sparkline = ({ values, color = 'var(--dgd-primary-500)', w = 120, h = 28, showLast = true }) => {
  const vals = values.filter((v) => v != null);
  if (vals.length < 2) return null;
  const min = Math.min(...vals);
  const max = Math.max(...vals);
  const range = max - min || 1;
  const step = w / (values.length - 1);
  const points = values.map((v, i) => {
    if (v == null) return null;
    const x = i * step;
    const y = h - ((v - min) / range) * (h - 4) - 2;
    return `${x},${y}`;
  }).filter(Boolean).join(' ');
  const lastIdx = values.map((v, i) => v != null ? i : -1).filter((i) => i >= 0).pop();
  const lastX = lastIdx * step;
  const lastY = h - ((values[lastIdx] - min) / range) * (h - 4) - 2;
  return (
    <svg width={w} height={h} style={{ display: 'block' }}>
      <polyline fill="none" stroke={color} strokeWidth="1.75" points={points} />
      {showLast && <circle cx={lastX} cy={lastY} r="2.5" fill={color} />}
    </svg>
  );
};

const Donut = ({ value, max = 100, size = 48, stroke = 5, color = 'var(--dgd-primary-500)', label }) => {
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  const pct = Math.min(value / max, 1);
  const offset = c - pct * c;
  return (
    <div style={{ position: 'relative', width: size, height: size }}>
      <svg width={size} height={size}>
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke="var(--dgd-border-1)" strokeWidth={stroke} />
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke={color} strokeWidth={stroke}
                strokeDasharray={c} strokeDashoffset={offset} strokeLinecap="round"
                transform={`rotate(-90 ${size/2} ${size/2})`} />
      </svg>
      <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 11, fontWeight: 700, color: 'var(--dgd-fg-1)', fontFamily: 'var(--dgd-font-mono)' }}>
        {label}
      </div>
    </div>
  );
};

// ============================================================================
// VIEW TOGGLE — YTM (Year-to-Month) / YTY (Year-to-Year)
// ============================================================================
const DashViewToggle = ({ value, onChange }) => {
  const opts = [
    { id: 'ytm', label: 'YTM', sub: 'Year-to-Month · vs plano anual' },
    { id: 'yty', label: 'YTY', sub: 'Year-to-Year · vs ano anterior' },
  ];
  return (
    <div role="tablist" aria-label="Modo de visualização"
         style={{
           display: 'inline-flex',
           background: 'var(--dgd-bg-surface)',
           border: '1px solid var(--dgd-border-1)',
           borderRadius: 'var(--dgd-radius-md)',
           padding: 2,
           boxShadow: 'var(--dgd-shadow-1)',
           flexShrink: 0,
         }}>
      {opts.map((o) => {
        const active = value === o.id;
        return (
          <button key={o.id}
                  role="tab" aria-selected={active}
                  onClick={() => onChange(o.id)}
                  title={o.sub}
                  style={{
                    background: active ? 'var(--dgd-primary-50)' : 'transparent',
                    color: active ? 'var(--dgd-primary-700)' : 'var(--dgd-fg-2)',
                    border: 0,
                    borderRadius: 'var(--dgd-radius-sm)',
                    padding: '6px 14px',
                    font: 'var(--dgd-button)',
                    letterSpacing: '0.04em',
                    cursor: 'pointer',
                    transition: 'all 150ms ease-out',
                  }}>
            {o.label}
          </button>
        );
      })}
    </div>
  );
};

// ============================================================================
// HERO — top strip (saudação + parágrafo + CTAs + toggle YTM/YTY)
// ============================================================================
// ============================================================================
// FILTER BAR — Marca · Empresa · Período · + Mais filtros (drawer Tier 2)
// ============================================================================
const FILTER_OPTIONS = {
  marca: [
    { value: 'todas',   label: 'Todas as marcas' },
    { value: 'mimaki',  label: 'Mimaki' },
    { value: 'biond',   label: 'BIOND' },
    { value: 'decal',   label: 'Decal' },
    { value: 'sensek',  label: 'Sensek' },
    { value: 'alldecor',label: 'AllDecor' },
  ],
  empresa: [
    { value: 'pt',      label: 'Digidelta PT' },
    { value: 'es',      label: 'Dimension ES' },
    { value: 'ns',      label: 'Netscreen' },
    { value: 'tas',     label: 'TAS' },
    { value: 'todas',   label: 'Todas as empresas' },
  ],
  periodo: [
    { value: 'mes',     label: 'Este mês' },
    { value: 'tri',     label: 'Trimestre' },
    { value: 'ytd',     label: 'YTD · Ano' },
    { value: 'yty',     label: 'YTY · vs ano' },
    { value: 'custom',  label: 'Custom…' },
  ],
};

const FilterDropdown = ({ icon, value, options, onChange }) => {
  const current = options.find(o => o.value === value) || options[0];
  const isDefault = value === options[0].value;
  return (
    <label style={{
      display: 'inline-flex', alignItems: 'center', gap: 8,
      padding: '7px 10px 7px 12px',
      borderRadius: 'var(--dgd-radius-md, 8px)',
      background: isDefault ? 'transparent' : 'color-mix(in oklch, var(--dd-primary-600, #3859D0) 10%, transparent)',
      border: '1px solid ' + (isDefault ? 'var(--dgd-border-2)' : 'color-mix(in oklch, var(--dd-primary-600, #3859D0) 30%, transparent)'),
      fontSize: 12, fontWeight: 600,
      color: isDefault ? 'var(--dgd-fg-2)' : 'var(--dd-primary-600, #3859D0)',
      cursor: 'pointer',
      position: 'relative',
      transition: 'background 150ms, border-color 150ms, color 150ms',
      minHeight: 32,
    }}
    onMouseEnter={(e) => {
      if (isDefault) e.currentTarget.style.borderColor = 'var(--dgd-fg-3, #6B7080)';
    }}
    onMouseLeave={(e) => {
      if (isDefault) e.currentTarget.style.borderColor = 'var(--dgd-border-2)';
    }}>
      <Icon name={icon} size={13} style={{ color: isDefault ? 'var(--dgd-fg-3)' : 'var(--dd-primary-600, #3859D0)' }} />
      <span style={{ lineHeight: 1, whiteSpace: 'nowrap' }}>{current.label}</span>
      <Icon name="chevron" size={11} style={{ color: 'currentColor', opacity: 0.65, marginLeft: 2 }} />
      <select value={value} onChange={(e) => onChange(e.target.value)}
        style={{
          position: 'absolute', inset: 0, opacity: 0,
          width: '100%', height: '100%', cursor: 'pointer',
        }}>
        {options.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
      </select>
    </label>
  );
};

const DashFilterBar = () => {
  const [marca,   setMarca]   = React.useState('todas');
  const [empresa, setEmpresa] = React.useState('pt');
  const [periodo, setPeriodo] = React.useState('ytd');
  return (
    <div style={{ display: 'inline-flex', gap: 6, alignItems: 'center', flexWrap: 'wrap' }}>
      <FilterDropdown icon="tag"      value={marca}   options={FILTER_OPTIONS.marca}   onChange={setMarca} />
      <FilterDropdown icon="building" value={empresa} options={FILTER_OPTIONS.empresa} onChange={setEmpresa} />
      <FilterDropdown icon="calendar" value={periodo} options={FILTER_OPTIONS.periodo} onChange={setPeriodo} />
      <button
        onClick={() => alert('Drawer "+ Mais filtros" — em build:\n• Source / Origem (Web · WhatsApp · Referral · Ads · Showroom · Outbound)\n• Idade da OP (<7d · activa · parada >30d · risk >60d)\n• Valor mínimo (slider €0–€500k)')}
        style={{
          display: 'inline-flex', alignItems: 'center', gap: 6,
          padding: '7px 12px',
          borderRadius: 'var(--dgd-radius-md, 8px)',
          border: 'none',
          background: 'transparent',
          fontSize: 12, fontWeight: 600,
          color: 'var(--dgd-fg-3)',
          cursor: 'pointer', fontFamily: 'inherit',
          minHeight: 32,
          transition: 'color 150ms, background 150ms',
        }}
        onMouseEnter={(e) => { e.currentTarget.style.color = 'var(--dd-primary-600, #3859D0)'; e.currentTarget.style.background = 'color-mix(in oklch, var(--dd-primary-600, #3859D0) 8%, transparent)'; }}
        onMouseLeave={(e) => { e.currentTarget.style.color = 'var(--dgd-fg-3)'; e.currentTarget.style.background = 'transparent'; }}>
        <Icon name="plus" size={11} />
        Mais filtros
      </button>
    </div>
  );
};

const HERO_GREETINGS = {
  manha: (n) => [
    `Bom dia, ${n}.`,
    `Olá ${n}, bom dia.`,
    `Boa manhã, ${n}.`,
    `${n}, pronto para o dia?`,
    `Bom dia, ${n} — vamos a isto.`,
    'Bom dia! Café e pipeline?',
    `${n}, bom dia. O dia está teu.`,
  ],
  tarde: (n) => [
    `Boa tarde, ${n}.`,
    `${n}, boa tarde.`,
    `Olá ${n} — como está o dia?`,
    `Boa tarde, ${n}. Há OPs para fechar.`,
    `${n}, ainda dá para fechar uma proposta hoje.`,
  ],
  noite: (n) => [
    `Boa noite, ${n}.`,
    `${n}, ainda na luta?`,
    'Boa noite! A fechar o dia?',
    `${n}, o pipeline também precisa de descansar.`,
  ],
  madrugada: (n) => [
    `${n}, a esta hora?`,
    `Madrugaste, ${n}.`,
    `Ainda acordado, ${n}?`,
  ],
};

const DashHero = ({ viewMode, onChangeView, onNav, userName, pipelineData }) => {
  const firstName = (userName || 'Comercial').split(' ')[0];
  const d = new Date();
  const nowStr = (() => {
    const dias = ['Domingo','Segunda','Terça','Quarta','Quinta','Sexta','Sábado'];
    const meses = ['Janeiro','Fevereiro','Março','Abril','Maio','Junho','Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'];
    return `${dias[d.getDay()]}, ${d.getDate()} de ${meses[d.getMonth()]}`;
  })();
  const greeting = React.useMemo(() => {
    const h = new Date().getHours();
    const period = h < 5 ? 'madrugada' : h < 12 ? 'manha' : h < 19 ? 'tarde' : 'noite';
    const pool = HERO_GREETINGS[period](firstName);
    return pool[Math.floor(Math.random() * pool.length)];
  }, [firstName]);
  return (
    <div style={{
      background: 'var(--dgd-bg-surface)',
      borderRadius: 'var(--dgd-radius-xl)',
      boxShadow: 'var(--dgd-shadow-card)',
      padding: 24,
      display: 'flex', flexDirection: 'column', gap: 20,
    }}>
      <div style={{
        display: 'grid',
        gridTemplateColumns: 'minmax(0, 1fr) auto',
        gap: 24,
        alignItems: 'flex-start',
      }}>
        <div style={{ minWidth: 0 }}>
          <div style={{ font: 'var(--dgd-caption)', color: 'var(--dgd-fg-3)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 8 }}>
            Comercial · {nowStr}
          </div>
          <h1 style={{ margin: 0, font: 'var(--dgd-h1)', letterSpacing: '-0.015em', color: 'var(--dgd-fg-1)' }}>
            {greeting}
          </h1>
          <p style={{ margin: '10px 0 18px', font: 'var(--dgd-body-lg)', color: 'var(--dgd-fg-2)', maxWidth: 760, lineHeight: 1.55 }}>
            {(() => {
              if (!pipelineData) {
                // Sem dados ainda — mock
                return viewMode === 'yty'
                  ? <>Pipeline 2026 vs 2025: <strong style={{ color: 'var(--dgd-green-700)' }}>+22% OPs no funil</strong> (208 vs 170) mas conversão <strong>65→WON</strong> caiu de 28% para <strong style={{ color: 'var(--dgd-red-700)' }}>21%</strong>. Recupera com follow-up &lt;7d nas Demos e proposta concreta na saída do Evento.</>
                  : <>Tens <strong style={{ color: 'var(--dgd-fg-1)' }}>€3,73M no pipeline</strong> e fechaste <strong style={{ color: 'var(--dgd-fg-1)' }}>€189k</strong> (21% do BP). Maior fuga: <strong style={{ color: 'var(--dgd-red-700)' }}>80→90 a 50%</strong> — 9 OPs paradas na Aguarda Decisão valem €612k. Foco da semana: desbloquear top 5 do stage 80 (vale ~€340k) e mover 3 Demos para Aguarda Decisão com proposta fechada.</>;
              }
              const activeStages  = (pipelineData.byStage || []);
              const liveTotal     = activeStages.reduce((a, s) => a + s.value, 0);
              const liveWon       = pipelineData.wonValue || 0;
              const bottleneck    = [...activeStages].sort((a, b) => b.value - a.value)[0];
              return <>
                Tens <strong style={{ color: 'var(--dgd-fg-1)' }}>{fmtE(liveTotal)} no pipeline</strong> ({pipelineData.total} OPs)
                {' '}e fechaste <strong style={{ color: 'var(--dgd-fg-1)' }}>{fmtE(liveWon)}</strong>{' '}
                (<strong style={{ color: 'var(--dgd-red-700)' }}>****% do BP</strong> — meta BP em falta).
                {bottleneck && <> Maior valor em aberto: <strong style={{ color: 'var(--dgd-fg-1)' }}>{bottleneck.stage}</strong> — {fmtE(bottleneck.value)} em {bottleneck.count} OPs.</>}
              </>;
            })()}
          </p>
          <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', alignItems: 'center' }}>
            <button onClick={() => onNav && onNav('bp')}
                    className="dgd-btn dgd-btn-primary">Ver plano BP</button>
            <button onClick={() => {
                      const el = document.getElementById('dash-accoes-anchor');
                      if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
                    }}
                    className="dgd-btn dgd-btn-dark">Acções urgentes</button>
            <div style={{ width: 1, height: 24, background: 'var(--dgd-border-2)', margin: '0 4px' }} />
            <DashFilterBar />
          </div>
        </div>
        <DashViewToggle value={viewMode} onChange={onChangeView} />
      </div>

      <DashHeroPipeline onNav={onNav} pipelineData={pipelineData} />
    </div>
  );
};

// ============================================================================
// HERO PIPELINE — UKO-style vertical bar chart (Total Spent / Earnings Report)
// ============================================================================
// Transform FM byStage data into chart-compatible format
const fmStagesToFunnel = (byStage) => {
  if (!byStage || !byStage.length) return null;
  const active = byStage
    .filter(s => !s.stage.includes('CLOSED - LOST'))
    .sort((a, b) => {
      // Sort by known stage code, then WON last, unknowns at end
      const codeA = parseInt(window.FM_STAGE_CODES?.[a.stage] || a.stage.match(/^(\d+)/)?.[0]) || (a.stage.includes('WON') ? 9999 : 9998);
      const codeB = parseInt(window.FM_STAGE_CODES?.[b.stage] || b.stage.match(/^(\d+)/)?.[0]) || (b.stage.includes('WON') ? 9999 : 9998);
      return codeA - codeB;
    });
  return active.map((s, i) => {
    const isWon = s.stage === '__WON__' || s.stage.includes('CLOSED - WON');
    const code = window.FM_STAGE_CODES?.[s.stage] || s.stage.match(/^(\d+)/)?.[1];
    return {
      id: isWon ? 'FM_WON' : `FM_${i}`,
      label: isWon ? 'WON' : (code || s.stage.slice(0, 6)),
      sub:   isWon ? '__WON__' : s.stage,
      count: s.count,
      value: s.value,
      budget: 0,
      color: isWon ? 'var(--dgd-green-700)' : 'var(--dgd-primary-500)',
    };
  });
};

const DashHeroPipeline = ({ onNav, pipelineData }) => {
  const isLive = !!pipelineData?.byStage;
  const liveFunnel = isLive ? fmStagesToFunnel(pipelineData.byStage) : null;
  const stages = liveFunnel || BRIEFING_FUNNEL;
  const [hover, setHover] = React.useState(null);
  const defaultHighlightId = isLive ? (liveFunnel?.[0]?.id ?? null) : 'S80';
  const activeId = hover ?? defaultHighlightId;
  const active = stages.find(s => s.id === activeId) || stages[0];
  // WON detection: mock uses id='WON', live uses id='FM_WON'
  const findWon = (ss) => ss.find(s => s.id === 'WON' || s.id === 'FM_WON');
  const maxCount = Math.max(...stages.map(s => s.count));
  const totalOps = stages.reduce((acc, s) => acc + s.count, 0);
  const totalValue = stages.reduce((acc, s) => acc + (s.value || 0), 0);
  const globalConv = Math.round((stages[stages.length - 1].count / stages[0].count) * 100);

  // Y-axis: 4 gridlines (0, 25, 50, 75, 100% of round-up max)
  const yTop = Math.ceil(maxCount / 10) * 10;
  const yTicks = [yTop, Math.round(yTop * 0.75), Math.round(yTop * 0.5), Math.round(yTop * 0.25), 0];

  const CHART_H = 180;
  const CHART_PAD_TOP = 14;
  const PRIMARY = 'var(--dd-primary-600, #3859D0)';
  const PRIMARY_SOFT = 'color-mix(in oklch, var(--dd-primary-600, #3859D0) 18%, transparent)';

  return (
    <div style={{
      borderTop: '1px solid var(--dgd-border-2)',
      paddingTop: 18,
      display: 'flex', flexDirection: 'column', gap: 14,
    }}>
      {/* Header */}
      {(() => {
        const facturado = isLive ? (pipelineData.wonValue || 0) : (findWon(stages)?.value || 0);
        const liveConv = isLive && pipelineData.total > 0
          ? Math.round((pipelineData.won / pipelineData.total) * 100)
          : globalConv;
        return (
          <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 16, flexWrap: 'wrap' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <div style={{ font: 'var(--dgd-caption)', color: 'var(--dgd-fg-3)', textTransform: 'uppercase', letterSpacing: '0.08em', fontWeight: 700 }}>
                Pipeline Gestor · oportunidades {isLive && <span style={{ color: 'var(--dgd-green-700)', fontWeight: 600 }}>· dados reais</span>}
              </div>
              <span style={{
                padding: '3px 9px', borderRadius: 999,
                background: 'color-mix(in oklch, var(--dgd-green-700) 14%, transparent)',
                color: 'var(--dgd-green-700)', fontSize: 10.5, fontWeight: 700, letterSpacing: '0.04em',
              }}>{liveConv}% lead→won</span>
            </div>
            <button onClick={() => onNav && onNav('bp')} className="dgd-btn dgd-btn-ghost" style={{ padding: '6px 12px' }}>
              Ver pipeline completo →
            </button>
          </div>
        );
      })()}

      {/* KPIs row — Pipeline total + Facturação YTD vs objectivo */}
      {(() => {
        const facturado = isLive ? (pipelineData.wonValue || 0) : (findWon(stages)?.value || 0);
        // DASH_BP_TARGET só existe no mock — com dados reais mostramos ****
        const bpTarget = isLive ? null : DASH_BP_TARGET;
        const facturaPct = bpTarget ? Math.round((facturado / bpTarget) * 100) : null;
        const monthIdx = new Date().getMonth() + 1;
        const pacePct = Math.round((monthIdx / 12) * 100);
        const paceDelta = facturaPct != null ? facturaPct - pacePct : null;
        const paceOk = paceDelta != null ? paceDelta >= 0 : null;
        return (
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, minmax(0, 1fr))', gap: 16, paddingBottom: 4 }}>
            {/* KPI Pipeline */}
            <div style={{ borderLeft: '3px solid var(--dd-primary-600, #3859D0)', paddingLeft: 12 }}>
              <div style={{ font: 'var(--dgd-caption)', color: 'var(--dgd-fg-3)', textTransform: 'uppercase', letterSpacing: '0.08em', fontWeight: 700, marginBottom: 4 }}>
                Pipeline total
              </div>
              <div style={{ font: 'var(--dgd-h2)', color: 'var(--dgd-fg-1)', fontWeight: 700, letterSpacing: '-0.01em', fontFamily: 'var(--dgd-font-mono)' }}>
                {fmtE(totalValue)}
                <span style={{ fontSize: 12, color: 'var(--dgd-fg-3)', marginLeft: 10, fontWeight: 500, fontFamily: 'inherit' }}>· {totalOps} OPs</span>
              </div>
            </div>
            {/* KPI Facturação */}
            <div style={{ borderLeft: `3px solid ${paceOk === false ? 'var(--dgd-red-700)' : paceOk ? 'var(--dgd-green-700)' : 'var(--dgd-border-2)'}`, paddingLeft: 12 }}>
              <div style={{ font: 'var(--dgd-caption)', color: 'var(--dgd-fg-3)', textTransform: 'uppercase', letterSpacing: '0.08em', fontWeight: 700, marginBottom: 4, display: 'flex', alignItems: 'center', gap: 8 }}>
                Facturação YTD vs objectivo
                {paceDelta != null && (
                  <span style={{
                    padding: '2px 7px', borderRadius: 999,
                    background: `color-mix(in oklch, ${paceOk ? 'var(--dgd-green-700)' : 'var(--dgd-red-700)'} 14%, transparent)`,
                    color: paceOk ? 'var(--dgd-green-700)' : 'var(--dgd-red-700)',
                    fontSize: 10, fontWeight: 700, letterSpacing: '0.04em', textTransform: 'none',
                  }}>
                    {paceOk ? '↑' : '↓'} {Math.abs(paceDelta)}pp vs pace
                  </span>
                )}
                {isLive && (
                  <span style={{ fontSize: 9.5, color: 'var(--dgd-fg-3)', fontWeight: 400 }}>meta BP em falta</span>
                )}
              </div>
              <div style={{ font: 'var(--dgd-h2)', color: 'var(--dgd-fg-1)', fontWeight: 700, letterSpacing: '-0.01em', fontFamily: 'var(--dgd-font-mono)' }}>
                {fmtE(facturado)}
                <span style={{ fontSize: 12, color: 'var(--dgd-fg-3)', marginLeft: 10, fontWeight: 500, fontFamily: 'inherit' }}>/ {bpTarget ? fmtE(bpTarget) : '****'} ({facturaPct != null ? `${facturaPct}%` : '****'})</span>
              </div>
              {/* Progress bar facturação vs target */}
              <div style={{ marginTop: 6, height: 4, borderRadius: 2, background: 'var(--dgd-grey-200, #ECEEF4)', overflow: 'hidden', position: 'relative' }}>
                <div style={{
                  width: `${Math.min(100, facturaPct)}%`, height: '100%',
                  background: paceOk ? 'var(--dgd-green-700)' : 'var(--dgd-red-700)',
                }} />
                {/* Pace marker (linha vertical) */}
                <div style={{
                  position: 'absolute', top: -2, bottom: -2, left: `${pacePct}%`,
                  width: 2, background: 'var(--dgd-fg-1, #28293D)', opacity: 0.5,
                }} title={`Pace ${pacePct}% (mês ${monthIdx}/12)`} />
              </div>
            </div>
          </div>
        );
      })()}

      {/* Chart */}
      <div style={{ display: 'grid', gridTemplateColumns: '32px 1fr', gap: 4, position: 'relative' }}>
        {/* Y-axis labels */}
        <div style={{ position: 'relative', height: CHART_H + CHART_PAD_TOP }}>
          {yTicks.map((t, i) => (
            <div key={i} style={{
              position: 'absolute', right: 6,
              top: CHART_PAD_TOP + (i / (yTicks.length - 1)) * CHART_H - 6,
              fontSize: 9.5, color: 'var(--dgd-fg-3)', fontFamily: 'var(--dgd-font-mono)',
            }}>{t}</div>
          ))}
        </div>

        {/* Bars + gridlines */}
        <div style={{ position: 'relative', height: CHART_H + CHART_PAD_TOP }}>
          {/* dashed gridlines */}
          {yTicks.map((_, i) => (
            <div key={i} style={{
              position: 'absolute', left: 0, right: 0,
              top: CHART_PAD_TOP + (i / (yTicks.length - 1)) * CHART_H,
              borderTop: '1px dashed var(--dgd-border-2)', height: 0,
            }} />
          ))}

          {/* Bars */}
          <div style={{
            position: 'absolute', inset: 0,
            display: 'grid', gridTemplateColumns: `repeat(${stages.length}, 1fr)`,
            gap: 8, paddingTop: CHART_PAD_TOP,
          }}>
            {stages.map((s) => {
              const heightPx = (s.count / yTop) * CHART_H;
              const isActive = s.id === activeId;
              return (
                <div key={s.id}
                     onMouseEnter={() => setHover(s.id)}
                     onMouseLeave={() => setHover(null)}
                     onClick={() => onNav && onNav('bp', s.sub)}
                     style={{
                       position: 'relative',
                       display: 'flex', alignItems: 'flex-end', justifyContent: 'center',
                       cursor: 'pointer',
                     }}>
                  {/* Tooltip */}
                  {isActive && (
                    <div style={{
                      position: 'absolute',
                      bottom: heightPx + 8,
                      left: '50%', transform: 'translateX(-50%)',
                      background: 'var(--dgd-fg-1, #28293D)',
                      color: '#fff',
                      padding: '8px 12px',
                      borderRadius: 'var(--dgd-radius-sm)',
                      fontSize: 10.5, fontWeight: 600,
                      whiteSpace: 'nowrap',
                      fontFamily: 'var(--dgd-font-mono)',
                      boxShadow: '0 4px 14px rgba(40,41,61,0.22)',
                      zIndex: 2,
                      lineHeight: 1.5,
                    }}>
                      <div>{s.count} OPs{s.value ? ` · ${fmtEuro(s.value)}` : ''}</div>
                      {s.budget > 0 && (() => {
                        const delta = s.value - s.budget;
                        const pct = Math.round((s.value / s.budget) * 100);
                        const ok = delta >= 0;
                        return (
                          <div style={{ fontSize: 9.5, opacity: 0.85, marginTop: 2 }}>
                            Budget: {fmtEuro(s.budget)} · <span style={{ color: ok ? '#7ED957' : '#FF6B73' }}>{ok ? '+' : ''}{fmtEuro(delta)} ({pct}%)</span>
                          </div>
                        );
                      })()}
                      <div style={{
                        position: 'absolute', left: '50%', bottom: -4,
                        transform: 'translateX(-50%) rotate(45deg)',
                        width: 8, height: 8,
                        background: 'var(--dgd-fg-1, #28293D)',
                      }} />
                    </div>
                  )}
                  <div style={{
                    width: '60%', maxWidth: 38,
                    height: heightPx,
                    background: s.id === 'FM_WON'
                      ? (isActive ? 'var(--dgd-green-700)' : 'color-mix(in oklch, var(--dgd-green-700) 25%, transparent)')
                      : isActive
                        ? PRIMARY
                        : `linear-gradient(180deg, ${PRIMARY_SOFT} 0%, color-mix(in oklch, var(--dd-primary-600, #3859D0) 6%, transparent) 100%)`,
                    borderTopLeftRadius: 6, borderTopRightRadius: 6,
                    transition: 'background 150ms ease-out',
                  }} />
                </div>
              );
            })}
          </div>
        </div>
      </div>

      {/* X-axis labels */}
      <div style={{ display: 'grid', gridTemplateColumns: '32px 1fr', gap: 4 }}>
        <div />
        <div style={{ display: 'grid', gridTemplateColumns: `repeat(${stages.length}, 1fr)`, gap: 8 }}>
          {stages.map((s) => {
            const isActive = s.id === activeId;
            const hasBudget = s.budget > 0;
            const ok = hasBudget ? s.value >= s.budget : null;
            const fmtCompact = (n) => n >= 1000000 ? `€${(n/1000000).toFixed(2)}M` : `€${Math.round(n/1000)}k`;
            return (
              <div key={s.id} style={{ textAlign: 'center', minWidth: 0 }}>
                <div style={{
                  fontSize: 11, fontWeight: 700,
                  color: isActive ? PRIMARY : 'var(--dgd-fg-1)',
                  fontFamily: 'var(--dgd-font-mono)',
                  lineHeight: 1.2,
                }}>{s.label}</div>
                <div style={{
                  fontSize: 9.5,
                  color: 'var(--dgd-fg-3)',
                  marginTop: 2, lineHeight: 1.2,
                  whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                }}>{s.sub === '__WON__' ? 'Closed Won' : s.sub}</div>
                {s.value > 0 && !hasBudget && (
                  <div style={{ marginTop: 4, fontSize: 9.5, fontWeight: 700, fontFamily: 'var(--dgd-font-mono)', color: s.id === 'FM_WON' ? 'var(--dgd-green-700)' : (isActive ? PRIMARY : 'var(--dgd-fg-2)') }}>
                    {fmtCompact(s.value)}
                  </div>
                )}
                {hasBudget && (
                  <div style={{
                    marginTop: 6, display: 'flex', flexDirection: 'column', gap: 2, alignItems: 'center',
                  }}>
                    <div style={{
                      fontSize: 10, fontWeight: 700,
                      color: ok ? 'var(--dgd-green-700)' : 'var(--dgd-red-700)',
                      fontFamily: 'var(--dgd-font-mono)', lineHeight: 1,
                    }}>
                      {fmtCompact(s.value)}
                    </div>
                    <div style={{
                      fontSize: 8.5, color: 'var(--dgd-fg-3)',
                      fontFamily: 'var(--dgd-font-mono)', lineHeight: 1,
                    }}>
                      / {fmtCompact(s.budget)}
                    </div>
                    {/* mini progress bar valor vs budget */}
                    <div style={{
                      width: '80%', height: 3, borderRadius: 2,
                      background: 'var(--dgd-grey-200, #ECEEF4)',
                      overflow: 'hidden', marginTop: 2,
                    }}>
                      <div style={{
                        width: `${Math.min(100, Math.round((s.value / s.budget) * 100))}%`,
                        height: '100%',
                        background: ok ? 'var(--dgd-green-700)' : 'var(--dgd-red-700)',
                      }} />
                    </div>
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
};

// ============================================================================
// BRIEFING — 4 cards (Foco semana · Digi proactiva · Mensagens · BP performance)
// ============================================================================
const briefingCardStyle = {
  background: 'var(--dgd-bg-surface)',
  borderRadius: 'var(--dgd-radius-xl)',
  boxShadow: 'var(--dgd-shadow-card)',
  padding: 20,
  display: 'flex', flexDirection: 'column', gap: 14,
  transition: 'box-shadow 200ms ease-out, transform 200ms ease-out',
};

const BriefingHeader = ({ icon, label, badge, badgeColor }) => (
  <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
    <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
      <Icon name={icon} size={14} style={{ color: 'var(--dd-primary-600)' }} />
      <div style={{ font: 'var(--dgd-caption)', color: 'var(--dgd-fg-3)', textTransform: 'uppercase', letterSpacing: '0.08em', fontWeight: 700 }}>{label}</div>
    </div>
    {badge && (
      <div style={{
        padding: '3px 9px', borderRadius: 999,
        background: `color-mix(in oklch, ${badgeColor} 14%, transparent)`,
        color: badgeColor, fontSize: 10.5, fontWeight: 700, letterSpacing: '0.04em',
      }}>{badge}</div>
    )}
  </div>
);

// --- Foco da semana ---
const BRIEFING_FOCO = [
  { tag: 'RECOMPRA', tagColor: 'var(--dgd-purple-700)', titulo: 'Olimpo Lda · €95k', sub: 'Mimaki UJV200 · padrão 30d aponta esta semana', deadline: 'até 6ª', navTo: 'carteira' },
  { tag: 'OP PARADA', tagColor: 'var(--dgd-pumpkin-700)', titulo: 'Vinyl Lab · €110k', sub: 'Proposta enviada há 33d · re-engagement urgente', deadline: '4ª', navTo: 'carteira' },
  { tag: 'PROSPECÇÃO', tagColor: 'var(--dgd-green-700)', titulo: 'Madrid · 2 leads quentes', sub: 'Impresión Madrid (9/10) + ColorLab (8/10) · agendar', deadline: '5ª', navTo: 'prospeccao' },
];

const BriefingFoco = ({ onNav }) => (
  <div style={briefingCardStyle}>
    <BriefingHeader icon="target" label="Foco esta semana" badge="3 prioridades" badgeColor="var(--dd-primary-600)" />
    <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
      {BRIEFING_FOCO.map((f, i) => (
        <div key={i} onClick={() => f.navTo && onNav && onNav(f.navTo)}
             style={{
               display: 'grid', gridTemplateColumns: 'auto 1fr auto', gap: 10, alignItems: 'center',
               padding: '10px 12px', borderRadius: 'var(--dgd-radius-md)',
               background: 'var(--dgd-bg-app)', cursor: f.navTo ? 'pointer' : 'default',
               transition: 'background 150ms ease-out',
             }}
             onMouseEnter={(e) => { if (f.navTo) e.currentTarget.style.background = 'var(--dgd-grey-200)'; }}
             onMouseLeave={(e) => { if (f.navTo) e.currentTarget.style.background = 'var(--dgd-bg-app)'; }}>
          <div style={{
            padding: '3px 8px', borderRadius: 'var(--dgd-radius-xs)',
            background: `color-mix(in oklch, ${f.tagColor} 14%, transparent)`,
            color: f.tagColor, fontSize: 9.5, fontWeight: 700, letterSpacing: '0.05em',
          }}>{f.tag}</div>
          <div style={{ minWidth: 0 }}>
            <div style={{ font: 'var(--dgd-body-md)', color: 'var(--dgd-fg-1)', fontWeight: 600 }}>{f.titulo}</div>
            <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-2)' }}>{f.sub}</div>
          </div>
          <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', fontFamily: 'var(--dgd-font-mono)', fontWeight: 700, letterSpacing: '0.04em' }}>{f.deadline}</div>
        </div>
      ))}
    </div>
  </div>
);

// --- Digi a trabalhar ---
const BRIEFING_DIGI = [
  { mark: '✓', color: 'var(--dgd-green-700)', text: 'Qualifiquei 12 leads ES esta noite — 3 com score 9+' },
  { mark: '↻', color: 'var(--dgd-primary-500)', text: 'A enriquecer 47 contactos LinkedIn (Apollo + GMB)' },
  { mark: '✓', color: 'var(--dgd-green-700)', text: 'Follow-up enviado a 4 propostas >30d — Vinyl Lab confirmou reunião 3ª' },
  { mark: '📨', color: 'var(--dgd-pumpkin-700)', text: '3 mensagens WhatsApp aguardam tua resposta' },
];

const BriefingDigi = ({ onNav }) => (
  <div style={briefingCardStyle}>
    <BriefingHeader icon="sparkle" label="Digi a trabalhar" badge="ao vivo" badgeColor="var(--dgd-green-700)" />
    <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
      {BRIEFING_DIGI.map((d, i) => (
        <div key={i} style={{ display: 'grid', gridTemplateColumns: '24px 1fr', gap: 10, alignItems: 'flex-start', padding: '8px 0', borderTop: i === 0 ? 'none' : '1px solid var(--dgd-border-2)' }}>
          <div style={{
            width: 22, height: 22, borderRadius: '50%',
            background: `color-mix(in oklch, ${d.color} 16%, transparent)`,
            color: d.color, display: 'grid', placeItems: 'center',
            fontSize: 12, fontWeight: 700,
          }}>{d.mark}</div>
          <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-1)', lineHeight: 1.5 }}>{d.text}</div>
        </div>
      ))}
    </div>
    <button onClick={() => onNav && onNav('digi')} className="dgd-btn dgd-btn-ghost" style={{ alignSelf: 'flex-start', padding: '6px 12px' }}>
      Ver fluxo completo →
    </button>
  </div>
);

// --- Mensagens clientes ---
const BRIEFING_MSGS = [
  { who: 'João Afonso', empresa: 'Olimpo Lda', avatar: 'JA', avatarBg: 'oklch(0.58 0.14 28)', preview: 'Podemos falar hoje? Roland mandou proposta…', tempo: 'há 14h', urgencia: 'red' },
  { who: 'Ricardo Dias', empresa: 'Grupo Siena', avatar: 'RD', avatarBg: 'oklch(0.56 0.14 300)', preview: 'Confirmo encomenda 6.450 € · obrigado 👍', tempo: 'há 2h', urgencia: 'green' },
  { who: 'Tiago Moreira', empresa: 'BannerMax', avatar: 'TM', avatarBg: 'oklch(0.58 0.12 230)', preview: 'Tens o datasheet do PPE100 em PDF?', tempo: 'há 4h', urgencia: 'blue' },
];

const BriefingMensagens = ({ onNav }) => (
  <div style={briefingCardStyle}>
    <BriefingHeader icon="message-square" label="Mensagens clientes" badge="3 novas" badgeColor="var(--dgd-pumpkin-700)" />
    <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
      {BRIEFING_MSGS.map((m, i) => {
        const dotColor = m.urgencia === 'red' ? 'var(--dgd-red-700)' : m.urgencia === 'green' ? 'var(--dgd-green-700)' : 'var(--dd-primary-600)';
        return (
          <div key={i} onClick={() => onNav && onNav('clientes')}
               style={{
                 display: 'grid', gridTemplateColumns: '32px 1fr auto', gap: 10, alignItems: 'center',
                 padding: '8px 4px', cursor: 'pointer',
                 borderTop: i === 0 ? 'none' : '1px solid var(--dgd-border-2)',
                 transition: 'background 150ms ease-out',
               }}
               onMouseEnter={(e) => { e.currentTarget.style.background = 'var(--dgd-bg-app)'; }}
               onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }}>
            <div style={{
              width: 32, height: 32, borderRadius: '50%',
              background: m.avatarBg, color: '#fff',
              display: 'grid', placeItems: 'center',
              fontSize: 11, fontWeight: 700, letterSpacing: '0.02em',
            }}>{m.avatar}</div>
            <div style={{ minWidth: 0 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                <span style={{ width: 6, height: 6, borderRadius: '50%', background: dotColor, flexShrink: 0 }} />
                <div style={{ font: 'var(--dgd-body-md)', color: 'var(--dgd-fg-1)', fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                  {m.who} <span style={{ color: 'var(--dgd-fg-3)', fontWeight: 400 }}>· {m.empresa}</span>
                </div>
              </div>
              <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-2)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                {m.preview}
              </div>
            </div>
            <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', fontFamily: 'var(--dgd-font-mono)', flexShrink: 0 }}>{m.tempo}</div>
          </div>
        );
      })}
    </div>
    <button onClick={() => onNav && onNav('clientes')} className="dgd-btn dgd-btn-ghost" style={{ alignSelf: 'flex-start', padding: '6px 12px' }}>
      Abrir Inbox →
    </button>
  </div>
);

// --- Funil Pipeline Gestor (stages reais Primavera: 10→20→50→65→80→90→91→92→99→WON) ---
// budget = valor mínimo que cada stage deve ter para BP anual €895k bater (cobertura 4x conservadora)
const BRIEFING_FUNNEL = [
  { id: 'S10',  label: '10',  sub: 'Lead',              count: 62, value: 0,       budget: 0,       color: 'var(--dgd-primary-500)' },
  { id: 'S20',  label: '20',  sub: 'Demo. Interesse',   count: 48, value: 0,       budget: 0,       color: 'var(--dgd-primary-500)' },
  { id: 'S50',  label: '50',  sub: 'Evento',            count: 31, value: 0,       budget: 0,       color: 'var(--dgd-primary-600)' },
  { id: 'S65',  label: '65',  sub: 'Demo',              count: 24, value: 1240000, budget: 1100000, color: 'var(--dgd-primary-700)' },
  { id: 'S80',  label: '80',  sub: 'Aguarda Decisão',   count: 18, value: 998155,  budget: 850000,  color: 'var(--dgd-pumpkin-500)' },
  { id: 'S90',  label: '90',  sub: 'Dec. Financeira',   count: 9,  value: 612300,  budget: 600000,  color: 'var(--dgd-pumpkin-500)' },
  { id: 'S91',  label: '91',  sub: 'Pedido',            count: 6,  value: 388420,  budget: 400000,  color: 'var(--dgd-pumpkin-700)' },
  { id: 'S92',  label: '92',  sub: 'Aprovado Fin.',     count: 4,  value: 246800,  budget: 250000,  color: 'var(--dgd-pumpkin-700)' },
  { id: 'S99',  label: '99',  sub: 'Ag. Cobrança',      count: 3,  value: 53800,   budget: 120000,  color: 'var(--dgd-green-700)' },
  { id: 'WON',  label: 'WON', sub: 'Closed Won',        count: 5,  value: 188755,  budget: 298000,  color: 'var(--dgd-green-700)' },
];
const DASH_BP_TARGET = 895000;
const DASH_BP_REALIZADO = 188755;
const DASH_BP_DESVIO = DASH_BP_REALIZADO - DASH_BP_TARGET;

const BriefingBP = ({ onNav }) => {
  const maxCount = Math.max(...BRIEFING_FUNNEL.map(s => s.count));
  const stages = BRIEFING_FUNNEL;
  const last = stages[stages.length - 1];
  const first = stages[0];
  const globalConv = Math.round((last.count / first.count) * 100);
  const bpPct = Math.round((DASH_BP_REALIZADO / DASH_BP_TARGET) * 100);

  return (
    <div style={briefingCardStyle}>
      <BriefingHeader icon="bar-chart" label="Funil · Pipeline Gestor" badge={`${globalConv}% SPIN→Vendas`} badgeColor="var(--dgd-green-700)" />

      {/* Funil horizontal */}
      <div style={{ display: 'flex', alignItems: 'stretch', gap: 4, paddingTop: 4 }}>
        {stages.map((s, i) => {
          const heightPct = 30 + ((s.count / maxCount) * 70);
          const prev = i > 0 ? stages[i - 1] : null;
          const conv = prev ? Math.round((s.count / prev.count) * 100) : null;
          const convColor = conv == null ? 'transparent' : conv >= 90 ? 'var(--dgd-green-700)' : conv >= 70 ? 'var(--dgd-pumpkin-700)' : 'var(--dgd-red-700)';
          return (
            <React.Fragment key={s.id}>
              {conv != null && (
                <div style={{
                  display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center',
                  fontSize: 9, fontWeight: 700, color: convColor, fontFamily: 'var(--dgd-font-mono)',
                  letterSpacing: '0.04em', minWidth: 24,
                }}>
                  <div>→</div>
                  <div>{conv}%</div>
                </div>
              )}
              <div style={{
                flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'stretch',
                minWidth: 0,
              }}>
                <div style={{
                  height: 78, display: 'flex', alignItems: 'flex-end', justifyContent: 'center',
                }}>
                  <div style={{
                    width: '100%', height: `${heightPct}%`,
                    background: s.color, borderRadius: 'var(--dgd-radius-sm)',
                    display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
                    color: '#fff', boxShadow: '0 1px 3px rgba(40,41,61,0.16)', padding: '4px 2px',
                  }}>
                    <div style={{ fontSize: 14, fontWeight: 800, lineHeight: 1, fontFamily: 'var(--dgd-font-mono)' }}>
                      {s.count}
                    </div>
                    <div style={{ fontSize: 8, fontWeight: 600, opacity: 0.85, marginTop: 2 }}>
                      OPs
                    </div>
                  </div>
                </div>
                <div style={{ textAlign: 'center', marginTop: 6, minWidth: 0 }}>
                  <div style={{ fontSize: 9.5, fontWeight: 700, color: s.color, fontFamily: 'var(--dgd-font-mono)', letterSpacing: '0.04em', lineHeight: 1.2, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                    {s.label}
                  </div>
                  {s.value != null && (
                    <div style={{ fontSize: 9.5, fontWeight: 600, color: 'var(--dgd-fg-1)', fontFamily: 'var(--dgd-font-mono)', marginTop: 2, lineHeight: 1.2 }}>
                      {s.value >= 1000000 ? `€${(s.value/1000000).toFixed(2)}M` : `€${Math.round(s.value/1000)}k`}
                    </div>
                  )}
                  <div style={{ fontSize: 9, color: 'var(--dgd-fg-3)', lineHeight: 1.2, marginTop: 1, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                    {s.sub}
                  </div>
                </div>
              </div>
            </React.Fragment>
          );
        })}
      </div>

      {/* BP comparativo */}
      <div style={{
        display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8,
        padding: '10px 0', borderTop: '1px solid var(--dgd-border-2)',
      }}>
        <div>
          <div style={{ fontSize: 9.5, color: 'var(--dgd-fg-3)', fontFamily: 'var(--dgd-font-mono)', letterSpacing: '0.04em', textTransform: 'uppercase' }}>BP target</div>
          <div style={{ fontSize: 14, fontWeight: 700, color: 'var(--dgd-fg-1)', fontFamily: 'var(--dgd-font-mono)' }}>{fmtEuro(DASH_BP_TARGET)}</div>
        </div>
        <div>
          <div style={{ fontSize: 9.5, color: 'var(--dgd-fg-3)', fontFamily: 'var(--dgd-font-mono)', letterSpacing: '0.04em', textTransform: 'uppercase' }}>Realizado</div>
          <div style={{ fontSize: 14, fontWeight: 700, color: 'var(--dgd-fg-1)', fontFamily: 'var(--dgd-font-mono)' }}>{fmtEuro(DASH_BP_REALIZADO)} <span style={{ fontSize: 10, color: 'var(--dgd-fg-3)' }}>({bpPct}%)</span></div>
        </div>
        <div>
          <div style={{ fontSize: 9.5, color: 'var(--dgd-fg-3)', fontFamily: 'var(--dgd-font-mono)', letterSpacing: '0.04em', textTransform: 'uppercase' }}>Desvio</div>
          <div style={{ fontSize: 14, fontWeight: 700, color: 'var(--dgd-red-700)', fontFamily: 'var(--dgd-font-mono)' }}>{fmtEuro(DASH_BP_DESVIO)}</div>
        </div>
      </div>

      <div style={{
        background: 'color-mix(in oklch, var(--dd-primary-600) 8%, transparent)',
        border: '1px solid color-mix(in oklch, var(--dd-primary-600) 24%, transparent)',
        borderRadius: 'var(--dgd-radius-md)',
        padding: 12,
        display: 'flex', gap: 10, alignItems: 'flex-start',
      }}>
        <Icon name="sparkle" size={14} style={{ color: 'var(--dd-primary-600)', marginTop: 2, flexShrink: 0 }} />
        <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-1)', lineHeight: 1.5 }}>
          <strong style={{ color: 'var(--dd-primary-600)' }}>Sugestão Digi:</strong> bottleneck em <strong>80 Aguarda Decisão → 90 Dec. Financeira</strong> (50%). 9 OPs paradas valem <strong>€612k</strong>; desbloquear top 5 fecha o gap BP.
        </div>
      </div>
      <button onClick={() => onNav && onNav('bp')} className="dgd-btn dgd-btn-ghost" style={{ alignSelf: 'flex-start', padding: '6px 12px' }}>
        Ver pipeline completo →
      </button>
    </div>
  );
};

// --- Wrapper Briefing 2x2 ---
const DashBriefing = ({ onNav }) => (
  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(380px, 1fr))', gap: 18 }}>
    <BriefingFoco onNav={onNav} />
    <BriefingDigi onNav={onNav} />
    <BriefingMensagens onNav={onNav} />
    <BriefingBP onNav={onNav} />
  </div>
);

// ============================================================================
// CARTÃO BP DESTACADO
// ============================================================================
const DashBPCard = ({ onNav }) => {
  const desvios = [-55130, -106390, 5201, -226706, -556706, -881706, -1206706, -1426706, -1751706, -2081706, -2411706, -2736706];
  return (
    <div onClick={() => onNav && onNav('bp')}
         style={{
           background: 'var(--dgd-bg-surface)',
           borderRadius: 'var(--dgd-radius-xl)',
           boxShadow: 'var(--dgd-shadow-card)',
           borderLeft: '3px solid var(--dgd-red-700)',
           padding: 24, cursor: 'pointer',
           display: 'grid', gridTemplateColumns: '1.4fr 1fr 1fr auto', alignItems: 'center', gap: 24,
           transition: 'box-shadow 150ms ease-out, transform 150ms ease-out',
         }}
         onMouseEnter={(e) => { e.currentTarget.style.boxShadow = 'var(--dgd-shadow-regular)'; e.currentTarget.style.transform = 'translateY(-1px)'; }}
         onMouseLeave={(e) => { e.currentTarget.style.boxShadow = 'var(--dgd-shadow-card)'; e.currentTarget.style.transform = 'translateY(0)'; }}
    >
      <div>
        <div style={{ font: 'var(--dgd-caption)', color: 'var(--dgd-fg-3)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 6 }}>Business Plan 2026</div>
        <div style={{ font: 'var(--dgd-h3)', color: 'var(--dgd-fg-1)', marginBottom: 4 }}>Desvio crítico</div>
        <div style={{ font: 'var(--dgd-body-md)', color: 'var(--dgd-fg-2)' }}>
          Vendas <strong style={{ color: 'var(--dgd-fg-1)' }}>€923k</strong> vs BP <strong style={{ color: 'var(--dgd-fg-1)' }}>€1,15M</strong> YTD
        </div>
      </div>
      <div>
        <div style={{ font: 'var(--dgd-caption)', color: 'var(--dgd-fg-3)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 6 }}>Gap projectado</div>
        <div style={{ font: 'var(--dgd-h2)', color: 'var(--dgd-red-700)', letterSpacing: '-0.01em' }}>−€2,7M</div>
        <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-3)', marginTop: 2 }}>+€342k/mês p/ recuperar</div>
      </div>
      <div>
        <div style={{ font: 'var(--dgd-caption)', color: 'var(--dgd-fg-3)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 8 }}>Desvio acumulado</div>
        <Sparkline values={desvios} color="var(--dgd-red-500)" w={140} h={32} />
        <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', fontFamily: 'var(--dgd-font-mono)', marginTop: 4, letterSpacing: '0.06em' }}>JAN → DEZ</div>
      </div>
      <button className="dgd-btn dgd-btn-primary" style={{ whiteSpace: 'nowrap' }}>Ver plano →</button>
    </div>
  );
};

// ============================================================================
// 3 ACÇÕES URGENTES HOJE
// ============================================================================
const DASH_ACCOES = [
  {
    kind: 'carteira', kindLabel: 'CARTEIRA', kindColor: 'var(--dgd-primary-500)',
    titulo: 'João Afonso · Olimpo Lda',
    body: 'Respondeu no WhatsApp ontem às 22:47. Disse que reuniu com a Roland hoje. Urgente reagir antes de fecharem.',
    metric: '€95k', metricLabel: 'potencial',
    cta: 'Abrir conversa', navTo: 'clientes',
  },
  {
    kind: 'ops', kindLabel: 'OP · PRIMAVERA', kindColor: 'var(--dgd-pumpkin-700)',
    titulo: 'Vinyl Lab · Proposta Mimaki UJV200',
    body: 'Proposta enviada há 33 dias sem resposta. Valor €110k · fase "proposta enviada". Follow-up automático sugerido.',
    metric: '33d', metricLabel: 'parado',
    cta: 'Fazer follow-up', navTo: 'carteira',
  },
  {
    kind: 'prospec', kindLabel: 'PROSPECÇÃO ES', kindColor: 'var(--dgd-green-700)',
    titulo: 'Impresión Madrid Digital · Score 9/10',
    body: 'Lead detectado hoje. CNAE 1812, 28 colaboradores, comprou HP Latex há 4 anos. Match directo Mimaki UJV200.',
    metric: '€120k', metricLabel: 'potencial',
    cta: 'Ver lead', navTo: 'prospeccao',
  },
  {
    kind: 'finance', kindLabel: 'FINANCEIRO', kindColor: 'var(--dgd-red-700)',
    titulo: 'Gráfica Central, Lda · €12.400 em dívida',
    body: 'Factura vencida há 67 dias. Patrícia Mota já enviou 2 lembretes. Antes de abordares recompra, tens de resolver.',
    metric: '67d', metricLabel: 'em atraso',
    cta: 'Ver aging',
  },
  {
    kind: 'sat', kindLabel: 'SAT', kindColor: 'var(--dgd-purple-700)',
    titulo: 'Rótulos Norte · Mimaki UJV200 em down',
    body: 'Máquina parada há 2 dias. Técnico agendado para amanhã. Falar com o cliente antes que abra novo fornecedor.',
    metric: '2d', metricLabel: 'down',
    cta: 'Ver ticket',
  },
];

const DashAccoes = ({ onNav }) => {
  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, marginBottom: 12 }}>
        <h3 style={{ margin: 0, font: 'var(--dgd-h4)', letterSpacing: '-0.01em', color: 'var(--dgd-fg-1)' }}>Acções urgentes hoje</h3>
        <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-3)' }}>5 alertas que não podem passar para amanhã</div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(264px, 1fr))', gap: 16 }}>
        {DASH_ACCOES.map((a, i) => (
          <div key={i}
               onClick={() => a.navTo && onNav && onNav(a.navTo)}
               style={{
                 background: 'var(--dgd-bg-surface)',
                 borderRadius: 'var(--dgd-radius-xl)',
                 boxShadow: 'var(--dgd-shadow-card)',
                 borderTop: `3px solid ${a.kindColor}`,
                 padding: 18, cursor: a.navTo ? 'pointer' : 'default',
                 transition: 'box-shadow 150ms ease-out, transform 150ms ease-out',
                 display: 'flex', flexDirection: 'column', gap: 10,
               }}
               onMouseEnter={(e) => { if (a.navTo) { e.currentTarget.style.boxShadow = 'var(--dgd-shadow-regular)'; e.currentTarget.style.transform = 'translateY(-1px)'; } }}
               onMouseLeave={(e) => { if (a.navTo) { e.currentTarget.style.boxShadow = 'var(--dgd-shadow-card)'; e.currentTarget.style.transform = 'translateY(0)'; } }}
          >
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
              <div style={{ font: 'var(--dgd-caption)', color: a.kindColor, textTransform: 'uppercase', letterSpacing: '0.08em', fontWeight: 700 }}>
                {a.kindLabel}
              </div>
              <div style={{ textAlign: 'right' }}>
                <div style={{ font: 'var(--dgd-h4)', color: a.kindColor, lineHeight: 1 }}>{a.metric}</div>
                <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', textTransform: 'uppercase', letterSpacing: '0.06em', marginTop: 2 }}>{a.metricLabel}</div>
              </div>
            </div>
            <div style={{ font: 'var(--dgd-label)', color: 'var(--dgd-fg-1)' }}>{a.titulo}</div>
            <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-2)', flex: 1 }}>{a.body}</div>
            <button className="dgd-btn dgd-btn-ghost" style={{ alignSelf: 'flex-start', padding: '6px 12px' }}>{a.cta} →</button>
          </div>
        ))}
      </div>
    </div>
  );
};

// ============================================================================
// PIPELINE OPs — Gestor (stages reais FM) com fallback mock
// ============================================================================

// FM stage name → display meta
const FM_STAGE_META = {
  'LEAD':          { label: 'Lead',          color: 'var(--dgd-primary-500)', accent: 'var(--dgd-primary-700)' },
  'INTERESSE':     { label: 'Interesse',      color: 'var(--dgd-primary-500)', accent: 'var(--dgd-primary-700)' },
  'AG FINANCEIRO': { label: 'Ag. Financeiro', color: 'var(--dgd-pumpkin-500)', accent: 'var(--dgd-pumpkin-700)' },
  'AG DECISAO':    { label: 'Ag. Decisão',    color: 'var(--dgd-pumpkin-500)', accent: 'var(--dgd-pumpkin-700)' },
  'EVENTO':        { label: 'Evento',         color: 'var(--dgd-pumpkin-700)', accent: 'var(--dgd-pumpkin-700)' },
  'DEMO':          { label: 'Demo',           color: 'var(--dgd-green-500)',   accent: 'var(--dgd-green-700)'   },
};

const fmtEuro = (n) => {
  if (n >= 1000000) return `€${(n/1000000).toFixed(2)}M`;
  if (n >= 1000) return `€${(n/1000).toFixed(0)}k`;
  return `€${n}`;
};

const DASH_PIPELINE_STAGES = [
  {
    id: 65, label: 'Qualificação', sub: 'stage 65',
    count: 18, value: 612000, color: 'var(--dgd-primary-500)', accent: 'var(--dgd-primary-700)',
    deltaYTY: '+12%',
    items: [
      { cliente: 'Olimpo Lda', maquina: 'Mimaki UJV200', valor: 95000, dias: 4 },
      { cliente: 'Vinyl Lab', maquina: 'Mimaki UJF-7151', valor: 152000, dias: 6 },
      { cliente: 'Print Center Madrid', maquina: 'Mimaki TxF300', valor: 48000, dias: 9 },
    ],
  },
  {
    id: 80, label: 'Proposta enviada', sub: 'stage 80',
    count: 17, value: 743000, color: 'var(--dgd-pumpkin-500)', accent: 'var(--dgd-pumpkin-700)',
    paradas: 12, deltaYTY: '−4%',
    items: [
      { cliente: 'Vinyl Lab', maquina: 'Mimaki UJV200', valor: 110000, dias: 33, alerta: true },
      { cliente: 'Rótulos Norte', maquina: 'Mimaki TxF300', valor: 64000, dias: 41, alerta: true },
      { cliente: 'Impresión Madrid Digital', maquina: 'Mimaki UJV200', valor: 120000, dias: 12 },
    ],
  },
  {
    id: 90, label: 'Negociação final', sub: 'stage 90',
    count: 12, value: 380000, color: 'var(--dgd-green-500)', accent: 'var(--dgd-green-700)',
    deltaYTY: '+27%',
    items: [
      { cliente: 'Etiquetas Centro', maquina: 'Mimaki UJV330', valor: 175000, dias: 3 },
      { cliente: 'Gráfica Mar', maquina: 'Mimaki UJF-7151', valor: 82000, dias: 7 },
      { cliente: 'Lab Print SL', maquina: 'Mimaki UCJV330', valor: 64000, dias: 5 },
    ],
  },
];

const DashPipelineOPs = ({ onNav, viewMode, pipelineData }) => {
  const isLive = !!pipelineData?.byStage;

  // Build top-3 stages from live data; fall back to mock
  const stages = React.useMemo(() => {
    if (!isLive) return DASH_PIPELINE_STAGES;
    return pipelineData.byStage
      .filter(s => s.stage && s.stage !== 'Desconhecido' && s.value > 0)
      .sort((a, b) => b.value - a.value)
      .slice(0, 3)
      .map(s => {
        const meta = FM_STAGE_META[s.stage] || { label: s.stage, color: 'var(--dgd-primary-500)', accent: 'var(--dgd-primary-700)' };
        const stageRecords = (pipelineData.records || [])
          .filter(r => r.Stage_Name === s.stage)
          .sort((a, b) => (parseFloat(b.Produto_Valor_K) || 0) - (parseFloat(a.Produto_Valor_K) || 0))
          .slice(0, 3)
          .map(r => ({
            cliente: r.Entidade_Nome || '—',
            maquina: r.Produto_Name  || '—',
            valor:   Math.round((parseFloat(r.Produto_Valor_K) || 0) * 1000),
            dias:    parseInt(r.Age) || null,
          }));
        return { id: s.stage, label: meta.label, sub: s.stage.toLowerCase(), count: s.count, value: s.value, color: meta.color, accent: meta.accent, items: stageRecords };
      });
  }, [pipelineData]);

  const total = stages.reduce((s, x) => s + x.value, 0);
  const totalCount = stages.reduce((s, x) => s + x.count, 0);
  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 12, marginBottom: 12, flexWrap: 'wrap' }}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, flexWrap: 'wrap' }}>
          <h3 style={{ margin: 0, font: 'var(--dgd-h4)', letterSpacing: '-0.01em', color: 'var(--dgd-fg-1)' }}>Pipeline · Gestor</h3>
          <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-3)' }}>
            {totalCount} OPs · {fmtEuro(total)} · {isLive ? <span style={{ color: 'var(--dgd-green-700)', fontWeight: 600 }}>dados reais</span> : (viewMode === 'yty' ? 'comparado a 2025' : 'YTD')}
          </div>
        </div>
        <button onClick={() => onNav && onNav('carteira')}
                className="dgd-btn dgd-btn-ghost" style={{ padding: '6px 12px' }}>
          Ver tudo →
        </button>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))', gap: 16 }}>
        {DASH_PIPELINE_STAGES.map((s) => (
          <div key={s.id}
               onClick={() => onNav && onNav('carteira')}
               style={{
                 background: 'var(--dgd-bg-surface)',
                 borderRadius: 'var(--dgd-radius-xl)',
                 boxShadow: 'var(--dgd-shadow-card)',
                 borderTop: `3px solid ${s.color}`,
                 padding: 18, cursor: 'pointer',
                 transition: 'box-shadow 150ms ease-out, transform 150ms ease-out',
                 display: 'flex', flexDirection: 'column', gap: 12,
               }}
               onMouseEnter={(e) => { e.currentTarget.style.boxShadow = 'var(--dgd-shadow-regular)'; e.currentTarget.style.transform = 'translateY(-1px)'; }}
               onMouseLeave={(e) => { e.currentTarget.style.boxShadow = 'var(--dgd-shadow-card)'; e.currentTarget.style.transform = 'translateY(0)'; }}
          >
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 8 }}>
              <div style={{ minWidth: 0 }}>
                <div style={{ font: 'var(--dgd-caption)', color: s.accent, textTransform: 'uppercase', letterSpacing: '0.08em', fontWeight: 700 }}>
                  {s.sub}
                </div>
                <div style={{ font: 'var(--dgd-h3)', color: 'var(--dgd-fg-1)', marginTop: 4 }}>{s.label}</div>
              </div>
              <div style={{ textAlign: 'right', flexShrink: 0 }}>
                <div style={{ font: 'var(--dgd-h2)', color: 'var(--dgd-fg-1)', letterSpacing: '-0.01em' }}>{fmtEuro(s.value)}</div>
                <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>
                  {s.count} OPs{viewMode === 'yty' ? ` · ${s.deltaYTY}` : ''}
                </div>
              </div>
            </div>
            {s.paradas && (
              <div style={{
                font: 'var(--dgd-body-sm)', color: 'var(--dgd-pumpkin-700)',
                background: 'color-mix(in oklch, var(--dgd-pumpkin-500) 12%, transparent)',
                padding: '6px 10px', borderRadius: 'var(--dgd-radius-sm)',
                fontWeight: 600,
              }}>
                <strong>{s.paradas}</strong> paradas &gt;30 dias
              </div>
            )}
            <div style={{ borderTop: '1px solid var(--dgd-border-2)', paddingTop: 10, display: 'flex', flexDirection: 'column', gap: 8 }}>
              {s.items.map((it, i) => (
                <div key={i} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 10 }}>
                  <div style={{ minWidth: 0, flex: 1 }}>
                    <div style={{ font: 'var(--dgd-body-md)', color: 'var(--dgd-fg-1)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                      {it.cliente}
                    </div>
                    <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)' }}>{it.maquina}</div>
                  </div>
                  <div style={{ textAlign: 'right', flexShrink: 0 }}>
                    <div style={{ font: 'var(--dgd-body-md)', color: 'var(--dgd-fg-1)', fontWeight: 600, fontFamily: 'var(--dgd-font-mono)' }}>
                      {fmtEuro(it.valor)}
                    </div>
                    {(it.dias != null || it.alerta) && (
                      <div style={{ font: 'var(--dgd-body-xs)', color: it.alerta ? 'var(--dgd-pumpkin-700)' : 'var(--dgd-fg-3)', fontWeight: it.alerta ? 600 : 400 }}>
                        {it.dias != null ? `${it.dias}d` : '—'}
                      </div>
                    )}
                  </div>
                </div>
              ))}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

// ============================================================================
// PULSE — 4 stat cards UKO-style (número grande + sparkline tintada + label)
// ============================================================================
const UkoStatCard = ({ value, label, sub, sparkValues, color, tintColor, onClick }) => {
  const tint = tintColor || `color-mix(in oklch, ${color} 14%, var(--dgd-bg-surface))`;
  return (
    <div onClick={onClick}
         style={{
           background: 'var(--dgd-bg-surface)',
           borderRadius: 'var(--dgd-radius-xl)',
           boxShadow: 'var(--dgd-shadow-card)',
           padding: 22, cursor: onClick ? 'pointer' : 'default',
           transition: 'box-shadow 200ms ease-out, transform 200ms ease-out',
           display: 'flex', flexDirection: 'column', gap: 14,
         }}
         onMouseEnter={(e) => { if (onClick) { e.currentTarget.style.boxShadow = 'var(--dgd-shadow-regular)'; e.currentTarget.style.transform = 'translateY(-2px)'; } }}
         onMouseLeave={(e) => { if (onClick) { e.currentTarget.style.boxShadow = 'var(--dgd-shadow-card)'; e.currentTarget.style.transform = 'translateY(0)'; } }}
    >
      <div style={{
        fontFamily: 'var(--dgd-font-sans)',
        fontWeight: 800,
        fontSize: 36,
        lineHeight: 1,
        letterSpacing: '-0.02em',
        color: 'var(--dgd-fg-1)',
      }}>
        {value}
      </div>
      <div style={{
        background: tint,
        borderRadius: 'var(--dgd-radius-lg)',
        padding: '14px 14px 10px',
        display: 'flex', justifyContent: 'center', alignItems: 'center',
        height: 64,
      }}>
        <Sparkline values={sparkValues} color={color} w={160} h={40} showLast={false} />
      </div>
      <div>
        <div style={{ fontFamily: 'var(--dgd-font-sans)', fontWeight: 700, fontSize: 14, color: color }}>{label}</div>
        {sub && <div style={{ fontFamily: 'var(--dgd-font-text)', fontSize: 12, color: 'var(--dgd-fg-3)', marginTop: 2 }}>{sub}</div>}
      </div>
    </div>
  );
};

const DashPulse = ({ onNav, pipelineData }) => {
  const liveOps    = pipelineData?.total  ?? null;
  const liveActive = pipelineData?.active ?? null;
  const opsValue   = liveOps != null ? (pipelineData.byStage || []).reduce((s, x) => s + x.value, 0) : null;

  // Carteira: entidades únicas com OPs activas derivadas do pipeline
  const liveCarteira = React.useMemo(() => {
    if (!pipelineData?.records?.length) return null;
    const active = pipelineData.records.filter(r => r.Status !== 'LOST' && r.Stage_Name);
    const entities = new Set(active.map(r => r.ID_Entidade || r.Entidade_Nome).filter(Boolean));
    const risco = new Set(
      pipelineData.records
        .filter(r => r.Status === 'LOST')
        .map(r => r.ID_Entidade || r.Entidade_Nome)
        .filter(k => !entities.has(k))
    ).size;
    return { total: entities.size, risco };
  }, [pipelineData]);

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, marginBottom: 14 }}>
        <h3 style={{ margin: 0, font: 'var(--dgd-h3)', letterSpacing: '-0.01em', color: 'var(--dgd-fg-1)' }}>Pulse</h3>
        <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-3)' }}>estado de cada secção · click para abrir</div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(232px, 1fr))', gap: 18 }}>
        <UkoStatCard
          value="****"
          label="Clientes"
          sub="integração CRM pendente"
          sparkValues={[2, 3, 1, 4, 2, 3, 5, 3]}
          color="var(--dd-primary-600)"
          onClick={() => onNav && onNav('clientes')}
        />
        <UkoStatCard
          value={liveCarteira ? String(liveCarteira.total) : '****'}
          label="Carteira · Gestor"
          sub={liveCarteira ? `entidades com OPs activas · dados reais` : 'integração pendente'}
          sparkValues={liveCarteira
            ? [liveCarteira.total * 0.6, liveCarteira.total * 0.7, liveCarteira.total * 0.8, liveCarteira.total * 0.9, liveCarteira.total, liveCarteira.total, liveCarteira.total, liveCarteira.total]
            : [42, 44, 43, 45, 47, 46, 47, 47]}
          color="var(--dgd-pumpkin-700)"
          onClick={() => onNav && onNav('carteira')}
        />
        <UkoStatCard
          value="****"
          label="Prospecção ES"
          sub="integração pendente"
          sparkValues={[120, 180, 240, 320, 410, 480, 540, 571]}
          color="var(--dgd-green-700)"
          onClick={() => onNav && onNav('prospeccao')}
        />
        <UkoStatCard
          value={liveOps != null ? String(liveOps) : '****'}
          label="OPs · Gestor"
          sub={liveOps != null ? `${liveActive} activas · dados reais` : 'integração pendente'}
          sparkValues={opsValue != null
            ? [opsValue * 0.6, opsValue * 0.7, opsValue * 0.8, opsValue * 0.85, opsValue * 0.9, opsValue * 0.95, opsValue, opsValue]
            : [1200000, 1350000, 1420000, 1580000, 1650000, 1700000, 1730000, 1730000]}
          color="var(--dgd-purple-700)"
          onClick={() => onNav && onNav('bp')}
        />
      </div>
    </div>
  );
};

// ============================================================================
// INPUT DIGI — pergunta proactiva
// ============================================================================
const DashDigiInput = ({ onOpenChat }) => {
  const chips = [
    'Quem devo ligar hoje?',
    'Mostra OPs paradas',
    'Simula UJF-7151 p/ Olimpo',
    'Leads quentes em Barcelona',
  ];
  return (
    <div style={{
      background: 'var(--dgd-bg-surface)',
      borderRadius: 'var(--dgd-radius-xl)',
      boxShadow: 'var(--dgd-shadow-card)',
      padding: 18,
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>
        <span style={{
          display: 'inline-flex', alignItems: 'center', gap: 6,
          padding: '4px 10px', borderRadius: 'var(--dgd-radius-pill)',
          background: 'var(--dgd-primary-50)', color: 'var(--dgd-primary-700)',
          fontSize: 11, fontWeight: 700, letterSpacing: '0.04em',
        }}>
          <span style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--dgd-primary-500)' }} />
          Digi
        </span>
        <div style={{ font: 'var(--dgd-body-md)', color: 'var(--dgd-fg-2)' }}>
          Pergunta-me o que quiseres sobre carteira, leads, OPs, simulações…
        </div>
      </div>
      <div onClick={() => onOpenChat && onOpenChat()}
           style={{
             background: 'var(--dgd-bg-app)', border: '1px solid var(--dgd-border-1)',
             borderRadius: 'var(--dgd-radius-md)',
             padding: '12px 16px', cursor: 'text',
             display: 'flex', alignItems: 'center', gap: 10,
             font: 'var(--dgd-body-md)', color: 'var(--dgd-fg-3)',
           }}>
        <span>Pergunta à Digi…</span>
        <span style={{
          marginLeft: 'auto', font: 'var(--dgd-body-xs)', fontFamily: 'var(--dgd-font-mono)',
          color: 'var(--dgd-fg-3)', background: 'var(--dgd-bg-surface)',
          padding: '2px 8px', borderRadius: 'var(--dgd-radius-xs)',
          border: '1px solid var(--dgd-border-1)',
        }}>⌘ K</span>
      </div>
      <div style={{ display: 'flex', gap: 8, marginTop: 12, flexWrap: 'wrap' }}>
        {chips.map((c, i) => (
          <button key={i} onClick={() => onOpenChat && onOpenChat(c)}
                  style={{
                    background: 'var(--dgd-bg-surface)', border: '1px solid var(--dgd-border-1)',
                    borderRadius: 'var(--dgd-radius-pill)',
                    padding: '6px 12px',
                    font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-2)',
                    cursor: 'pointer', transition: 'all 150ms ease-out',
                  }}
                  onMouseEnter={(e) => { e.currentTarget.style.borderColor = 'var(--dgd-primary-500)'; e.currentTarget.style.color = 'var(--dgd-fg-1)'; e.currentTarget.style.background = 'var(--dgd-primary-50)'; }}
                  onMouseLeave={(e) => { e.currentTarget.style.borderColor = 'var(--dgd-border-1)'; e.currentTarget.style.color = 'var(--dgd-fg-2)'; e.currentTarget.style.background = 'var(--dgd-bg-surface)'; }}
          >
            {c}
          </button>
        ))}
      </div>
    </div>
  );
};

// ============================================================================
// SAT · INSTALAÇÕES DA SEMANA — calendar strip (oportunidade comercial pré/pós)
// ============================================================================
const DASH_SAT_SEMANA = [
  { dia: 'SEG', data: 28, mes: 'Abr', items: [] },
  { dia: 'TER', data: 29, mes: 'Abr', items: [
    { cliente: 'Pixel Print Lisboa', maquina: 'Mimaki UJV200', tecnico: 'Mário S.', tipo: 'instalação' },
  ]},
  { dia: 'QUA', data: 30, mes: 'Abr', items: [
    { cliente: 'Etiquetas Centro', maquina: 'Mimaki TxF300', tecnico: 'Carlos R.', tipo: 'manutenção' },
  ], hoje: true },
  { dia: 'QUI', data: 1, mes: 'Mai', items: [
    { cliente: 'Rótulos Norte', maquina: 'Mimaki UJV200', tecnico: 'Mário S.', tipo: 'reparação' },
    { cliente: 'Print Lab Madrid', maquina: 'Mimaki UJF-7151', tecnico: 'Pedro F.', tipo: 'instalação' },
  ]},
  { dia: 'SEX', data: 2, mes: 'Mai', items: [
    { cliente: 'Vinyl Lab', maquina: 'Mimaki UCJV330', tecnico: 'Carlos R.', tipo: 'instalação' },
  ]},
  { dia: 'SAB', data: 3, mes: 'Mai', items: [] },
  { dia: 'DOM', data: 4, mes: 'Mai', items: [] },
];

const SAT_TIPO_COLOR = {
  'instalação': 'var(--dgd-green-700)',
  'manutenção': 'var(--dgd-primary-700)',
  'reparação': 'var(--dgd-pumpkin-700)',
};

const DashSATSemana = ({ onNav }) => {
  const totalSemana = DASH_SAT_SEMANA.reduce((acc, d) => acc + d.items.length, 0);
  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 12, marginBottom: 12, flexWrap: 'wrap' }}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, flexWrap: 'wrap' }}>
          <h3 style={{ margin: 0, font: 'var(--dgd-h4)', letterSpacing: '-0.01em', color: 'var(--dgd-fg-1)' }}>SAT · Instalações da semana</h3>
          <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-3)' }}>{totalSemana} intervenções · oportunidade comercial pré/pós</div>
        </div>
      </div>
      <div style={{
        background: 'var(--dgd-bg-surface)',
        borderRadius: 'var(--dgd-radius-xl)',
        boxShadow: 'var(--dgd-shadow-card)',
        padding: 18,
      }}>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 10 }}>
          {DASH_SAT_SEMANA.map((d, i) => (
            <div key={i} style={{
              borderRadius: 'var(--dgd-radius-md)',
              border: d.hoje ? '1px solid var(--dgd-primary-500)' : '1px solid var(--dgd-border-2)',
              background: d.hoje ? 'var(--dgd-primary-50)' : 'var(--dgd-bg-app)',
              padding: 10,
              minHeight: 140,
              display: 'flex', flexDirection: 'column', gap: 8,
            }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
                <div style={{ font: 'var(--dgd-caption)', color: d.hoje ? 'var(--dgd-primary-700)' : 'var(--dgd-fg-3)', letterSpacing: '0.06em', fontWeight: 700 }}>
                  {d.dia}
                </div>
                <div style={{ font: 'var(--dgd-body-md)', color: d.hoje ? 'var(--dgd-primary-700)' : 'var(--dgd-fg-1)', fontWeight: 700 }}>
                  {d.data}
                </div>
              </div>
              {d.items.length === 0 ? (
                <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', fontStyle: 'italic', marginTop: 4 }}>—</div>
              ) : (
                <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                  {d.items.map((it, j) => (
                    <div key={j}
                         onClick={(e) => { e.stopPropagation(); onNav && onNav('carteira'); }}
                         style={{
                           background: 'var(--dgd-bg-surface)',
                           border: '1px solid var(--dgd-border-2)',
                           borderLeft: `3px solid ${SAT_TIPO_COLOR[it.tipo] || 'var(--dgd-primary-500)'}`,
                           borderRadius: 'var(--dgd-radius-sm)',
                           padding: '6px 8px',
                           cursor: 'pointer',
                           transition: 'box-shadow 150ms ease-out',
                         }}
                         onMouseEnter={(e) => { e.currentTarget.style.boxShadow = 'var(--dgd-shadow-1)'; }}
                         onMouseLeave={(e) => { e.currentTarget.style.boxShadow = 'none'; }}>
                      <div style={{ font: 'var(--dgd-body-xs)', color: SAT_TIPO_COLOR[it.tipo] || 'var(--dgd-primary-700)', textTransform: 'uppercase', letterSpacing: '0.06em', fontWeight: 700 }}>
                        {it.tipo}
                      </div>
                      <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-1)', fontWeight: 600, lineHeight: 1.2, marginTop: 2 }}>
                        {it.cliente}
                      </div>
                      <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', marginTop: 2 }}>
                        {it.maquina}
                      </div>
                      <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', fontStyle: 'italic' }}>
                        {it.tecnico}
                      </div>
                    </div>
                  ))}
                </div>
              )}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};

// ============================================================================
// MAPA IBÉRIA — Leaflet · clientes Mimaki PT + ES
// ============================================================================
const DASH_MAP_CLIENTES = [
  { nome: 'Olimpo Lda', cidade: 'Lisboa', lat: 38.7223, lng: -9.1393, estado: 'risco', maquinas: 2, ultimaCompra: '2023' },
  { nome: 'Pixel Print Lisboa', cidade: 'Lisboa', lat: 38.7423, lng: -9.1693, estado: 'activo', maquinas: 1, ultimaCompra: '2025' },
  { nome: 'Etiquetas Centro', cidade: 'Coimbra', lat: 40.2056, lng: -8.4196, estado: 'oportunidade', maquinas: 1, ultimaCompra: '2024' },
  { nome: 'Vinyl Lab', cidade: 'Porto', lat: 41.1579, lng: -8.6291, estado: 'activo', maquinas: 3, ultimaCompra: '2025' },
  { nome: 'Rótulos Norte', cidade: 'Braga', lat: 41.5454, lng: -8.4265, estado: 'risco', maquinas: 1, ultimaCompra: '2022' },
  { nome: 'Gráfica Mar', cidade: 'Faro', lat: 37.0194, lng: -7.9304, estado: 'activo', maquinas: 2, ultimaCompra: '2024' },
  { nome: 'Aveiro Print', cidade: 'Aveiro', lat: 40.6405, lng: -8.6538, estado: 'oportunidade', maquinas: 1, ultimaCompra: '2023' },
  { nome: 'Print Center Madrid', cidade: 'Madrid', lat: 40.4168, lng: -3.7038, estado: 'oportunidade', maquinas: 0, ultimaCompra: null },
  { nome: 'Impresión Madrid Digital', cidade: 'Madrid', lat: 40.4368, lng: -3.6738, estado: 'oportunidade', maquinas: 0, ultimaCompra: null },
  { nome: 'Lab Print SL', cidade: 'Barcelona', lat: 41.3851, lng: 2.1734, estado: 'activo', maquinas: 1, ultimaCompra: '2025' },
  { nome: 'Print Lab Madrid', cidade: 'Madrid', lat: 40.4268, lng: -3.6938, estado: 'activo', maquinas: 1, ultimaCompra: '2024' },
  { nome: 'Valencia Vinyl', cidade: 'Valencia', lat: 39.4699, lng: -0.3763, estado: 'oportunidade', maquinas: 0, ultimaCompra: null },
  { nome: 'Sevilla Gráfica', cidade: 'Sevilla', lat: 37.3891, lng: -5.9845, estado: 'activo', maquinas: 1, ultimaCompra: '2024' },
  { nome: 'Bilbao Print', cidade: 'Bilbao', lat: 43.2630, lng: -2.9350, estado: 'risco', maquinas: 1, ultimaCompra: '2022' },
  { nome: 'Zaragoza Digital', cidade: 'Zaragoza', lat: 41.6488, lng: -0.8891, estado: 'oportunidade', maquinas: 0, ultimaCompra: null },
];

const DASH_MAP_COLORS = {
  activo:       '#1F8A52',
  risco:        '#B53B3B',
  oportunidade: '#E96D17',
};

const DashMapaIberia = () => {
  const ref = React.useRef(null);
  const stateRef = React.useRef(null);
  const [filtro, setFiltro] = React.useState('todos');

  React.useEffect(() => {
    if (!ref.current || typeof window.L === 'undefined') return;
    if (stateRef.current) return;
    const map = window.L.map(ref.current, {
      center: [40.0, -4.5],
      zoom: 6,
      scrollWheelZoom: false,
      zoomControl: true,
    });
    window.L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
      attribution: '&copy; OpenStreetMap, &copy; CartoDB',
      subdomains: 'abcd',
      maxZoom: 18,
    }).addTo(map);
    stateRef.current = { map, markers: [] };
    return () => {
      if (stateRef.current && stateRef.current.map) {
        stateRef.current.map.remove();
        stateRef.current = null;
      }
    };
  }, []);

  React.useEffect(() => {
    if (!stateRef.current || !stateRef.current.map) return;
    const { map } = stateRef.current;
    stateRef.current.markers.forEach((m) => map.removeLayer(m));
    stateRef.current.markers = [];
    const list = filtro === 'todos' ? DASH_MAP_CLIENTES : DASH_MAP_CLIENTES.filter((c) => c.estado === filtro);
    list.forEach((c) => {
      const color = DASH_MAP_COLORS[c.estado] || '#3859D0';
      const radius = 7 + Math.min(c.maquinas, 3) * 3;
      const m = window.L.circleMarker([c.lat, c.lng], {
        radius,
        fillColor: color,
        color: '#FFFFFF',
        weight: 2,
        opacity: 1,
        fillOpacity: 0.85,
      }).addTo(map);
      const tip = `<strong>${c.nome}</strong><br>${c.cidade} · ${c.maquinas} máquina(s)<br><em style="text-transform:uppercase;letter-spacing:0.06em;color:${color}">${c.estado}</em>${c.ultimaCompra ? ' · última ' + c.ultimaCompra : ''}`;
      m.bindTooltip(tip, { direction: 'top', offset: [0, -4] });
      stateRef.current.markers.push(m);
    });
  }, [filtro]);

  const totals = DASH_MAP_CLIENTES.reduce((acc, c) => { acc[c.estado] = (acc[c.estado] || 0) + 1; return acc; }, {});
  const filtros = [
    { id: 'todos',        label: 'Todos',        count: DASH_MAP_CLIENTES.length, color: 'var(--dgd-fg-2)' },
    { id: 'activo',       label: 'Activos',      count: totals.activo || 0,       color: 'var(--dgd-green-700)' },
    { id: 'risco',        label: 'Em risco',     count: totals.risco || 0,        color: 'var(--dgd-red-700)' },
    { id: 'oportunidade', label: 'Oportunidade', count: totals.oportunidade || 0, color: 'var(--dgd-pumpkin-700)' },
  ];

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 12, marginBottom: 12, flexWrap: 'wrap' }}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, flexWrap: 'wrap' }}>
          <h3 style={{ margin: 0, font: 'var(--dgd-h4)', letterSpacing: '-0.01em', color: 'var(--dgd-fg-1)' }}>Mapa Ibéria · clientes Mimaki</h3>
          <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-3)' }}>{DASH_MAP_CLIENTES.length} pontos · PT + ES</div>
        </div>
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
          {filtros.map((f) => (
            <button key={f.id}
                    onClick={() => setFiltro(f.id)}
                    style={{
                      background: filtro === f.id ? 'var(--dgd-bg-surface)' : 'transparent',
                      border: `1px solid ${filtro === f.id ? f.color : 'var(--dgd-border-1)'}`,
                      color: filtro === f.id ? f.color : 'var(--dgd-fg-2)',
                      borderRadius: 'var(--dgd-radius-pill)',
                      padding: '4px 10px',
                      font: 'var(--dgd-body-xs)',
                      fontWeight: 600,
                      cursor: 'pointer',
                      transition: 'all 150ms ease-out',
                    }}>
              {f.label} <span style={{ opacity: 0.6, marginLeft: 4 }}>{f.count}</span>
            </button>
          ))}
        </div>
      </div>
      <div style={{
        background: 'var(--dgd-bg-surface)',
        borderRadius: 'var(--dgd-radius-xl)',
        boxShadow: 'var(--dgd-shadow-card)',
        padding: 6,
        overflow: 'hidden',
      }}>
        <div ref={ref} style={{
          height: 380,
          width: '100%',
          borderRadius: 'var(--dgd-radius-lg)',
          overflow: 'hidden',
        }} />
      </div>
    </div>
  );
};

// ============================================================================
// HISTÓRICO INSTALAÇÕES — Ficheiro Nanda · máquinas vendidas
// ============================================================================
const DASH_NANDA_HISTORICO = [
  { ano: 2025, cliente: 'Vinyl Lab',           cidade: 'Porto',     maquina: 'Mimaki UJV200',   valor: 95000,  estado: 'instalada', meses: 3 },
  { ano: 2025, cliente: 'Pixel Print Lisboa',  cidade: 'Lisboa',    maquina: 'Mimaki UJV200',   valor: 88000,  estado: 'instalada', meses: 1 },
  { ano: 2025, cliente: 'Lab Print SL',        cidade: 'Barcelona', maquina: 'Mimaki UCJV330',  valor: 64000,  estado: 'pendente',  meses: 0 },
  { ano: 2024, cliente: 'Etiquetas Centro',    cidade: 'Coimbra',   maquina: 'Mimaki TxF300',   valor: 72000,  estado: 'instalada', meses: 6 },
  { ano: 2024, cliente: 'Gráfica Mar',         cidade: 'Faro',      maquina: 'Mimaki UJF-7151', valor: 48000,  estado: 'instalada', meses: 9 },
  { ano: 2024, cliente: 'Print Lab Madrid',    cidade: 'Madrid',    maquina: 'Mimaki UJF-7151', valor: 52000,  estado: 'instalada', meses: 8 },
  { ano: 2024, cliente: 'Sevilla Gráfica',     cidade: 'Sevilla',   maquina: 'Mimaki UJV200',   valor: 110000, estado: 'instalada', meses: 11 },
  { ano: 2023, cliente: 'Olimpo Lda',          cidade: 'Lisboa',    maquina: 'Mimaki UJV150',   valor: 78000,  estado: 'instalada', meses: 18 },
];

const NANDA_ESTADO_COLOR = {
  instalada: 'var(--dgd-green-700)',
  pendente:  'var(--dgd-pumpkin-700)',
};

const DashHistoricoNanda = ({ onNav }) => {
  const [anoFiltro, setAnoFiltro] = React.useState('todos');
  const anos = ['todos', 2025, 2024, 2023];
  const filtered = anoFiltro === 'todos' ? DASH_NANDA_HISTORICO : DASH_NANDA_HISTORICO.filter((h) => h.ano === anoFiltro);
  const total = filtered.reduce((s, x) => s + x.valor, 0);
  const thStyle = { padding: '10px 14px', textAlign: 'left', font: 'var(--dgd-caption)', color: 'var(--dgd-fg-3)', textTransform: 'uppercase', letterSpacing: '0.06em', fontWeight: 700 };
  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 12, marginBottom: 12, flexWrap: 'wrap' }}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, flexWrap: 'wrap' }}>
          <h3 style={{ margin: 0, font: 'var(--dgd-h4)', letterSpacing: '-0.01em', color: 'var(--dgd-fg-1)' }}>Histórico instalações · Nanda</h3>
          <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-3)' }}>{filtered.length} máquinas · {fmtEuro(total)}</div>
        </div>
        <div style={{ display: 'flex', gap: 6 }}>
          {anos.map((a) => (
            <button key={a}
                    onClick={() => setAnoFiltro(a)}
                    style={{
                      background: anoFiltro === a ? 'var(--dgd-primary-50)' : 'transparent',
                      border: `1px solid ${anoFiltro === a ? 'var(--dgd-primary-500)' : 'var(--dgd-border-1)'}`,
                      color: anoFiltro === a ? 'var(--dgd-primary-700)' : 'var(--dgd-fg-2)',
                      borderRadius: 'var(--dgd-radius-pill)',
                      padding: '4px 12px',
                      font: 'var(--dgd-body-xs)',
                      fontWeight: 600,
                      cursor: 'pointer',
                    }}>
              {a === 'todos' ? 'Todos' : a}
            </button>
          ))}
        </div>
      </div>
      <div style={{
        background: 'var(--dgd-bg-surface)',
        borderRadius: 'var(--dgd-radius-xl)',
        boxShadow: 'var(--dgd-shadow-card)',
        overflow: 'hidden',
      }}>
        <table style={{ width: '100%', borderCollapse: 'collapse', font: 'var(--dgd-body-md)' }}>
          <thead>
            <tr style={{ background: 'var(--dgd-bg-app)' }}>
              <th style={thStyle}>Ano</th>
              <th style={thStyle}>Cliente</th>
              <th style={thStyle}>Máquina</th>
              <th style={{ ...thStyle, textAlign: 'right' }}>Valor</th>
              <th style={{ ...thStyle, textAlign: 'right' }}>Idade</th>
              <th style={thStyle}>Estado</th>
            </tr>
          </thead>
          <tbody>
            {filtered.map((h, i) => (
              <tr key={i}
                  onClick={() => onNav && onNav('carteira')}
                  style={{ cursor: 'pointer', borderTop: '1px solid var(--dgd-border-2)', transition: 'background 150ms ease-out' }}
                  onMouseEnter={(e) => { e.currentTarget.style.background = 'var(--dgd-bg-app)'; }}
                  onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }}>
                <td style={{ padding: '10px 14px', font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-3)', fontFamily: 'var(--dgd-font-mono)' }}>{h.ano}</td>
                <td style={{ padding: '10px 14px', color: 'var(--dgd-fg-1)', fontWeight: 600 }}>
                  {h.cliente}
                  <span style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', marginLeft: 6, fontWeight: 400 }}>· {h.cidade}</span>
                </td>
                <td style={{ padding: '10px 14px', color: 'var(--dgd-fg-2)' }}>{h.maquina}</td>
                <td style={{ padding: '10px 14px', textAlign: 'right', color: 'var(--dgd-fg-1)', fontWeight: 600, fontFamily: 'var(--dgd-font-mono)' }}>{fmtEuro(h.valor)}</td>
                <td style={{ padding: '10px 14px', textAlign: 'right', color: 'var(--dgd-fg-3)', font: 'var(--dgd-body-sm)' }}>
                  {h.meses === 0 ? '—' : `${h.meses}m`}
                </td>
                <td style={{ padding: '10px 14px' }}>
                  <span style={{
                    display: 'inline-flex', alignItems: 'center', gap: 5,
                    background: `color-mix(in oklch, ${NANDA_ESTADO_COLOR[h.estado]} 12%, transparent)`,
                    color: NANDA_ESTADO_COLOR[h.estado],
                    padding: '2px 8px', borderRadius: 'var(--dgd-radius-pill)',
                    font: 'var(--dgd-body-xs)', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.04em',
                  }}>
                    {h.estado}
                  </span>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
};

// ============================================================================
// BUDGET MERCADO EQUIPAMENTOS — InfoSource · quota Mimaki por categoria
// ============================================================================
const DASH_BUDGET_INFOSOURCE = [
  { categoria: 'UV LED',      mercadoPT: 4200000, quotaMimaki: 0.32, deltaQuota: '+3pp' },
  { categoria: 'Sublimação',  mercadoPT: 2100000, quotaMimaki: 0.28, deltaQuota: '+1pp' },
  { categoria: 'Solvent',     mercadoPT: 1800000, quotaMimaki: 0.18, deltaQuota: '−2pp' },
  { categoria: 'Latex',       mercadoPT: 1500000, quotaMimaki: 0.04, deltaQuota: '0pp'  },
];

const DashBudgetInfoSource = () => {
  const totalMercado = DASH_BUDGET_INFOSOURCE.reduce((s, x) => s + x.mercadoPT, 0);
  const totalMimaki = DASH_BUDGET_INFOSOURCE.reduce((s, x) => s + x.mercadoPT * x.quotaMimaki, 0);
  const maxMercado = Math.max(...DASH_BUDGET_INFOSOURCE.map((x) => x.mercadoPT));
  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, marginBottom: 12, flexWrap: 'wrap' }}>
        <h3 style={{ margin: 0, font: 'var(--dgd-h4)', letterSpacing: '-0.01em', color: 'var(--dgd-fg-1)' }}>Budget mercado equipamentos · InfoSource</h3>
        <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-3)' }}>
          mercado PT {fmtEuro(totalMercado)} · quota Mimaki {fmtEuro(totalMimaki)} ({Math.round(totalMimaki/totalMercado*100)}%)
        </div>
      </div>
      <div style={{
        background: 'var(--dgd-bg-surface)',
        borderRadius: 'var(--dgd-radius-xl)',
        boxShadow: 'var(--dgd-shadow-card)',
        padding: 18,
        display: 'flex', flexDirection: 'column', gap: 16,
      }}>
        {DASH_BUDGET_INFOSOURCE.map((c, i) => {
          const valorMimaki = c.mercadoPT * c.quotaMimaki;
          const pct = c.quotaMimaki * 100;
          const barWidth = (c.mercadoPT / maxMercado) * 100;
          const positivo = c.deltaQuota.startsWith('+');
          const negativo = c.deltaQuota.startsWith('−');
          return (
            <div key={i}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 12, marginBottom: 6, flexWrap: 'wrap' }}>
                <div style={{ display: 'flex', alignItems: 'baseline', gap: 10 }}>
                  <div style={{ font: 'var(--dgd-label)', color: 'var(--dgd-fg-1)', minWidth: 110 }}>{c.categoria}</div>
                  <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)' }}>mercado {fmtEuro(c.mercadoPT)}</div>
                </div>
                <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
                  <div style={{ font: 'var(--dgd-body-md)', color: 'var(--dgd-fg-1)', fontWeight: 700, fontFamily: 'var(--dgd-font-mono)' }}>
                    {pct.toFixed(0)}%
                  </div>
                  <div style={{
                    font: 'var(--dgd-body-xs)', fontWeight: 700,
                    color: positivo ? 'var(--dgd-green-700)' : negativo ? 'var(--dgd-red-700)' : 'var(--dgd-fg-3)',
                  }}>
                    {c.deltaQuota}
                  </div>
                </div>
              </div>
              <div style={{ position: 'relative', height: 12, background: 'var(--dgd-bg-app)', borderRadius: 'var(--dgd-radius-pill)', overflow: 'hidden' }}>
                <div style={{
                  position: 'absolute', left: 0, top: 0, bottom: 0,
                  width: `${barWidth}%`,
                  background: 'var(--dgd-primary-100)',
                  borderRadius: 'var(--dgd-radius-pill)',
                }} />
                <div style={{
                  position: 'absolute', left: 0, top: 0, bottom: 0,
                  width: `${barWidth * c.quotaMimaki}%`,
                  background: 'var(--dgd-primary-500)',
                  borderRadius: 'var(--dgd-radius-pill)',
                }} />
              </div>
              <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', marginTop: 6, fontFamily: 'var(--dgd-font-mono)', letterSpacing: '0.02em' }}>
                Mimaki {fmtEuro(valorMimaki)} · disponível {fmtEuro(c.mercadoPT - valorMimaki)}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
};

// ============================================================================
// GAMIFICATION + SCORING — ranking comerciais Mimaki PT
// ============================================================================
const DASH_GAMIFICATION = [
  { nome: 'Daniel Sousa', avatar: 'DS', vendasYTD: 312000, bpPct: 0.31, conversao: 0.118, leads: 14, score: 92, posicao: 1, voce: true },
  { nome: 'Manuel Costa', avatar: 'MC', vendasYTD: 287000, bpPct: 0.28, conversao: 0.094, leads: 11, score: 84, posicao: 2 },
  { nome: 'Walter Noia',  avatar: 'WN', vendasYTD: 241000, bpPct: 0.22, conversao: 0.103, leads: 18, score: 79, posicao: 3 },
  { nome: 'Hugo Lima',    avatar: 'HL', vendasYTD: 198000, bpPct: 0.18, conversao: 0.087, leads:  9, score: 71, posicao: 4 },
];

const SCORE_COLOR = (score) => {
  if (score >= 85) return 'var(--dgd-green-700)';
  if (score >= 75) return 'var(--dgd-primary-700)';
  if (score >= 65) return 'var(--dgd-pumpkin-700)';
  return 'var(--dgd-red-700)';
};

const DashGamification = ({ viewMode }) => (
  <div>
    <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, marginBottom: 12, flexWrap: 'wrap' }}>
      <h3 style={{ margin: 0, font: 'var(--dgd-h4)', letterSpacing: '-0.01em', color: 'var(--dgd-fg-1)' }}>Ranking comerciais · Mimaki PT</h3>
      <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-3)' }}>{viewMode === 'yty' ? 'vs Abr 2025' : 'YTD'} · score composto (vendas + conversão + leads)</div>
    </div>
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(260px, 1fr))', gap: 16 }}>
      {DASH_GAMIFICATION.map((c, i) => {
        const scoreColor = SCORE_COLOR(c.score);
        return (
          <div key={i} style={{
            background: 'var(--dgd-bg-surface)',
            borderRadius: 'var(--dgd-radius-xl)',
            boxShadow: c.voce ? 'var(--dgd-shadow-regular)' : 'var(--dgd-shadow-card)',
            border: c.voce ? '2px solid var(--dgd-primary-500)' : '1px solid var(--dgd-border-2)',
            padding: 16,
            display: 'flex', flexDirection: 'column', gap: 12,
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
              <div style={{
                width: 44, height: 44, borderRadius: '50%',
                background: c.voce ? 'var(--dgd-primary-500)' : 'var(--dgd-primary-100)',
                color: c.voce ? '#FFFFFF' : 'var(--dgd-primary-700)',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                font: 'var(--dgd-button)', fontSize: 14, fontWeight: 800,
                flexShrink: 0,
              }}>{c.avatar}</div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ font: 'var(--dgd-label)', color: 'var(--dgd-fg-1)' }}>
                  {c.nome}
                  {c.voce && <span style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-primary-700)', marginLeft: 6, fontWeight: 700 }}>· tu</span>}
                </div>
                <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>#{c.posicao} · score {c.score}</div>
              </div>
              <div style={{
                width: 34, height: 34, borderRadius: '50%',
                background: `color-mix(in oklch, ${scoreColor} 15%, transparent)`,
                color: scoreColor,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                font: 'var(--dgd-body-md)', fontWeight: 800, fontFamily: 'var(--dgd-font-mono)',
                flexShrink: 0,
              }}>{c.score}</div>
            </div>
            <div>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 4 }}>
                <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>BP {Math.round(c.bpPct*100)}%</div>
                <div style={{ font: 'var(--dgd-body-md)', color: 'var(--dgd-fg-1)', fontWeight: 600, fontFamily: 'var(--dgd-font-mono)' }}>{fmtEuro(c.vendasYTD)}</div>
              </div>
              <div style={{ height: 6, background: 'var(--dgd-bg-app)', borderRadius: 'var(--dgd-radius-pill)', overflow: 'hidden', position: 'relative' }}>
                <div style={{
                  width: `${Math.min(c.bpPct/0.40*100, 100)}%`,
                  height: '100%',
                  background: c.bpPct >= 0.30 ? 'var(--dgd-green-500)' : c.bpPct >= 0.20 ? 'var(--dgd-pumpkin-500)' : 'var(--dgd-red-500)',
                  borderRadius: 'var(--dgd-radius-pill)',
                }} />
                <div style={{ position: 'absolute', left: '82.5%', top: -2, bottom: -2, width: 1, background: 'var(--dgd-fg-3)', opacity: 0.4 }} />
              </div>
              <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', marginTop: 4 }}>linha esperada YTD: 33%</div>
            </div>
            <div style={{ display: 'flex', gap: 16, borderTop: '1px solid var(--dgd-border-2)', paddingTop: 10 }}>
              <div>
                <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Conversão</div>
                <div style={{ font: 'var(--dgd-body-md)', color: 'var(--dgd-fg-1)', fontWeight: 600 }}>{(c.conversao*100).toFixed(1)}%</div>
              </div>
              <div>
                <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Leads novos</div>
                <div style={{ font: 'var(--dgd-body-md)', color: 'var(--dgd-fg-1)', fontWeight: 600 }}>{c.leads}</div>
              </div>
            </div>
          </div>
        );
      })}
    </div>
  </div>
);

// ============================================================================
// FINANCEIRO PRÉ-FECHO — check Patrícia Mota antes de assinar
// ============================================================================
const DASH_PRE_FECHO = [
  { cliente: 'Etiquetas Centro',    cidade: 'Coimbra',  valor: 175000, score: 'A', divida:    0, dias:  0, pode: true,  nota: 'Score AAA, sem dívida. Pode fechar.' },
  { cliente: 'Vinyl Lab',           cidade: 'Porto',    valor: 110000, score: 'B', divida: 4200, dias: 18, pode: true,  nota: 'Dívida pequena, dentro do prazo. Confirmar com Patrícia antes.' },
  { cliente: 'Gráfica Central, Lda',cidade: 'Setúbal',  valor:  78000, score: 'C', divida:12400, dias: 67, pode: false, nota: 'BLOQUEADO · €12,4k em atraso há 67 dias. Resolver antes de fechar.' },
];

const DashFinanceiroPreFecho = ({ onNav }) => (
  <div>
    <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, marginBottom: 12, flexWrap: 'wrap' }}>
      <h3 style={{ margin: 0, font: 'var(--dgd-h4)', letterSpacing: '-0.01em', color: 'var(--dgd-fg-1)' }}>Pré-fecho · check financeiro</h3>
      <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-3)' }}>{DASH_PRE_FECHO.length} propostas perto de fechar · validar crédito (Patrícia Mota) antes de assinar</div>
    </div>
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))', gap: 16 }}>
      {DASH_PRE_FECHO.map((p, i) => {
        const accent = p.pode ? 'var(--dgd-green-700)' : 'var(--dgd-red-700)';
        return (
          <div key={i} style={{
            background: 'var(--dgd-bg-surface)',
            borderRadius: 'var(--dgd-radius-xl)',
            boxShadow: 'var(--dgd-shadow-card)',
            borderLeft: `3px solid ${accent}`,
            padding: 16,
            display: 'flex', flexDirection: 'column', gap: 10,
          }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 10 }}>
              <div style={{ minWidth: 0 }}>
                <div style={{ font: 'var(--dgd-label)', color: 'var(--dgd-fg-1)' }}>{p.cliente}</div>
                <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)' }}>{p.cidade}</div>
              </div>
              <span style={{
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                width: 28, height: 28, borderRadius: '50%',
                background: `color-mix(in oklch, ${accent} 14%, transparent)`,
                color: accent,
                font: 'var(--dgd-body-md)', fontWeight: 800, fontFamily: 'var(--dgd-font-mono)',
                flexShrink: 0,
              }}>{p.score}</span>
            </div>
            <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12, paddingTop: 8, borderTop: '1px solid var(--dgd-border-2)' }}>
              <div>
                <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Proposta</div>
                <div style={{ font: 'var(--dgd-h4)', color: 'var(--dgd-fg-1)', fontFamily: 'var(--dgd-font-mono)' }}>{fmtEuro(p.valor)}</div>
              </div>
              <div>
                <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Dívida</div>
                <div style={{ font: 'var(--dgd-h4)', color: p.divida > 0 ? (p.dias > 30 ? 'var(--dgd-red-700)' : 'var(--dgd-pumpkin-700)') : 'var(--dgd-fg-1)', fontFamily: 'var(--dgd-font-mono)' }}>
                  {p.divida === 0 ? '—' : fmtEuro(p.divida)}
                </div>
                {p.divida > 0 && (
                  <div style={{ font: 'var(--dgd-body-xs)', color: p.dias > 30 ? 'var(--dgd-red-700)' : 'var(--dgd-fg-3)' }}>{p.dias}d atraso</div>
                )}
              </div>
            </div>
            <div style={{
              font: 'var(--dgd-body-sm)',
              color: p.pode ? 'var(--dgd-fg-2)' : 'var(--dgd-red-700)',
              background: p.pode ? 'var(--dgd-bg-app)' : 'color-mix(in oklch, var(--dgd-red-500) 10%, transparent)',
              padding: '8px 10px', borderRadius: 'var(--dgd-radius-sm)',
              fontWeight: p.pode ? 400 : 600,
            }}>{p.nota}</div>
            <button onClick={() => onNav && onNav('carteira')}
                    className={p.pode ? 'dgd-btn dgd-btn-primary' : 'dgd-btn dgd-btn-ghost'}
                    style={{ alignSelf: 'flex-start', padding: '6px 12px' }}>
              {p.pode ? 'Avançar fecho →' : 'Ver aging →'}
            </button>
          </div>
        );
      })}
    </div>
  </div>
);

// ============================================================================
// WEBSITE ENTRY — leads via digidelta.pt formulários
// ============================================================================
const DASH_WEBSITE_LEADS = [
  { nome: 'Tipografia Beira',     cidade: 'Viseu',     source: 'digidelta.pt/contactos',    dataIso: '2026-04-30 09:14', interesse: 'Mimaki UJV200',  score: 'quente', detalhe: 'Pediu demo. 18 colab. CNAE 1812. Match Mimaki UJV200 directo.' },
  { nome: 'PrintLab Algarve',     cidade: 'Albufeira', source: 'digidelta.pt/mimaki-uvled', dataIso: '2026-04-29 16:42', interesse: 'Mimaki UCJV330', score: 'morno',  detalhe: 'Descarregou ficha técnica. Perfil pequeno (4 colab). Avaliar potencial.' },
  { nome: 'Centro Etiquetagem ES',cidade: 'Madrid',    source: 'digidelta.pt/es/contacto',  dataIso: '2026-04-29 11:08', interesse: 'Mimaki TxF300',  score: 'quente', detalhe: 'Reuniu com 3 fornecedores. Foco têxtil sublimação. Resposta urgente.' },
];

const WEB_SCORE_COLOR = {
  quente: 'var(--dgd-red-700)',
  morno:  'var(--dgd-pumpkin-700)',
  frio:   'var(--dgd-fg-3)',
};

const DashWebsiteEntry = ({ onNav }) => (
  <div>
    <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, marginBottom: 12, flexWrap: 'wrap' }}>
      <h3 style={{ margin: 0, font: 'var(--dgd-h4)', letterSpacing: '-0.01em', color: 'var(--dgd-fg-1)' }}>Leads do website · digidelta.pt</h3>
      <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-3)' }}>{DASH_WEBSITE_LEADS.length} novos · last 48h · Digi qualificou automaticamente</div>
    </div>
    <div style={{
      background: 'var(--dgd-bg-surface)',
      borderRadius: 'var(--dgd-radius-xl)',
      boxShadow: 'var(--dgd-shadow-card)',
      overflow: 'hidden',
    }}>
      {DASH_WEBSITE_LEADS.map((l, i) => {
        const color = WEB_SCORE_COLOR[l.score];
        return (
          <div key={i}
               onClick={() => onNav && onNav('prospeccao')}
               style={{
                 padding: '14px 18px',
                 cursor: 'pointer',
                 borderTop: i === 0 ? 'none' : '1px solid var(--dgd-border-2)',
                 transition: 'background 150ms ease-out',
                 display: 'grid', gridTemplateColumns: 'auto 1fr auto', gap: 14, alignItems: 'center',
               }}
               onMouseEnter={(e) => { e.currentTarget.style.background = 'var(--dgd-bg-app)'; }}
               onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }}>
            <div style={{
              width: 8, height: 8, borderRadius: '50%',
              background: color,
              boxShadow: `0 0 0 4px color-mix(in oklch, ${color} 18%, transparent)`,
            }} />
            <div style={{ minWidth: 0 }}>
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, flexWrap: 'wrap' }}>
                <div style={{ font: 'var(--dgd-label)', color: 'var(--dgd-fg-1)' }}>{l.nome}</div>
                <span style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)' }}>· {l.cidade}</span>
                <span style={{
                  font: 'var(--dgd-body-xs)', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.06em',
                  color: color,
                  background: `color-mix(in oklch, ${color} 12%, transparent)`,
                  padding: '1px 8px', borderRadius: 'var(--dgd-radius-pill)',
                }}>{l.score}</span>
                <span style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-2)' }}>· {l.interesse}</span>
              </div>
              <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-2)', marginTop: 4 }}>{l.detalhe}</div>
              <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)', fontFamily: 'var(--dgd-font-mono)', marginTop: 4 }}>
                {l.source} · {l.dataIso}
              </div>
            </div>
            <button className="dgd-btn dgd-btn-ghost" style={{ padding: '6px 12px', flexShrink: 0 }}>Abrir lead →</button>
          </div>
        );
      })}
    </div>
  </div>
);

// ============================================================================
// CARTEIRA → PIPELINE — handoff sinais de recompra/upsell/cross-sell
// ============================================================================
const DASH_CARTEIRA_HANDOFF = [
  { cliente: 'Vinyl Lab',         cidade: 'Porto',     tipo: 'recompra',   sinal: 'Última compra há 12 meses · UJV200 perto do EOL',         valor:  95000, sugMaquina: 'Mimaki UJV330'  },
  { cliente: 'Etiquetas Centro',  cidade: 'Coimbra',   tipo: 'upsell',     sinal: 'Volume produção +34% YoY · pediu cotação de tinta',       valor:  64000, sugMaquina: 'Mimaki TxF300'  },
  { cliente: 'Print Lab Madrid',  cidade: 'Madrid',    tipo: 'cross-sell', sinal: 'Tem UJF-7151 · há 2 anos sem expandir gama',              valor:  48000, sugMaquina: 'Mimaki UCJV330' },
  { cliente: 'Gráfica Mar',       cidade: 'Faro',      tipo: 'recompra',   sinal: 'Renovação contrato manutenção em Junho · momento ideal',  valor: 110000, sugMaquina: 'Mimaki UJV200'  },
];

const HANDOFF_TIPO_COLOR = {
  recompra:    'var(--dgd-green-700)',
  upsell:      'var(--dgd-primary-700)',
  'cross-sell':'var(--dgd-purple-700)',
};

const DashCarteiraHandoff = ({ onNav }) => {
  const total = DASH_CARTEIRA_HANDOFF.reduce((s, x) => s + x.valor, 0);
  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 12, marginBottom: 12, flexWrap: 'wrap' }}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, flexWrap: 'wrap' }}>
          <h3 style={{ margin: 0, font: 'var(--dgd-h4)', letterSpacing: '-0.01em', color: 'var(--dgd-fg-1)' }}>Carteira → Pipeline · clientes prontos</h3>
          <div style={{ font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-3)' }}>{DASH_CARTEIRA_HANDOFF.length} oportunidades · {fmtEuro(total)} potenciais</div>
        </div>
        <button onClick={() => onNav && onNav('carteira')} className="dgd-btn dgd-btn-ghost" style={{ padding: '6px 12px' }}>Ver carteira →</button>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', gap: 16 }}>
        {DASH_CARTEIRA_HANDOFF.map((h, i) => {
          const color = HANDOFF_TIPO_COLOR[h.tipo];
          return (
            <div key={i} style={{
              background: 'var(--dgd-bg-surface)',
              borderRadius: 'var(--dgd-radius-xl)',
              boxShadow: 'var(--dgd-shadow-card)',
              padding: 16,
              display: 'flex', flexDirection: 'column', gap: 10,
              transition: 'box-shadow 150ms ease-out, transform 150ms ease-out',
            }}
                 onMouseEnter={(e) => { e.currentTarget.style.boxShadow = 'var(--dgd-shadow-regular)'; e.currentTarget.style.transform = 'translateY(-1px)'; }}
                 onMouseLeave={(e) => { e.currentTarget.style.boxShadow = 'var(--dgd-shadow-card)'; e.currentTarget.style.transform = 'translateY(0)'; }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 10 }}>
                <div style={{ minWidth: 0 }}>
                  <div style={{
                    display: 'inline-block',
                    font: 'var(--dgd-body-xs)', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.06em',
                    color: color,
                    background: `color-mix(in oklch, ${color} 12%, transparent)`,
                    padding: '2px 8px', borderRadius: 'var(--dgd-radius-pill)',
                    marginBottom: 6,
                  }}>{h.tipo}</div>
                  <div style={{ font: 'var(--dgd-label)', color: 'var(--dgd-fg-1)' }}>{h.cliente}</div>
                  <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)' }}>{h.cidade}</div>
                </div>
                <div style={{ textAlign: 'right', flexShrink: 0 }}>
                  <div style={{ font: 'var(--dgd-h4)', color: 'var(--dgd-fg-1)', fontFamily: 'var(--dgd-font-mono)' }}>{fmtEuro(h.valor)}</div>
                  <div style={{ font: 'var(--dgd-body-xs)', color: 'var(--dgd-fg-3)' }}>potencial</div>
                </div>
              </div>
              <div style={{
                font: 'var(--dgd-body-sm)', color: 'var(--dgd-fg-2)',
                borderLeft: `2px solid ${color}`,
                paddingLeft: 10,
                fontStyle: 'italic',
              }}>"{h.sinal}"</div>
              <div style={{
                font: 'var(--dgd-body-sm)',
                background: 'var(--dgd-bg-app)',
                padding: '6px 10px',
                borderRadius: 'var(--dgd-radius-sm)',
                color: 'var(--dgd-fg-2)',
              }}>
                <span style={{ fontWeight: 700, color: 'var(--dgd-fg-1)' }}>Sugestão Digi:</span> {h.sugMaquina}
              </div>
              <button onClick={() => onNav && onNav('carteira')} className="dgd-btn dgd-btn-primary" style={{ alignSelf: 'flex-start', padding: '6px 12px' }}>
                Criar OP →
              </button>
            </div>
          );
        })}
      </div>
    </div>
  );
};

// ============================================================================
// SCREEN
// ============================================================================
const ScreenComercialDashboard = ({ onOpenChat, onNav, userName, vendedorId }) => {
  const [viewMode, setViewMode] = React.useState('ytm');
  const { data: pipelineData, loading: pipelineLoading } = usePipeline(vendedorId);
  return (
    <div className="dgd-design-system scrollbar"
         style={{ height: '100%', overflow: 'auto', background: 'var(--dgd-bg-app)' }}>
      <div style={{ padding: '32px 32px 60px', maxWidth: 1360, margin: '0 auto', display: 'flex', flexDirection: 'column', gap: 28 }}>
        <DashHero viewMode={viewMode} onChangeView={setViewMode} onNav={onNav} userName={userName} pipelineData={pipelineData} />
        <DashBriefing onNav={onNav} />
        <DashPulse onNav={onNav} pipelineData={pipelineData} />
        <DashBPCard onNav={onNav} />
        <DashPipelineOPs onNav={onNav} viewMode={viewMode} pipelineData={pipelineData} />
        <div id="dash-accoes-anchor" />
        <DashAccoes onNav={onNav} />
        <DashSATSemana onNav={onNav} />
        <DashMapaIberia />
        <DashHistoricoNanda onNav={onNav} />
        <DashBudgetInfoSource />
        <DashGamification viewMode={viewMode} />
        <DashFinanceiroPreFecho onNav={onNav} />
        <DashWebsiteEntry onNav={onNav} />
        <DashCarteiraHandoff onNav={onNav} />
        <DashDigiInput onOpenChat={onOpenChat} />
      </div>
    </div>
  );
};

window.ScreenComercialDashboard = ScreenComercialDashboard;
