// js/components/pages/Dashboard.jsx
// Dashboard principal — métricas, metas, pipeline, alertas
// Extraído de index.html em Fase 6 (2026-04-29): L583-L1076
// Deps runtime: fmt, fmtDate, today, saleFinalTotal, nid, Modal, MetasAdmin, Compras, Pagar, Receber, ApprovalHub, ComissaoAdmin, ComissaoVendedora
(function() {
  'use strict';
  const {useState, useMemo} = React;

function Dashboard({user,data,metas,setMetas,metasBase={},setMetasBase,extraUsers,setExtraUsers,allUsers,discountRequests,cancelRequests,onOpenDiscountModal,onOpenCancelModal,onNavigate}){
  // [v224.28 DASHBOARD-ESTOQUISTA] +entries, +notasFreteiro pra cards novos
  const{products,sales,quotes,payables,receivables,clients,entries,notasFreteiro}=data;
  const[clientSearch,setClientSearch]=useState('');
  const[stockModal,setStockModal]=useState(null); // null | 'acabando' | 'zerados'
  const[stockSearch,setStockSearch]=useState('');
  // [v224.28 DASHBOARD-ESTOQUISTA] quickSearch dropdown produtos no header
  const[quickSearch,setQuickSearch]=useState('');
  // [v224.29 DASHBOARD-ESTOQUISTA NUCLEAR] fetch local · warehouses + 3 queries stock_transfers
  const[transfersPending,setTransfersPending]=useState(0);
  const[transfersHoje,setTransfersHoje]=useState(0);
  const[myTransfers,setMyTransfers]=useState([]);
  const[warehouses,setWarehouses]=useState([]);
  // [v224.38 20260526] paginação "Transferir Senador→Alfonso" · 50/pg + setas
  const[pageIdx,setPageIdx]=useState(0);
  // [v224.39 20260526] 3 filtros bloco Transferir · search + chip status + sort dropdown
  const[transferSearch,setTransferSearch]=useState('');
  const[transferStatus,setTransferStatus]=useState('all'); // 'all' | 'zero' | 'acabando'
  const[transferSort,setTransferSort]=useState('default'); // 'default' | 'senador_desc' | 'alfonso_asc' | 'name_asc'
  // [v224.40 HISTÓRICO 20260526] TabBar interna bloco G + histórico stock_transfers últimos 30d
  const[transferTab,setTransferTab]=useState('atual'); // 'atual' | 'historico'
  const[transferHistorico,setTransferHistorico]=useState([]);
  // [v224.45 20260527] Vendas pendentes despacho com peça no Senador (visibilidade · trazer pro Alfonso)
  const[vendasSenador,setVendasSenador]=useState([]);
  const[loadingVendasSenador,setLoadingVendasSenador]=useState(false);
  const[loadingHistorico,setLoadingHistorico]=useState(false);
  const[historicoSearch,setHistoricoSearch]=useState('');
  const[historicoStatus,setHistoricoStatus]=useState('all');
  const[historicoPage,setHistoricoPage]=useState(0);
  // [v224.37 20260526] reposFilter REMOVIDO · novo bloco "Acabando no Alfonso" sem filter chips (foco operacional)
  React.useEffect(function(){
    if(user.role!=='estoquista' || typeof sb==='undefined') return;
    // 1. Warehouses (pra split bar + transfer rotas + repos pills)
    sb.from('warehouses').select('id,name,code').order('name')
      .then(function(res){ if(!res.error && Array.isArray(res.data)) setWarehouses(res.data); })
      .catch(function(e){ znxLogWarn('[ZNX v224.29 warehouses] fetch failed', e); });
    // 2. Transferências pendentes (criadas por mim · não recebidas)
    sb.from('stock_transfers')
      .select('id', {count:'exact', head:true})
      .eq('requested_by', user.id).is('received_at', null).is('cancelled_at', null)
      .then(function(res){ if(!res.error) setTransfersPending(res.count||0); })
      .catch(function(e){ znxLogWarn('[ZNX v224.29 transfersPending] fetch failed', e); });
    // 3. Minhas últimas 5 transferências
    sb.from('stock_transfers')
      .select('id,transfer_number,from_warehouse_id,to_warehouse_id,quantity_requested,status,created_at')
      .eq('requested_by', user.id).order('created_at',{ascending:false}).limit(5)
      .then(function(res){ if(!res.error && Array.isArray(res.data)) setMyTransfers(res.data); })
      .catch(function(e){ znxLogWarn('[ZNX v224.29 myTransfers] fetch failed', e); });
    // 4. Transferências hoje (count global · qualquer requested_by)
    const todayISO = new Date().toISOString().slice(0,10);
    sb.from('stock_transfers')
      .select('id', {count:'exact', head:true})
      .gte('created_at', todayISO)
      .then(function(res){ if(!res.error) setTransfersHoje(res.count||0); })
      .catch(function(e){ znxLogWarn('[ZNX v224.29 transfersHoje] fetch failed', e); });
  },[user]);

  // [v224.40 HISTÓRICO 20260526] Fetch stock_transfers últimos 30d quando tab='historico'
  // Trigger SOMENTE quando estoquista E tab=historico (lazy load · zero custo no tab atual)
  React.useEffect(function(){
    if(user.role !== 'estoquista' || transferTab !== 'historico' || typeof sb === 'undefined') return;
    setLoadingHistorico(true);
    var since = new Date(); since.setDate(since.getDate() - 30);
    sb.from('stock_transfers')
      .select('id,transfer_number,product_id,from_warehouse_id,to_warehouse_id,quantity_requested,quantity_received,status,requested_by,requested_at,received_by,received_at,cancelled_by,cancelled_at,cancel_reason,created_at')
      .gte('created_at', since.toISOString())
      .order('requested_at', {ascending:false, nullsFirst:false})
      .limit(500)
      .then(function(r){
        if(!r.error && Array.isArray(r.data)) setTransferHistorico(r.data);
        else if(r.error) znxLogWarn('[v224.40 historico]', r.error);
        setLoadingHistorico(false);
      });
  }, [transferTab, user.role, user.id]);

  // [v224.45 20260527] Fetch vendas pendentes despacho com item Senador · RPC read-only
  // Bloco vazio HOJE por backfill v224.32 (printed_at populated) · popula com vendas novas
  React.useEffect(function(){
    if(user.role !== 'estoquista' || typeof sb === 'undefined') return;
    setLoadingVendasSenador(true);
    sb.rpc('get_estoquista_vendas_senador', { p_dias: 7 })
      .then(function(res){
        if(!res.error && Array.isArray(res.data)) setVendasSenador(res.data);
        else if(res.error) znxLogWarn('[v224.45 vendas senador]', res.error);
        setLoadingVendasSenador(false);
      })
      .catch(function(e){ znxLogWarn('[v224.45 vendas senador]', e); setLoadingVendasSenador(false); });
  }, [user.role]);

  // Mês atual dinâmico
  const todayStr=today();
  const currentMonth=todayStr.slice(0,7);

  // Helper: nome do cliente a partir de uma venda
  function getClientName(s){
    if(s.client)return s.client;
    if(s.clientId){const c=clients.find(x=>x.id===s.clientId);return c?.name||s.clientName||'Cliente avulso';}
    return 'Cliente avulso';
  }

  // Vendas filtradas por vendedor (vendedor vê só as suas)
  // [BUG-FIX 20260504] isFaturada exclui Cancelada + Cancelada (devolução) + Devolvida (total)
  // [v224.90 PERF 2026-05-31] envelopa 12 cálculos em useMemo · ZERO mudança lógica
  // Antes: cada render recalculava mySales (filter) + 11 derivados. Realtime sales event
  // disparava re-render → 12 passes sobre sales/mySales/todaySales/monthSales sem cache.
  // Refs: regra_extract_refactor_overhead_real (MINI envelope justificado)
  const mySales = useMemo(function(){
    return (user.role==='vendedor' ? sales.filter(s=>s.sellerName===user.name) : sales).filter(isFaturada);
  }, [sales, user.role, user.name]);
  const monthSales = useMemo(function(){
    return mySales.filter(s=>s.date && s.date.startsWith(currentMonth));
  }, [mySales, currentMonth]);
  const todaySales = useMemo(function(){
    return mySales.filter(s=>s.date===todayStr);
  }, [mySales, todayStr]);
  const dailyRevenue = useMemo(function(){
    return todaySales.reduce((s,v)=>s+saleFinalTotal(v),0);
  }, [todaySales]);
  const dailyTicket = useMemo(function(){
    return todaySales.length>0 ? dailyRevenue/todaySales.length : 0;
  }, [todaySales, dailyRevenue]);
  const dailyProfit = useMemo(function(){
    return todaySales.reduce((s,v)=>s+saleProfit(v.items,products),0);
  }, [todaySales, products]);
  // [BUG-FIX 20260507-v98] Mesmos 3 bugs que Vendas.jsx tinha:
  // 1. Filtro paymentMethod===Pix ignorava parte Pix de Misto
  // 2. Filtro paymentMethod===Dinheiro era string errada (banco usa 'Dinheiro Vivo')
  // 3. Somava total da venda em vez do split.
  // Fix: somar direto paymentPixValue/paymentCashValue de TODAS vendas.
  const dailyPix = useMemo(function(){
    return todaySales.reduce((s,v)=>s+Number(v.paymentPixValue||v.payment_pix_value||0),0);
  }, [todaySales]);
  const dailyCash = useMemo(function(){
    return todaySales.reduce((s,v)=>s+Number(v.paymentCashValue||v.payment_cash_value||0),0);
  }, [todaySales]);
  const monthPix = useMemo(function(){
    return monthSales.reduce((s,v)=>s+Number(v.paymentPixValue||v.payment_pix_value||0),0);
  }, [monthSales]);
  const monthCash = useMemo(function(){
    return monthSales.reduce((s,v)=>s+Number(v.paymentCashValue||v.payment_cash_value||0),0);
  }, [monthSales]);
  const revenue = useMemo(function(){
    return monthSales.reduce((s,v)=>s+saleFinalTotal(v),0);
  }, [monthSales]);
  const profit = useMemo(function(){
    return monthSales.reduce((s,v)=>s+saleProfit(v.items,products),0);
  }, [monthSales, products]);

  // [v224.95 N+1 fix] productsById O(1) lookup · template provado v224.91 Orcamentos
  // Substitui products.find(p=>nid(p.id,it.productId)) na lista itens (clientStats hot path)
  const productsById = useMemo(function(){
    return Object.fromEntries((products||[]).map(p=>[p.id,p]));
  }, [products]);

  // Estoque
  const lowStock=products.filter(p=>isLowStock(p,sales));
  const acabando=products.filter(p=>p.stock>0&&p.stock<=(p.estoqueMin||20));
  const noStock=products.filter(p=>p.stock<=0);
  const overduePay=payables.filter(p=>p.status==='Pendente'&&isOverdue(p.due));
  const overdueRec=receivables.filter(r=>r.status==='Pendente'&&isOverdue(r.due));
  const todayPay=payables.filter(p=>p.status==='Pendente'&&isDueToday(p.due));

  // Análise de clientes: frequência, inatividade, produto preferido
  const clientStats=useMemo(()=>{
    const baseSales=(user.role==='vendedor'?mySales:sales).filter(isFaturada);
    const map={};
    for(const s of baseSales){
      const nome=getClientName(s);
      if(!map[nome])map[nome]={name:nome,comprasMes:0,totalMes:0,lastDate:'',unidadesMes:0,prodCount:{}};
      const st=map[nome];
      if(s.date?.startsWith(currentMonth)){
        st.comprasMes++;
        st.totalMes+=saleFinalTotal(s);
        (s.items||[]).forEach(it=>{
          st.unidadesMes+=(it.qty||1);
          if(it.productId&&it.productId!==0){
            const pname=productsById[it.productId]?.name||`Prod #${it.productId}`;
            st.prodCount[pname]=(st.prodCount[pname]||0)+(it.qty||1);
          }
        });
      }
      if(s.date&&(!st.lastDate||s.date>st.lastDate))st.lastDate=s.date;
    }
    return Object.values(map).map(st=>{
      const days=st.lastDate?Math.floor((new Date(todayStr)-new Date(st.lastDate))/86400000):999;
      const top=Object.entries(st.prodCount).sort((a,b)=>b[1]-a[1])[0];
      return{...st,daysSince:days,inactive:days>30,topProduct:top?top[0]:'—'};
    }).sort((a,b)=>a.daysSince-b.daysSince);
  },[sales,currentMonth,user.role,user.name,clients,products]);

  const filteredClients=useMemo(()=>clientSearch
    ?clientStats.filter(c=>c.name.toLowerCase().includes(clientSearch.toLowerCase()))
    :clientStats
  ,[clientStats,clientSearch]);

  function dayLabel(d){
    if(d===0)return'Hoje';if(d===1)return'Ontem';
    if(d<7)return`${d}d atrás`;if(d<30)return`${Math.floor(d/7)}sem atrás`;
    if(d<365)return`${Math.floor(d/30)}m atrás`;return`${Math.floor(d/365)}a atrás`;
  }

  function ClientAnalytics({title}){
    const ativos=filteredClients.filter(c=>!c.inactive).length;
    const inativos=filteredClients.filter(c=>c.inactive).length;
    return(
      <div className="card" style={{marginTop:16}}>
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:12,flexWrap:'wrap',gap:8}}>
          <div>
            <span style={{fontSize:13,color:'#9CA3AF',fontWeight:600}}>{title||'Análise de Clientes'}</span>
            <span style={{fontSize:11,color:'#16A34A',marginLeft:10}}>● {ativos} ativos</span>
            <span style={{fontSize:11,color:'#DC2626',marginLeft:8}}>● {inativos} inativos</span>
            <span style={{fontSize:10,color:'#6B7280',marginLeft:6}}>(sem compra +30 dias)</span>
          </div>
          <input value={clientSearch} onChange={e=>setClientSearch(e.target.value)}
            placeholder="🔍 Pesquisar cliente..."
            style={{width:210,fontSize:12,background:'#FFFFFF',border:'1px solid #2563EB55',borderRadius:7,color:'#374151',padding:'5px 12px',outline:'none'}}/>
        </div>
        <div style={{overflowX:'auto',maxHeight:400,overflowY:'auto'}}>
          <table style={{width:'100%',borderCollapse:'collapse',fontSize:12}}>
            <thead style={{position:'sticky',top:0,background:'#F0F2F5',zIndex:1}}>
              <tr style={{borderBottom:'1px solid #E4E7EC'}}>
                <th style={{textAlign:'left',padding:'6px 8px',color:'#9CA3AF',fontWeight:600,whiteSpace:'nowrap'}}>#</th>
                <th style={{textAlign:'left',padding:'6px 8px',color:'#9CA3AF',fontWeight:600}}>Cliente</th>
                <th style={{textAlign:'center',padding:'6px 8px',color:'#9CA3AF',fontWeight:600,whiteSpace:'nowrap'}}>Compras/mês</th>
                <th style={{textAlign:'right',padding:'6px 8px',color:'#9CA3AF',fontWeight:600,whiteSpace:'nowrap'}}>Total mês</th>
                <th style={{textAlign:'center',padding:'6px 8px',color:'#9CA3AF',fontWeight:600,whiteSpace:'nowrap'}}>Unid/mês</th>
                <th style={{textAlign:'center',padding:'6px 8px',color:'#9CA3AF',fontWeight:600,whiteSpace:'nowrap'}}>Último pedido</th>
                <th style={{textAlign:'left',padding:'6px 8px',color:'#9CA3AF',fontWeight:600}}>Produto preferido</th>
                <th style={{textAlign:'center',padding:'6px 8px',color:'#9CA3AF',fontWeight:600}}>Status</th>
              </tr>
            </thead>
            <tbody>
              {filteredClients.slice(0,100).map((c,i)=>(
                <tr key={c.name+i} style={{borderBottom:'1px solid #F3F4F6',background:i%2===0?'#F9FAFB':'transparent'}}>
                  <td style={{padding:'7px 8px',color:'#6B7280',fontSize:11}}>{i+1}</td>
                  <td style={{padding:'7px 8px',color:'#374151',maxWidth:220,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap',fontWeight:500}}>{c.name}</td>
                  <td style={{textAlign:'center',padding:'7px 8px'}}>
                    <span style={{color:c.comprasMes>0?'#2563EB':'#555',fontWeight:700,fontSize:13}}>{c.comprasMes}</span>
                  </td>
                  <td style={{textAlign:'right',padding:'7px 8px',color:'#374151',whiteSpace:'nowrap'}}>{c.totalMes>0?fmt(c.totalMes):'—'}</td>
                  <td style={{textAlign:'center',padding:'7px 8px',color:'#9CA3AF'}}>{c.unidadesMes||'—'}</td>
                  <td style={{textAlign:'center',padding:'7px 8px',whiteSpace:'nowrap'}}>
                    <span style={{
                      color:c.daysSince>60?'#DC2626':c.daysSince>30?'#EA580C':c.daysSince>7?'#2563EB':'#16A34A',
                      fontSize:11,fontWeight:600
                    }}>{c.lastDate?dayLabel(c.daysSince):'—'}</span>
                  </td>
                  <td style={{padding:'7px 8px',color:'#9CA3AF',fontSize:11,maxWidth:200,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{c.topProduct}</td>
                  <td style={{textAlign:'center',padding:'7px 8px'}}>
                    {c.inactive
                      ?<span style={{background:'#DC262620',color:'#DC2626',border:'1px solid #DC262640',borderRadius:10,padding:'2px 8px',fontSize:10,fontWeight:700,whiteSpace:'nowrap'}}>INATIVO</span>
                      :c.comprasMes>0
                        ?<span style={{background:'#16A34A20',color:'#16A34A',border:'1px solid #16A34A40',borderRadius:10,padding:'2px 8px',fontSize:10,fontWeight:700,whiteSpace:'nowrap'}}>ATIVO</span>
                        :<span style={{background:'#EA580C20',color:'#EA580C',border:'1px solid #EA580C40',borderRadius:10,padding:'2px 8px',fontSize:10,whiteSpace:'nowrap'}}>SEM COMPRA</span>
                    }
                  </td>
                </tr>
              ))}
              {filteredClients.length===0&&(
                <tr><td colSpan={8} style={{textAlign:'center',color:'#6B7280',padding:20,fontSize:13}}>Nenhum cliente encontrado</td></tr>
              )}
              {filteredClients.length>100&&(
                <tr><td colSpan={8} style={{textAlign:'center',color:'#6B7280',padding:8,fontSize:11}}>+{filteredClients.length-100} clientes — use o filtro para encontrar</td></tr>
              )}
            </tbody>
          </table>
        </div>
      </div>
    );
  }

  if(user.role==='admin') return(
    <div>
      <div style={{marginBottom:24}}>
        <div style={{fontSize:13,color:'#9CA3AF'}}>Bem-vindo de volta,</div>
        <div style={{fontSize:24,fontWeight:700}}>{user.name}</div>
      </div>
      <div style={{display:'grid',gridTemplateColumns:'repeat(4,1fr)',gap:16,marginBottom:16}}>
        <div className="stat-card" style={{border:'1px solid #C8A95133',background:'linear-gradient(135deg,#FFFBEB,#FEF9E7)'}}><div className="stat-label" style={{color:'#92700A'}}>💰 Faturamento Hoje</div><div className="stat-value" style={{fontSize:22,color:'#92700A'}}>{fmt(dailyRevenue)}</div><div style={{fontSize:11,color:'#9CA3AF',marginTop:4}}>{todaySales.length} venda{todaySales.length!==1?'s':''} · Ticket {dailyTicket>0?fmt(dailyTicket):'—'}</div></div>
        <div className="stat-card" style={{border:'1px solid #16A34A33',background:'linear-gradient(135deg,#F0FDF4,#DCFCE7)'}}><div className="stat-label" style={{color:'#15803D'}}>📊 Lucro Hoje</div><div className="stat-value" style={{fontSize:22,color:dailyProfit>=0?'#15803D':'#DC2626'}}>{fmt(dailyProfit)}</div><div style={{fontSize:11,color:'#9CA3AF',marginTop:4}}>Margem {dailyRevenue?((dailyProfit/dailyRevenue)*100).toFixed(1)+'%':'—'}</div></div>
        <div className="stat-card"><div className="stat-label">Faturamento Mensal — {currentMonth}</div><div className="stat-value">{fmt(revenue)}</div><div style={{fontSize:11,color:'#9CA3AF',marginTop:4}}>{monthSales.length} vendas · Ticket {monthSales.length>0?fmt(revenue/monthSales.length):'—'}</div></div>
        {/* [BUG-FIX 20260518 #619] Relabel: era "Lucro Líquido Mensal" mas saleProfit = Receita − COGS = LUCRO BRUTO. Lucro Líquido REAL precisa subtrair Gastos (ver Relatório → P&L). */}
        <div className="stat-card"><div className="stat-label">Lucro Bruto Mensal</div><div className="stat-value" style={{color:profit>=0?'#16A34A':'#DC2626'}}>{fmt(profit)}</div><div style={{fontSize:11,color:'#9CA3AF',marginTop:4}}>Margem bruta {revenue?((profit/revenue)*100).toFixed(1)+'%':'—'} · líquido em Relatório</div></div>
      </div>
      <div style={{display:'grid',gridTemplateColumns:'repeat(4,1fr)',gap:16,marginBottom:24}}>
        <div className="stat-card" style={{border:'1px solid #2563EB33',background:'linear-gradient(135deg,#EFF6FF,#DBEAFE)'}}><div className="stat-label" style={{color:'#1D4ED8'}}>🔵 Pix Hoje</div><div className="stat-value" style={{fontSize:20,color:'#1D4ED8'}}>{fmt(dailyPix)}</div><div style={{fontSize:11,color:'#9CA3AF',marginTop:4}}>Mês: {fmt(monthPix)}</div></div>
        <div className="stat-card" style={{border:'1px solid #16A34A33',background:'linear-gradient(135deg,#F0FDF4,#DCFCE7)'}}><div className="stat-label" style={{color:'#15803D'}}>💵 Dinheiro Hoje</div><div className="stat-value" style={{fontSize:20,color:'#15803D'}}>{fmt(dailyCash)}</div><div style={{fontSize:11,color:'#9CA3AF',marginTop:4}}>Mês: {fmt(monthCash)}</div></div>
        <div className="stat-card"><div className="stat-label">Pedidos em Aberto</div><div className="stat-value">{sales.filter(s=>s.status==='Aberto').length}</div><div style={{fontSize:11,color:'#9CA3AF',marginTop:4}}>{quotes.filter(q=>q.status!=='Convertido'&&q.status!=='Recusado').length} orç. abertos · {quotes.filter(q=>q.status==='Convertido').length} convertidos</div></div>
        <div className="stat-card"><div className="stat-label">Contas a Receber Atrasadas</div><div className="stat-value" style={{color:overdueRec.length>0?'#DC2626':'#16A34A'}}>{overdueRec.length}</div><div style={{fontSize:11,color:'#9CA3AF',marginTop:4}}>{fmt(overdueRec.reduce((s,r)=>s+Number(r.value||0),0))} em atraso</div></div>
      </div>
      {/* [REVERT URGENTE 2026-05-07] Dashboard volta a ser usado pra vendedor/estoquista.
          VendedorActivityCard restaurado pra mostrar atividade WhatsApp pra esses roles também
          (admin/financeiro veem em Usuários). DashboardV2 é só admin/financeiro. */}
      {(user.role==='admin'||user.role==='financeiro') && <VendedorActivityCard allUsers={allUsers} user={user}/>}

      <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:16,marginBottom:16}}>
        <div className="card">
          <div style={{fontSize:13,color:'#9CA3AF',marginBottom:12}}>Últimas Vendas do Mês</div>
          {monthSales.length===0&&<div style={{color:'#6B7280',fontSize:13}}>Nenhuma venda</div>}
          {[...monthSales].sort((a,b)=>new Date(b.createdAt||b.date)-new Date(a.createdAt||a.date)).slice(0,5).map(v=>(
            <div key={v.id} style={{display:'flex',justifyContent:'space-between',padding:'8px 0',borderBottom:'1px solid #F3F4F6',fontSize:13}}>
              <span style={{color:'#374151'}}>{v.number} — <span style={{color:'#9CA3AF'}}>{getClientName(v)}</span></span>
              <span className="gold">{fmt(saleFinalTotal(v))}</span>
            </div>
          ))}
        </div>
        <div className="card">
          <div style={{fontSize:13,color:'#9CA3AF',marginBottom:10}}>
            Alertas de Estoque
            <span onClick={()=>setStockModal('zerados')} style={{color:'#DC2626',marginLeft:8,fontSize:11,cursor:'pointer',textDecoration:'underline'}}>{noStock.length} zerados</span>
            <span onClick={()=>setStockModal('acabando')} style={{color:'#2563EB',marginLeft:6,fontSize:11,cursor:'pointer',textDecoration:'underline'}}>· {acabando.length} acabando (≤ mín)</span>
            <span style={{color:'#9CA3AF',marginLeft:6,fontSize:11}}>· {lowStock.length} baixo (dinâmico)</span>
          </div>
          <div style={{maxHeight:280,overflowY:'auto'}}>
            {/* Acabando: stock entre 1 e 19 — maior prioridade no dashboard */}
            {acabando.length>0&&<div style={{fontSize:10,color:'#2563EB',padding:'4px 2px',marginBottom:4,textTransform:'uppercase',letterSpacing:1}}>⚠ Acabando (≤ estoque mínimo)</div>}
            {acabando.slice(0,20).map(p=>(
              <div key={p.id} style={{display:'flex',justifyContent:'space-between',alignItems:'center',background:'#FFFBEB',border:'1px solid #2563EB33',borderRadius:5,marginBottom:4,padding:'5px 10px',fontSize:11}}>
                <span style={{color:'#374151'}}>{p.name}</span>
                <span style={{color:'#2563EB',fontWeight:700,marginLeft:8,whiteSpace:'nowrap'}}>{p.stock} un.</span>
              </div>
            ))}
            {acabando.length>20&&<div onClick={()=>setStockModal('acabando')} style={{color:'#2563EB',fontSize:11,padding:'3px 6px',cursor:'pointer',textDecoration:'underline',fontWeight:600}}>+{acabando.length-20} produtos acabando... (ver todos)</div>}
            {/* Zerados */}
            {noStock.length>0&&<div style={{fontSize:10,color:'#DC2626',padding:'6px 2px 4px',textTransform:'uppercase',letterSpacing:1}}>✕ Zerados ({noStock.length})</div>}
            {noStock.slice(0,15).map(p=>(
              <div key={p.id} style={{display:'flex',justifyContent:'space-between',alignItems:'center',background:'#2a0000',border:'1px solid #DC262633',borderRadius:5,marginBottom:3,padding:'4px 10px',fontSize:11}}>
                <span style={{color:'#374151'}}>{p.name}</span>
                <span style={{color:'#DC2626',fontWeight:700}}>ZERO</span>
              </div>
            ))}
            {noStock.length>15&&<div onClick={()=>setStockModal('zerados')} style={{color:'#DC2626',fontSize:11,padding:'3px 6px',cursor:'pointer',textDecoration:'underline',fontWeight:600}}>+{noStock.length-15} zerados... (ver todos)</div>}
            {/* Alto volume com estoque baixo */}
            {lowStock.filter(p=>p.stock>=20).length>0&&(
              <><div style={{fontSize:10,color:'#9CA3AF',padding:'6px 2px 4px',textTransform:'uppercase',letterSpacing:1}}>Alto volume — estoque baixo</div>
              {lowStock.filter(p=>p.stock>=20).slice(0,10).map(p=>(
                <div key={p.id} style={{display:'flex',justifyContent:'space-between',background:'#F9FAFB',borderRadius:5,marginBottom:3,padding:'4px 10px',fontSize:11}}>
                  <span style={{color:'#9CA3AF'}}>{p.name}</span>
                  <span style={{color:'#2563EB'}}>{p.stock} un.</span>
                </div>
              ))}</>
            )}
            {noStock.length===0&&acabando.length===0&&lowStock.length===0&&<div style={{color:'#16A34A',fontSize:13}}>Estoque saudável ✓</div>}
          </div>
        </div>
      </div>
      {overduePay.length>0&&<div className="alert-danger" style={{marginBottom:8}}>⚠ {overduePay.length} conta(s) a pagar em atraso</div>}
      {overdueRec.length>0&&<div className="alert-warn" style={{marginBottom:8}}>⚠ {overdueRec.length} recebimento(s) em atraso</div>}

      {/* Orçamentos — resumo do dia */}
      {user.role==='admin'&&(()=>{
        const todayQ=quotes.filter(q=>q.date===todayStr);
        const openQ=quotes.filter(q=>q.status!=='Convertido'&&q.status!=='Recusado');
        const convertedQ=quotes.filter(q=>q.status==='Convertido');
        const convertedToday=todayQ.filter(q=>q.status==='Convertido');
        return(
          <div className="card" style={{marginBottom:16,padding:'16px 20px'}}>
            <div style={{fontSize:12,color:'#9CA3AF',fontWeight:700,textTransform:'uppercase',letterSpacing:.5,marginBottom:14}}>📋 Orçamentos</div>
            <div style={{display:'grid',gridTemplateColumns:'1fr 1fr 1fr 1fr',gap:12}}>
              <div style={{textAlign:'center',background:'#F8FAFC',borderRadius:8,padding:'12px 8px'}}>
                <div style={{fontSize:22,fontWeight:800,color:'#1B2A4A'}}>{todayQ.length}</div>
                <div style={{fontSize:11,color:'#9CA3AF',marginTop:3}}>Abertos hoje</div>
              </div>
              <div style={{textAlign:'center',background:'#F0FDF4',borderRadius:8,padding:'12px 8px'}}>
                <div style={{fontSize:22,fontWeight:800,color:'#16A34A'}}>{convertedToday.length}</div>
                <div style={{fontSize:11,color:'#9CA3AF',marginTop:3}}>Fechados hoje</div>
              </div>
              <div style={{textAlign:'center',background:'#EFF6FF',borderRadius:8,padding:'12px 8px'}}>
                <div style={{fontSize:22,fontWeight:800,color:'#2563EB'}}>{openQ.length}</div>
                <div style={{fontSize:11,color:'#9CA3AF',marginTop:3}}>Em aberto (total)</div>
              </div>
              <div style={{textAlign:'center',background:'#FFFBF0',borderRadius:8,padding:'12px 8px'}}>
                <div style={{fontSize:22,fontWeight:800,color:'#B89840'}}>{convertedQ.length}</div>
                <div style={{fontSize:11,color:'#9CA3AF',marginTop:3}}>Convertidos (total)</div>
              </div>
            </div>
          </div>
        );
      })()}

      {/* Metas & Vendedores */}
      <MetasAdmin metas={metas} setMetas={setMetas} metasBase={metasBase} setMetasBase={setMetasBase} extraUsers={extraUsers} setExtraUsers={setExtraUsers} allUsers={allUsers} sales={sales} currentMonth={currentMonth}/>

      {/* [Onda V6 20260506] Approval Hub Centralizado — admin/financeiro veem TODOS pedidos */}
      <div style={{marginTop:20,marginBottom:14}}>
        <ApprovalHub
          user={user}
          discountRequests={discountRequests}
          cancelRequests={cancelRequests}
          sales={data?.sales||[]}
          products={data?.products||[]}
          clients={data?.clients||[]}
          onOpenDiscount={onOpenDiscountModal}
          onOpenCancel={onOpenCancelModal}
          onOpenTemplates={()=>{
            // ApprovalQueueModal abre via ApprovalBell (já tem polling); dispara click programático
            const bell=document.querySelector('[data-approval-bell]');
            if(bell)bell.click();
            else alert('Click no sino 🔔 no topo da página pra abrir os pedidos de templates.');
          }}
        />
      </div>

      {/* [Onda V4 20260506] Painel de Comissão admin/financeiro */}
      <div style={{marginTop:20,marginBottom:8}}>
        <ComissaoAdmin user={user} allUsers={allUsers}/>
      </div>

      {/* Modal estoque */}
      {stockModal&&(()=>{
        const isZ=stockModal==='zerados';
        const list=isZ?noStock:acabando;
        const col=isZ?'#DC2626':'#2563EB';
        const filtered=list.filter(p=>(p.name||'').toLowerCase().includes(stockSearch.toLowerCase())||(p.brand||'').toLowerCase().includes(stockSearch.toLowerCase()));
        return(
          <div onClick={()=>{setStockModal(null);setStockSearch('');}} style={{position:'fixed',inset:0,background:'rgba(0,0,0,.55)',zIndex:2000,display:'flex',alignItems:'center',justifyContent:'center'}}>
            <div onClick={e=>e.stopPropagation()} style={{background:'#fff',borderRadius:14,width:560,maxWidth:'95vw',maxHeight:'80vh',display:'flex',flexDirection:'column',boxShadow:'0 20px 60px rgba(0,0,0,.3)'}}>
              <div style={{padding:'18px 22px',borderBottom:'1px solid #E4E7EC',display:'flex',alignItems:'center',justifyContent:'space-between'}}>
                <div>
                  <div style={{fontWeight:800,fontSize:16,color:col}}>{isZ?'Produtos Zerados':'Produtos Acabando'}</div>
                  <div style={{fontSize:12,color:'#6B7280',marginTop:2}}>{list.length} produtos</div>
                </div>
                <button onClick={()=>{setStockModal(null);setStockSearch('');}} style={{background:'none',border:'none',fontSize:22,cursor:'pointer',color:'#9CA3AF',lineHeight:1}}>×</button>
              </div>
              <div style={{padding:'12px 22px',borderBottom:'1px solid #F0F2F5'}}>
                <input value={stockSearch} onChange={e=>setStockSearch(e.target.value)} placeholder="Buscar produto ou marca..." style={{width:'100%',border:'1px solid #E4E7EC',borderRadius:8,padding:'8px 12px',fontSize:13,outline:'none',boxSizing:'border-box'}}/>
              </div>
              <div style={{overflowY:'auto',padding:'10px 22px 18px'}}>
                {filtered.map(p=>(
                  <div key={p.id} style={{display:'flex',justifyContent:'space-between',alignItems:'center',padding:'7px 10px',borderRadius:6,marginBottom:3,background:isZ?'#FEF2F2':'#EFF6FF',border:`1px solid ${col}22`}}>
                    <div>
                      <span style={{fontWeight:600,fontSize:12,color:'#1F2937'}}>{p.name||p.productName}</span>
                      {p.brand&&<span style={{fontSize:11,color:'#6B7280',marginLeft:6}}>{p.brand}</span>}
                      {p.volume&&<span style={{fontSize:11,color:'#9CA3AF',marginLeft:4}}>{p.volume}</span>}
                    </div>
                    <span style={{fontWeight:700,fontSize:12,color:col,minWidth:50,textAlign:'right'}}>{isZ?'ZERO':p.stock+' un.'}</span>
                  </div>
                ))}
                {filtered.length===0&&<div style={{textAlign:'center',color:'#9CA3AF',padding:20}}>Nenhum produto encontrado</div>}
              </div>
            </div>
          </div>
        );
      })()}

      <ClientAnalytics title={`Análise de Clientes — ${currentMonth}`}/>
    </div>
  );

  if(user.role==='vendedor'){
    const meta=metas[user.name]||0;
    const base=metasBase[user.name]||0;
    const revenueTotal=revenue+base;
    const now2=new Date();
    const daysInMonth=new Date(now2.getFullYear(),now2.getMonth()+1,0).getDate();
    const dayOfMonth=now2.getDate();
    const daysLeft=daysInMonth-dayOfMonth;
    const faltando=Math.max(0,meta-revenueTotal);
    const porDia=daysLeft>0?faltando/daysLeft:faltando;
    const pctMeta=meta>0?Math.min(100,(revenueTotal/meta)*100):0;
    const ticket=monthSales.length?revenue/monthSales.length:0;
    const frase=FRASES_MOTIVACAO[dayOfMonth%FRASES_MOTIVACAO.length];
    const dicas=getDicasVendedor(pctMeta,ticket,monthSales.length,daysLeft,faltando,meta);
    const barColor=pctMeta>=100?'#16A34A':pctMeta>=70?'#2563EB':pctMeta>=40?'#EA580C':'#DC2626';
    const hora=now2.getHours();
    const saudacao=hora<12?'Bom dia':hora<18?'Boa tarde':'Boa noite';
    const orcPend=quotes.filter(q=>q.sellerName===user.name&&(q.status==='Rascunho'||q.status==='Aguardando')).length;

    // [v223.18 UX] GRÁFICO MÊS INTEIRO (D1-D31) — vendedora, mySales filtrado backend.
    // Substitui chart14 (rolling 14d) por mês corrente. Alinha com meta mensal + comissão V4.
    const chartMes = (function(){
      const buckets=[];
      const now = new Date();
      const ano = now.getFullYear();
      const mes = now.getMonth();
      const hoje = now.getDate();
      const ultimoDia = new Date(ano, mes+1, 0).getDate();
      for(let dia=1; dia<=ultimoDia; dia++){
        const d = new Date(ano, mes, dia);
        const dStr = d.toISOString().slice(0,10);
        const isFuture = dia > hoje;
        const dailyTotal = isFuture ? 0 : mySales.filter(s=>s.date===dStr).reduce((a,s)=>a+saleFinalTotal(s),0);
        const dPrev = new Date(ano, mes-1, dia);
        const dPrevStr = dPrev.toISOString().slice(0,10);
        const prevTotal = mySales.filter(s=>s.date===dPrevStr).reduce((a,s)=>a+saleFinalTotal(s),0);
        buckets.push({date:dStr,total:dailyTotal,totalPrev:prevTotal,label:String(dia),isFuture,dia});
      }
      return buckets;
    })();
    // chartMax/Pico ignoram futuros (senão pico fica em 0)
    const chartMesRealizado = chartMes.filter(b => !b.isFuture);
    const chartMax = Math.max(...chartMes.map(b=>Math.max(b.total,b.totalPrev||0)),1);
    const chartHoje = chartMesRealizado[chartMesRealizado.length-1] || chartMes[0];
    const chartPico = chartMesRealizado.reduce((max,b)=>b.total>max.total?b:max, chartMesRealizado[0] || chartMes[0]);
    // Label do mês pra header (ex: "MAIO 2026")
    const chartMesLabel = (() => {
      const meses = ['JANEIRO','FEVEREIRO','MARÇO','ABRIL','MAIO','JUNHO','JULHO','AGOSTO','SETEMBRO','OUTUBRO','NOVEMBRO','DEZEMBRO'];
      const now = new Date();
      return `${meses[now.getMonth()]} ${now.getFullYear()}`;
    })();
    const chartHojeDia = new Date().getDate();
    const chartUltimoDia = new Date(new Date().getFullYear(), new Date().getMonth()+1, 0).getDate();

    return(
      <div>
        {/* Greeting hero */}
        <div style={{background:'linear-gradient(135deg,#FFFBEB,#FEF3C7)',border:'1px solid #2563EB33',borderRadius:12,padding:'20px 24px',marginBottom:20}}>
          <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',flexWrap:'wrap',gap:12}}>
            <div>
              <div style={{fontSize:13,color:'#9CA3AF'}}>{saudacao},</div>
              <div style={{fontSize:26,fontWeight:800,color:'#374151'}}>{user.name} 💪</div>
              <div style={{fontSize:13,color:'#2563EB',marginTop:8,fontStyle:'italic',maxWidth:500}}>"{frase}"</div>
            </div>
            <div style={{textAlign:'right'}}>
              <div style={{fontSize:11,color:'#9CA3AF'}}>Hoje é dia {dayOfMonth}</div>
              <div style={{fontSize:13,color:'#374151',fontWeight:600}}>{daysLeft} dias restantes no mês</div>
            </div>
          </div>
        </div>

        {/* Meta Card */}
        {meta>0?(
          <div className="card" style={{marginBottom:20,border:pctMeta>=100?'1px solid #16A34A66':'1px solid #E4E7EC'}}>
            <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:16}}>
              <div>
                <div style={{fontSize:12,color:'#9CA3AF',textTransform:'uppercase',letterSpacing:1}}>🎯 Meta Mensal</div>
                <div style={{fontSize:22,fontWeight:800,color:'#2563EB'}}>{fmt(meta)}</div>
              </div>
              <div style={{textAlign:'right'}}>
                <div style={{fontSize:36,fontWeight:900,color:barColor}}>{pctMeta.toFixed(1)}%</div>
                <div style={{fontSize:12,color:'#9CA3AF'}}>da meta atingida</div>
              </div>
            </div>
            {/* Progress bar */}
            <div style={{background:'#F9FAFB',borderRadius:8,height:18,overflow:'hidden',marginBottom:16,position:'relative'}}>
              <div style={{height:'100%',background:`linear-gradient(90deg,${barColor}99,${barColor})`,borderRadius:8,width:`${pctMeta}%`,transition:'width .5s',minWidth:pctMeta>0?8:0}}/>
              {pctMeta>10&&<div style={{position:'absolute',left:'50%',top:'50%',transform:'translate(-50%,-50%)',fontSize:11,fontWeight:700,color:'#374151'}}>{fmt(revenueTotal)} / {fmt(meta)}</div>}
            </div>
            {/* Stats row */}
            <div style={{display:'grid',gridTemplateColumns:'repeat(3,1fr)',gap:12}}>
              <div style={{background:'#F8FAFB',borderRadius:8,padding:'12px 16px',textAlign:'center'}}>
                <div style={{fontSize:11,color:'#9CA3AF',marginBottom:4}}>Faltando</div>
                <div style={{fontSize:18,fontWeight:800,color:faltando>0?'#DC2626':'#16A34A'}}>{faltando>0?fmt(faltando):'Meta batida! 🎉'}</div>
              </div>
              <div style={{background:'#F8FAFB',borderRadius:8,padding:'12px 16px',textAlign:'center'}}>
                <div style={{fontSize:11,color:'#9CA3AF',marginBottom:4}}>Precisa/dia</div>
                <div style={{fontSize:18,fontWeight:800,color:porDia>0?'#2563EB':'#16A34A'}}>{daysLeft>0&&faltando>0?fmt(porDia):'—'}</div>
              </div>
              <div style={{background:'#F8FAFB',borderRadius:8,padding:'12px 16px',textAlign:'center'}}>
                <div style={{fontSize:11,color:'#9CA3AF',marginBottom:4}}>Dias Restantes</div>
                <div style={{fontSize:18,fontWeight:800,color:daysLeft<=5?'#DC2626':daysLeft<=10?'#2563EB':'#F5F0E8'}}>{daysLeft}</div>
              </div>
            </div>
          </div>
        ):(
          <div className="alert-warn" style={{marginBottom:20,padding:'14px 18px'}}>
            🎯 Nenhuma meta definida para este mês. Fale com o administrador para configurar sua meta.
          </div>
        )}

        {/* KPIs */}
        <div style={{display:'grid',gridTemplateColumns:'repeat(5,1fr)',gap:14,marginBottom:20}}>
          <div className="stat-card"><div className="stat-label">Vendas do Mês</div><div className="stat-value">{monthSales.length}</div></div>
          <div className="stat-card"><div className="stat-label">Faturado</div><div className="stat-value" style={{fontSize:18}}>{fmt(revenue)}</div></div>
          <div className="stat-card"><div className="stat-label">Ticket Médio Mês</div><div className="stat-value" style={{fontSize:18}}>{monthSales.length?fmt(ticket):'—'}</div></div>
          <div className="stat-card" style={{border:'1px solid #2563EB44',background:'linear-gradient(135deg,#FFFBEB,#FEF9E7)'}}>
            <div className="stat-label">🎯 Ticket Médio Hoje</div>
            <div className="stat-value" style={{fontSize:18}}>{dailyTicket>0?fmt(dailyTicket):'—'}</div>
            <div style={{fontSize:11,color:'#9CA3AF',marginTop:4}}>{todaySales.length} venda{todaySales.length!==1?'s':''} hoje · {dailyRevenue>0?fmt(dailyRevenue):'R$ 0'}</div>
          </div>
          <div className="stat-card"><div className="stat-label">Orç. Pendentes</div><div className="stat-value">{orcPend}</div></div>
        </div>

        {/* ═══ GRÁFICO 14 DIAS (vendedora) — só dados dela [v111] ═══ */}
        <div className="card" style={{padding:'18px 20px 12px',marginBottom:20}}>
          <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',flexWrap:'wrap',gap:8,marginBottom:14}}>
            <div>
              {/* [v223.18 UX] Header mensal — dia X/Y dinâmico */}
              <div style={{fontSize:11,color:'#9CA3AF',fontWeight:700,textTransform:'uppercase',letterSpacing:1.5}}>📈 Suas vendas — {chartMesLabel} · dia {chartHojeDia}/{chartUltimoDia}</div>
              {/* [v223.19 UX] Header dinâmico — quando pico=hoje, evita repetir mesmo valor 2x */}
              <div style={{fontSize:13,color:'#6B7280',marginTop:4}}>
                {chartPico.dia === chartHojeDia && chartPico.total > 0 ? (
                  <>🏆 <strong style={{color:'#7C3AED'}}>HOJE é o pico do mês</strong>: <strong style={{color:'#2563EB'}}>{fmt(chartHoje.total)}</strong></>
                ) : (
                  <>Pico: <strong style={{color:'#1B2A4A'}}>{fmt(chartPico.total)}</strong> em D{chartPico.label} · Hoje: <strong style={{color:'#2563EB'}}>{fmt(chartHoje.total)}</strong></>
                )}
              </div>
            </div>
            <div style={{display:'flex',gap:14,fontSize:11,color:'#6B7280'}}>
              <span style={{display:'flex',alignItems:'center',gap:5}}><span style={{width:18,height:3,background:'linear-gradient(90deg,#3B82F6,#2563EB)',display:'inline-block',borderRadius:2}}/> mês atual</span>
              <span style={{display:'flex',alignItems:'center',gap:5}}><span style={{width:18,height:0,borderTop:'2px dashed #94A3B8',display:'inline-block'}}/> mês anterior</span>
            </div>
          </div>
          {(() => {
            // [UX FIX v223.17] padT 16→32: dá folga pra label R$ pico não cortar no topo
            // [v223.18 UX] chart14 → chartMes (mês inteiro D1-D31)
            const W=980,H=220,padL=56,padR=16,padT=32,padB=32;
            const chartW=W-padL-padR;
            const chartH=H-padT-padB;
            const n=chartMes.length;
            const stepX=chartW/(n-1);
            const yTicks=[0,0.25,0.5,0.75,1].map(p=>Math.round(chartMax*p));
            function xAt(i){return padL+i*stepX;}
            function yAt(v){return padT+chartH-(v/chartMax)*chartH;}
            // [v223.18 UX] linePath só conecta dias realizados (não cai pra zero nos futuros)
            const realizados = chartMes.filter(b => !b.isFuture);
            const lastRealIdx = realizados.length - 1;
            const linePath = realizados.map((b,i)=>{
              const realIdx = chartMes.indexOf(b);
              return (i===0?'M':'L')+xAt(realIdx)+' '+yAt(b.total);
            }).join(' ');
            const areaPath = realizados.length > 0
              ? linePath+' L'+xAt(lastRealIdx)+' '+(padT+chartH)+' L'+xAt(0)+' '+(padT+chartH)+' Z'
              : '';
            // prevPath continua mês inteiro (tem dados mês passado todo)
            const prevPath=chartMes.map((b,i)=>(i===0?'M':'L')+xAt(i)+' '+yAt(b.totalPrev||0)).join(' ');
            return(
              <svg width="100%" viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="xMidYMid meet" style={{display:'block',maxHeight:260}}>
                <defs>
                  <linearGradient id="vendArea" x1="0" y1="0" x2="0" y2="1">
                    <stop offset="0%" stopColor="#3B82F6" stopOpacity="0.35"/>
                    <stop offset="60%" stopColor="#3B82F6" stopOpacity="0.08"/>
                    <stop offset="100%" stopColor="#3B82F6" stopOpacity="0"/>
                  </linearGradient>
                  <linearGradient id="vendLine" x1="0" y1="0" x2="1" y2="0">
                    <stop offset="0%" stopColor="#3B82F6"/><stop offset="100%" stopColor="#2563EB"/>
                  </linearGradient>
                </defs>
                {yTicks.map((tick,i)=>(
                  <g key={i}>
                    <line x1={padL} y1={yAt(tick)} x2={W-padR} y2={yAt(tick)} stroke={i===0?'#CBD5E1':'#E5E7EB'} strokeWidth="1" strokeDasharray={i===0?'':'3 3'}/>
                    <text x={padL-8} y={yAt(tick)+4} fontSize="10" fill="#94A3B8" textAnchor="end">{tick>=1000?(tick/1000).toFixed(0)+'k':tick}</text>
                  </g>
                ))}
                <path d={prevPath} stroke="#94A3B8" strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round" strokeDasharray="5 4" opacity="0.55"/>
                <path d={areaPath} fill="url(#vendArea)" stroke="none"/>
                <path d={linePath} stroke="url(#vendLine)" strokeWidth="3" fill="none" strokeLinecap="round" strokeLinejoin="round"/>
                {/* [v223.18 UX] Pontos + labels — dias futuros viram ghost vertical sutil */}
                {chartMes.map((b,i)=>{
                  if (b.isFuture) {
                    const x = xAt(i);
                    return (
                      <g key={i}>
                        <line x1={x} y1={padT} x2={x} y2={padT+chartH} stroke="#E5E7EB" strokeWidth="0.5" strokeDasharray="2 3" opacity="0.5"/>
                        {(b.dia % 5 === 0 || b.dia === chartUltimoDia) && (
                          <text x={x} y={H-12} fontSize="10" fill="#CBD5E1" textAnchor="middle">{b.label}</text>
                        )}
                      </g>
                    );
                  }
                  const isToday=b.dia===chartHojeDia;
                  const isPico=b.total===chartPico.total&&b.total>0;
                  const x=xAt(i),y=yAt(b.total);
                  return(
                    <g key={i}>
                      <rect x={x-stepX/2} y={padT} width={stepX} height={chartH} fill="transparent">
                        <title>D{b.label}: {fmt(b.total)}{b.totalPrev>0?` (mês anterior: ${fmt(b.totalPrev)})`:''}</title>
                      </rect>
                      {isToday&&<circle cx={x} cy={y} r="14" fill="#2563EB" opacity="0.15"><animate attributeName="r" values="10;18;10" dur="2s" repeatCount="indefinite"/></circle>}
                      <circle cx={x} cy={y} r={isToday?6:isPico?5:4} fill={isToday?'#2563EB':'#FFFFFF'} stroke={isPico?'#7C3AED':'#2563EB'} strokeWidth={isPico?2.5:2}/>
                      {isPico&&b.total>0&&(
                        <g>
                          {/* [UX FIX v223.17] auto-flip label abaixo do ponto se vai overflow no topo */}
                          <rect x={x-22} y={y - 22 < padT ? y + 6 : y - 22} width="44" height="14" rx="3" fill="#7C3AED"/>
                          <text x={x} y={y - 12 < padT ? y + 16 : y - 12} fontSize="9" fill="#FFFFFF" textAnchor="middle" fontWeight="700">{(b.total/1000).toFixed(0)}k</text>
                        </g>
                      )}
                      {(b.dia%5===0||isToday||b.dia===1)&&(
                        <text x={x} y={H-12} fontSize="10" fill={isToday?'#2563EB':'#94A3B8'} textAnchor="middle" fontWeight={isToday?700:400}>{b.label}</text>
                      )}
                    </g>
                  );
                })}
              </svg>
            );
          })()}
        </div>

        {/* [Onda V4 20260506] Widget de Comissão da vendedora */}
        <ComissaoVendedora user={user}/>

        {/* Feed de vendas + Dicas */}
        <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:16,marginBottom:16}}>
          {/* Vendas do mês */}
          <div className="card" style={{padding:0}}>
            <div style={{padding:'12px 16px',borderBottom:'1px solid #E4E7EC',display:'flex',justifyContent:'space-between',alignItems:'center'}}>
              <span style={{fontWeight:700,color:'#2563EB',fontSize:13}}>📋 Minhas Vendas — {currentMonth}</span>
              <span style={{fontSize:11,color:'#9CA3AF'}}>{monthSales.length} nota{monthSales.length!==1?'s':''}</span>
            </div>
            <div style={{maxHeight:380,overflowY:'auto'}}>
              {[...monthSales].reverse().map((v,i)=>{
                const running=[...monthSales].slice(0,monthSales.length-i).reduce((s,x)=>s+saleFinalTotal(x),0);
                return(
                  <div key={v.id} style={{display:'flex',justifyContent:'space-between',alignItems:'center',padding:'10px 16px',borderBottom:'1px solid #F3F4F6',background:i===0?'#111200':'transparent'}}>
                    <div>
                      <div style={{fontSize:13,fontWeight:600,color:'#374151'}}>{v.number||'—'}</div>
                      <div style={{fontSize:11,color:'#9CA3AF'}}>{getClientName(v)} · {fmtDate(v.date)}</div>
                    </div>
                    <div style={{textAlign:'right'}}>
                      <div style={{fontSize:14,fontWeight:700,color:'#2563EB'}}>{fmt(saleFinalTotal(v))}</div>
                      <div style={{fontSize:10,color:'#6B7280'}}>acum: {fmt(running)}</div>
                    </div>
                  </div>
                );
              })}
              {monthSales.length===0&&<div style={{padding:20,textAlign:'center',color:'#6B7280',fontSize:13}}>Nenhuma venda esse mês ainda.</div>}
            </div>
            {monthSales.length>0&&(
              <div style={{padding:'10px 16px',borderTop:'1px solid #E4E7EC',display:'flex',justifyContent:'space-between',fontSize:13}}>
                <span style={{color:'#9CA3AF'}}>Total do mês</span>
                <span style={{fontWeight:700,color:'#2563EB'}}>{fmt(revenue)}</span>
              </div>
            )}
          </div>

          {/* Dicas */}
          <div style={{display:'flex',flexDirection:'column',gap:14}}>
            <div className="card">
              <div style={{fontWeight:700,color:'#2563EB',marginBottom:14,fontSize:13}}>💡 Dicas para Melhorar</div>
              {dicas.map((d,i)=>(
                <div key={i} style={{display:'flex',gap:12,marginBottom:12,padding:'10px 12px',background:'#F8FAFB',borderRadius:8,border:'1px solid #E4E7EC'}}>
                  <span style={{fontSize:20,lineHeight:1}}>{d.icon}</span>
                  <span style={{fontSize:13,color:'#374151',lineHeight:1.5}}>{d.text}</span>
                </div>
              ))}
            </div>
            <div className="card" style={{background:'linear-gradient(135deg,#FFFBEB,#FEF9E7)'}}>
              <div style={{fontWeight:700,color:'#2563EB',marginBottom:10,fontSize:13}}>📊 Resumo Rápido</div>
              <div style={{display:'flex',flexDirection:'column',gap:8,fontSize:13}}>
                <div style={{display:'flex',justifyContent:'space-between'}}><span style={{color:'#9CA3AF'}}>Melhor venda do mês</span><span className="gold">{monthSales.length?fmt(Math.max(...monthSales.map(v=>saleFinalTotal(v)))):'—'}</span></div>
                <div style={{display:'flex',justifyContent:'space-between'}}><span style={{color:'#9CA3AF'}}>Total de orçamentos</span><span>{quotes.filter(q=>q.sellerName===user.name).length}</span></div>
                <div style={{display:'flex',justifyContent:'space-between'}}><span style={{color:'#9CA3AF'}}>Clientes atendidos</span><span>{new Set(monthSales.map(v=>getClientName(v))).size}</span></div>
                {meta>0&&<div style={{display:'flex',justifyContent:'space-between'}}><span style={{color:'#9CA3AF'}}>Progresso diário médio</span><span style={{color:'#2563EB'}}>{dayOfMonth>1?fmt(revenue/(dayOfMonth-1)):fmt(0)}/dia</span></div>}
              </div>
            </div>
          </div>
        </div>
        <ClientAnalytics title="Meus Clientes"/>
      </div>
    );
  }

  if(user.role==='estoquista') {
    // [v224.29 NUCLEAR DASHBOARD-ESTOQUISTA] computed data + helpers inline
    const fretesPending = (notasFreteiro||[]).filter(function(f){return f.status==='pendente' || f.status==='aguardando' || f.status==='emitida' || !f.received_at;}).length;
    const sortedEntries = [...(entries||[])].sort(function(a,b){return String(b.created_at||b.date||'').localeCompare(String(a.created_at||a.date||''));});
    const lastEntry = sortedEntries[0] || null;
    const todayStrEst = today();
    // Movimentação hoje
    const entriesHoje = (entries||[]).filter(function(e){return String(e.date||e.created_at||'').startsWith(todayStrEst);}).reduce(function(s,e){return s+(e.qty||e.quantity||0);},0);
    const saidasHoje = (todaySales||[]).reduce(function(s,v){return s+(v.items||[]).reduce(function(ss,i){return ss+(i.qty||0);},0);},0);
    // Quick search
    const quickResults = (quickSearch && quickSearch.length>=2)
      ? (products||[]).filter(function(p){
          const q=quickSearch.toLowerCase();
          return (p.name||'').toLowerCase().includes(q) || (p.brand||'').toLowerCase().includes(q);
        }).slice(0,10) : [];
    // [v224.38 20260526] Transferir Senador→Alfonso · só ACIONÁVEIS (qa<=min E qs>0).
    // [v224.39 20260526] 3 filtros aplicados: search nome/marca + chip status + sort dropdown.
    // Spec Jamal cravado: zero+zero some · cards bonitos · pag 50/pg · barra horizontal filtros.
    const alfonsoWh = warehouses.find(function(w){return w.name === 'Alfonso';});
    const senadorWh = warehouses.find(function(w){return w.name === 'Senador';});
    // RAW (base · só filtro acionável) · usado pra contagem chips
    const transferRaw = (alfonsoWh && senadorWh) ? (products||[]).filter(function(p){
      const bd = p.stock_breakdown || p.stockBreakdown || {};
      const qa = bd[alfonsoWh.id] || 0;
      const qs = bd[senadorWh.id] || 0;
      const min = p.estoqueMin || 20;
      return qa <= min && qs > 0;
    }).map(function(p){
      const bd = p.stock_breakdown || p.stockBreakdown || {};
      return Object.assign({}, p, {
        qtyAlfonso: bd[alfonsoWh.id] || 0,
        qtySenador: bd[senadorWh.id] || 0
      });
    }) : [];
    // Contagens por chip (sempre baseado em RAW, independente de search/sort/status atual)
    const countZero = transferRaw.filter(function(p){return p.qtyAlfonso === 0;}).length;
    const countAcabando = transferRaw.length - countZero;
    // FILTRADA (RAW + status chip + search) · usado pra render
    const searchLower = transferSearch.trim().toLowerCase();
    const produtosAcabandoAlfonso = transferRaw.filter(function(p){
      if(transferStatus === 'zero' && p.qtyAlfonso !== 0) return false;
      if(transferStatus === 'acabando' && p.qtyAlfonso === 0) return false;
      if(searchLower){
        const nm = (p.name||'').toLowerCase();
        const br = (p.brand||'').toLowerCase();
        if(!nm.includes(searchLower) && !br.includes(searchLower)) return false;
      }
      return true;
    }).sort(function(a, b){
      if(transferSort === 'senador_desc') return b.qtySenador - a.qtySenador;
      if(transferSort === 'alfonso_asc') return a.qtyAlfonso - b.qtyAlfonso;
      if(transferSort === 'name_asc') return (a.name||'').localeCompare(b.name||'', 'pt-BR');
      // default: zero primeiro → acabando crescente
      if(a.qtyAlfonso === 0 && b.qtyAlfonso !== 0) return -1;
      if(a.qtyAlfonso !== 0 && b.qtyAlfonso === 0) return 1;
      return a.qtyAlfonso - b.qtyAlfonso;
    });
    // [v224.38 20260526] Paginação 50/pg · reset auto quando lista shrinka
    const PAGE_SIZE = 50;
    const totalPages = Math.max(1, Math.ceil(produtosAcabandoAlfonso.length / PAGE_SIZE));
    const safePageIdx = Math.min(pageIdx, totalPages - 1);
    if(safePageIdx !== pageIdx){ setTimeout(function(){setPageIdx(safePageIdx);}, 0); }
    const produtosPagina = produtosAcabandoAlfonso.slice(safePageIdx * PAGE_SIZE, (safePageIdx + 1) * PAGE_SIZE);
    // [v224.40 HISTÓRICO 20260526] Filtros + paginação 30/pg do histórico stock_transfers 30d
    const historicoFiltrado = (function(){
      if(transferTab !== 'historico') return [];
      var list = transferHistorico;
      if(historicoStatus !== 'all'){
        list = list.filter(function(t){ return t.status === historicoStatus; });
      }
      var search = historicoSearch.trim().toLowerCase();
      if(search){
        list = list.filter(function(t){
          var prod = (products||[]).find(function(p){return p.id === t.product_id;});
          var prodName = (prod ? prod.name : '').toLowerCase();
          var tnum = (t.transfer_number || '').toLowerCase();
          return prodName.includes(search) || tnum.includes(search);
        });
      }
      return list;
    })();
    const HISTORICO_PAGE_SIZE = 30;
    const historicoTotalPages = Math.max(1, Math.ceil(historicoFiltrado.length / HISTORICO_PAGE_SIZE));
    const historicoSafePage = Math.min(historicoPage, historicoTotalPages - 1);
    if(historicoSafePage !== historicoPage){ setTimeout(function(){setHistoricoPage(historicoSafePage);}, 0); }
    const historicoPagina = historicoFiltrado.slice(historicoSafePage * HISTORICO_PAGE_SIZE, (historicoSafePage + 1) * HISTORICO_PAGE_SIZE);
    // [v224.39] handler reset pag em qualquer mudança filtro/sort
    const resetPag = function(fn){ return function(v){ fn(v); setPageIdx(0); }; };
    // Helpers
    const nav = function(page){ if(typeof onNavigate==='function') onNavigate(page); };
    const getWarehouseName = function(p){
      const bd = p.stock_breakdown || p.stockBreakdown || {};
      const entries_ = Object.entries(bd).sort(function(a,b){return (b[1]||0)-(a[1]||0);});
      if(!entries_[0]) return '—';
      const w = warehouses.find(function(x){return x.id===entries_[0][0];});
      return w ? w.name : '—';
    };
    const statusBg = function(s){return {'solicitada':'#FEF3C7','em_transito':'#DBEAFE','recebida':'#D1FAE5','cancelada':'#FEE2E2','aprovada':'#E0E7FF'}[s] || '#F3F4F6';};
    const statusFg = function(s){return {'solicitada':'#92400E','em_transito':'#1E40AF','recebida':'#065F46','cancelada':'#991B1B','aprovada':'#3730A3'}[s] || '#374151';};
    const timeAgo = function(iso){
      if(!iso) return '—';
      const diff = Date.now() - new Date(iso).getTime();
      if(diff < 60000) return 'agora';
      if(diff < 3600000) return Math.floor(diff/60000)+'min';
      if(diff < 86400000) return Math.floor(diff/3600000)+'h';
      return Math.floor(diff/86400000)+'d';
    };
    // Warehouse split bar data
    const whSplit = (function(){
      const map = {};
      warehouses.forEach(function(w){map[w.id] = {name:w.name, qty:0, skus:0};});
      (products||[]).forEach(function(p){
        const bd = p.stock_breakdown || p.stockBreakdown || {};
        Object.entries(bd).forEach(function(arr){
          const whId = arr[0], q = Number(arr[1])||0;
          if(map[whId]){ map[whId].qty += q; if(q>0) map[whId].skus++; }
        });
      });
      return Object.values(map).filter(function(w){return w.qty>0;});
    })();
    const whTotal = whSplit.reduce(function(s,w){return s+w.qty;},0);
    // Cards config (DRY render)
    const statCards = [
      {label:'Total Produtos', value:products.length, color:'#1B2A4A', icon:'📦', onClick:function(){nav('produtos');}},
      {label:'Acabando <20', value:acabando.length, color:'#EA580C', icon:'⚠️', onClick:function(){setStockModal('acabando');}},
      {label:'Zerados', value:noStock.length, color:'#DC2626', icon:'🔴', onClick:function(){setStockModal('zerados');}},
      // [v224.31 RECEBER-TRANSFERENCIA 20260526] navega page dedicada (era 'entradas' · agora UX direto sem precisar abrir Depósitos)
      {label:'Transferências Pendentes', value:transfersPending, color:'#7C3AED', icon:'🔄', onClick:function(){nav('receber-transferencia');}},
      {label:'Fretes Aguardando', value:fretesPending, color:'#0891B2', icon:'🚚', onClick:function(){nav('receber-frete');}},
      {label:'Última Entrada', value:lastEntry?fmtDate(String(lastEntry.date||lastEntry.created_at||'').slice(0,10)):'—', sub:lastEntry?((lastEntry.qty||lastEntry.quantity||0)+'un · '+(lastEntry.warehouse_name||lastEntry.warehouseName||getWarehouseName(lastEntry)||'depósito')):'', color:'#15803D', icon:'📥'}
    ];

    return(
    <div style={{background:'#F9FAFB',padding:'4px',minHeight:'100vh'}}>

      {/* A · HEADER */}
      <div style={{marginBottom:24,display:'flex',alignItems:'center',justifyContent:'space-between',flexWrap:'wrap',gap:10}}>
        <div>
          <div style={{fontSize:13,color:'#6B7280',marginBottom:4}}>Olá,</div>
          <div style={{fontSize:28,fontWeight:700,color:'#111827'}}>{user.name}</div>
        </div>
        <span style={{padding:'4px 14px',background:'#EFF6FF',color:'#1B2A4A',borderRadius:999,fontSize:12,fontWeight:600,border:'1px solid #DBEAFE'}}>Estoquista</span>
      </div>

      {/* B · AÇÕES RÁPIDAS */}
      <div style={{display:'flex',gap:12,marginBottom:24,flexWrap:'wrap',alignItems:'flex-start'}}>
        <button onClick={function(){nav('entradas');}}
          style={{padding:'14px 20px',background:'#B89840',color:'#fff',border:0,borderRadius:10,fontWeight:600,fontSize:14,cursor:'pointer',boxShadow:'0 2px 4px rgba(184,152,64,0.3)'}}>
          + Nova Transferência
        </button>
        <button onClick={function(){nav('receber-frete');}}
          style={{padding:'14px 20px',background:'#1B2A4A',color:'#fff',border:0,borderRadius:10,fontWeight:600,fontSize:14,cursor:'pointer'}}>
          🚚 Receber Frete
        </button>
        <div style={{flex:1,minWidth:280,position:'relative'}}>
          <input type="text" value={quickSearch} onChange={function(e){setQuickSearch(e.target.value);}}
            placeholder="🔍 Buscar produto..."
            style={{width:'100%',padding:'14px 18px',border:'1px solid #E5E7EB',borderRadius:10,fontSize:14,background:'#fff',boxSizing:'border-box'}}/>
          {quickResults.length>0 && (
            <div style={{position:'absolute',top:'100%',left:0,right:0,marginTop:4,background:'#fff',border:'1px solid #E5E7EB',borderRadius:10,boxShadow:'0 4px 12px rgba(0,0,0,0.08)',zIndex:10,maxHeight:300,overflowY:'auto'}}>
              {quickResults.map(function(p){
                return (
                  <div key={p.id} onClick={function(){nav('produtos');}}
                    style={{padding:'10px 14px',borderBottom:'1px solid #F3F4F6',cursor:'pointer',fontSize:13}}>
                    <div style={{fontWeight:600,color:'#111827'}}>{p.name}</div>
                    <div style={{color:'#6B7280',fontSize:11}}>{p.brand||'—'} · estoque: <strong>{p.stock||0} un.</strong></div>
                  </div>
                );
              })}
            </div>
          )}
        </div>
      </div>

      {/* C · 6 CARDS STAT grid 3x2 */}
      <div style={{display:'grid',gridTemplateColumns:'repeat(3,1fr)',gap:14,marginBottom:24}}>
        {statCards.map(function(c,i){
          return (
            <div key={i} onClick={c.onClick}
              style={{background:'#fff',padding:18,borderRadius:12,border:'1px solid #E5E7EB',boxShadow:'0 1px 3px rgba(0,0,0,0.06)',cursor:c.onClick?'pointer':'default',transition:'box-shadow 0.2s, transform 0.1s'}}
              onMouseEnter={function(e){if(c.onClick){e.currentTarget.style.boxShadow='0 4px 12px rgba(0,0,0,0.1)';e.currentTarget.style.transform='translateY(-1px)';}}}
              onMouseLeave={function(e){e.currentTarget.style.boxShadow='0 1px 3px rgba(0,0,0,0.06)';e.currentTarget.style.transform='translateY(0)';}}>
              <div style={{fontSize:20,marginBottom:8}}>{c.icon}</div>
              <div style={{fontSize:12,color:'#6B7280',marginBottom:6,fontWeight:500}}>{c.label}</div>
              <div style={{fontSize:24,fontWeight:700,color:c.color,fontVariantNumeric:'tabular-nums'}}>{c.value}</div>
              {c.sub && <div style={{fontSize:11,color:'#6B7280',marginTop:4}}>{c.sub}</div>}
            </div>
          );
        })}
      </div>

      {/* D · COMPARAÇÃO ALFONSO ↔ SENADOR · barra split */}
      <div style={{background:'#fff',padding:18,borderRadius:12,border:'1px solid #E5E7EB',marginBottom:24,boxShadow:'0 1px 3px rgba(0,0,0,0.06)'}}>
        <div style={{fontSize:13,color:'#6B7280',marginBottom:14,fontWeight:600}}>📊 Depósitos · Comparação</div>
        {whTotal === 0 ? (
          <div style={{color:'#9CA3AF',fontSize:13,padding:'10px 0'}}>Sem dados de estoque por depósito.</div>
        ) : (
          <div>
            <div style={{display:'flex',height:28,borderRadius:8,overflow:'hidden',marginBottom:12,border:'1px solid #E5E7EB'}}>
              {whSplit.map(function(w,i){
                const pct = (w.qty/whTotal*100);
                return (
                  <div key={w.name} style={{width:pct+'%',background:i===0?'#B89840':'#1B2A4A',color:'#fff',fontSize:11,fontWeight:600,display:'flex',alignItems:'center',justifyContent:'center'}}>
                    {pct>=8 ? pct.toFixed(0)+'%' : ''}
                  </div>
                );
              })}
            </div>
            <div style={{display:'flex',justifyContent:'space-between',fontSize:13,gap:14,flexWrap:'wrap'}}>
              {whSplit.map(function(w,i){
                return (
                  <div key={w.name}>
                    <span style={{color:i===0?'#B89840':'#1B2A4A',fontWeight:700}}>{w.name}</span>
                    <span style={{color:'#6B7280',marginLeft:8}}>{w.qty.toLocaleString('pt-BR')} un · {w.skus} SKUs</span>
                  </div>
                );
              })}
            </div>
          </div>
        )}
      </div>

      {/* E · MOVIMENTAÇÃO HOJE · 3 mini-cards */}
      <div style={{display:'grid',gridTemplateColumns:'repeat(3,1fr)',gap:12,marginBottom:24}}>
        <div style={{background:'#fff',padding:14,borderRadius:10,border:'1px solid #E5E7EB',boxShadow:'0 1px 3px rgba(0,0,0,0.06)'}}>
          <div style={{fontSize:11,color:'#6B7280',marginBottom:4,fontWeight:500}}>📥 Entradas hoje</div>
          <div style={{fontSize:20,fontWeight:700,color:'#15803D'}}>+{entriesHoje} un</div>
        </div>
        <div style={{background:'#fff',padding:14,borderRadius:10,border:'1px solid #E5E7EB',boxShadow:'0 1px 3px rgba(0,0,0,0.06)'}}>
          <div style={{fontSize:11,color:'#6B7280',marginBottom:4,fontWeight:500}}>📤 Saídas hoje</div>
          <div style={{fontSize:20,fontWeight:700,color:'#DC2626'}}>-{saidasHoje} un</div>
        </div>
        <div style={{background:'#fff',padding:14,borderRadius:10,border:'1px solid #E5E7EB',boxShadow:'0 1px 3px rgba(0,0,0,0.06)'}}>
          <div style={{fontSize:11,color:'#6B7280',marginBottom:4,fontWeight:500}}>🔄 Transferências hoje</div>
          <div style={{fontSize:20,fontWeight:700,color:'#7C3AED'}}>{transfersHoje}</div>
        </div>
      </div>

      {/* F · MINHAS ÚLTIMAS TRANSFERÊNCIAS · tabela compacta */}
      {myTransfers.length>0 && (
        <div style={{background:'#fff',padding:18,borderRadius:12,border:'1px solid #E5E7EB',marginBottom:24,boxShadow:'0 1px 3px rgba(0,0,0,0.06)'}}>
          <div style={{fontSize:13,color:'#6B7280',marginBottom:12,fontWeight:600}}>🔄 Minhas Últimas Transferências</div>
          <table style={{width:'100%',fontSize:12,borderCollapse:'collapse'}}>
            <thead>
              <tr style={{borderBottom:'1px solid #E5E7EB',color:'#6B7280'}}>
                <th style={{textAlign:'left',padding:'8px 4px',fontWeight:600}}>N°</th>
                <th style={{textAlign:'left',padding:'8px 4px',fontWeight:600}}>Rota</th>
                <th style={{textAlign:'right',padding:'8px 4px',fontWeight:600}}>Qty</th>
                <th style={{textAlign:'center',padding:'8px 4px',fontWeight:600}}>Status</th>
                <th style={{textAlign:'right',padding:'8px 4px',fontWeight:600}}>Quando</th>
              </tr>
            </thead>
            <tbody>
              {myTransfers.map(function(t){
                const fromName = (warehouses.find(function(w){return w.id===t.from_warehouse_id;})||{}).name || '?';
                const toName = (warehouses.find(function(w){return w.id===t.to_warehouse_id;})||{}).name || '?';
                return (
                  <tr key={t.id} style={{borderBottom:'1px solid #F3F4F6'}}>
                    <td style={{padding:'10px 4px',fontWeight:600,color:'#1B2A4A'}}>{t.transfer_number}</td>
                    <td style={{padding:'10px 4px',color:'#6B7280'}}>{fromName} → {toName}</td>
                    <td style={{padding:'10px 4px',textAlign:'right',fontWeight:600,color:'#111827'}}>{t.quantity_requested}</td>
                    <td style={{padding:'10px 4px',textAlign:'center'}}>
                      <span style={{padding:'2px 8px',borderRadius:999,fontSize:10,fontWeight:600,background:statusBg(t.status),color:statusFg(t.status)}}>{t.status}</span>
                    </td>
                    <td style={{padding:'10px 4px',textAlign:'right',color:'#6B7280',fontSize:11}}>{timeAgo(t.created_at)}</td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      )}

      {/* H · v224.45 20260527 · Trazer do Senador pra despachar · só renderiza se length>0 (vazio hoje por backfill v224.32) */}
      {vendasSenador.length > 0 && (
        <div style={{background:'#fff',padding:18,borderRadius:12,border:'1px solid #FED7AA',borderLeft:'4px solid #EA580C',boxShadow:'0 1px 3px rgba(0,0,0,0.06)',marginBottom:24}}>
          <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:14,flexWrap:'wrap',gap:8}}>
            <div>
              <div style={{fontSize:15,fontWeight:700,color:'#9A3412'}}>📥 Trazer do Senador pra despachar</div>
              <div style={{fontSize:11,color:'#6B7280',marginTop:3}}>
                {vendasSenador.length} venda{vendasSenador.length!==1?'s':''} pendente{vendasSenador.length!==1?'s':''} com peça no Senador
              </div>
            </div>
          </div>
          <div style={{display:'grid',gridTemplateColumns:'1fr',gap:10,maxHeight:420,overflowY:'auto'}}>
            {vendasSenador.map(function(v){
              var itens = v.itens_senador || [];
              return (
                <div key={v.sale_id} style={{background:'#FFF7ED',border:'1px solid #FED7AA',borderRadius:10,padding:'12px 14px'}}>
                  <div style={{display:'flex',alignItems:'center',gap:8,marginBottom:8,flexWrap:'wrap'}}>
                    <span style={{fontSize:13,fontWeight:700,color:'#1B2A4A'}}>{v.venda}</span>
                    <span style={{fontSize:12,color:'#6B7280'}}>{v.cliente}</span>
                    {v.frete_type && <span style={{fontSize:10,padding:'2px 8px',background:'#F3F4F6',color:'#374151',borderRadius:999,fontWeight:600}}>{v.frete_type}</span>}
                  </div>
                  <div style={{display:'flex',flexDirection:'column',gap:4}}>
                    {itens.map(function(it,idx){
                      return (
                        <div key={idx} style={{display:'flex',justifyContent:'space-between',alignItems:'center',fontSize:12,color:'#374151',padding:'3px 0'}}>
                          <span style={{wordBreak:'break-word'}}>📦 {it.produto}</span>
                          <span style={{fontWeight:700,color:'#9A3412',marginLeft:10,whiteSpace:'nowrap'}}>×{it.qty}</span>
                        </div>
                      );
                    })}
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}

      {/* G · v224.40 · TabBar interna [Atual · Histórico] · v224.38 cards + v224.39 filtros + v224.40 histórico 30d */}
      <div style={{background:'#fff',padding:18,borderRadius:12,border:'1px solid #E5E7EB',boxShadow:'0 1px 3px rgba(0,0,0,0.06)'}}>
        {/* [v224.40] TabBar interna · Atual (acionáveis agora) · Histórico (últimos 30d) */}
        <div style={{display:'flex',gap:4,marginBottom:18,borderBottom:'2px solid #F3F4F6'}}>
          {[
            {key:'atual', label:'🔄 Transferir Agora', count:transferRaw.length},
            {key:'historico', label:'📜 Histórico', count:transferHistorico.length}
          ].map(function(t){
            var active = transferTab === t.key;
            return (
              <button key={t.key} onClick={function(){setTransferTab(t.key);}}
                style={{padding:'10px 18px',borderRadius:'8px 8px 0 0',fontSize:13,fontWeight:active?700:500,
                  background:active?'#fff':'transparent',border:'2px solid '+(active?'#F3F4F6':'transparent'),
                  borderBottom:active?'2px solid #fff':'none',color:active?'#1B2A4A':'#6B7280',
                  marginBottom:active?-2:0,cursor:'pointer'}}>
                {t.label}{t.count > 0 && (
                  <span style={{marginLeft:8,padding:'1px 8px',background:active?'#1B2A4A':'#E5E7EB',
                    color:active?'#fff':'#6B7280',borderRadius:999,fontSize:11,fontWeight:600}}>{t.count}</span>
                )}
              </button>
            );
          })}
        </div>

        {transferTab === 'atual' && (<div>
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:16,flexWrap:'wrap',gap:10}}>
          <div>
            <div style={{fontSize:15,color:'#111827',fontWeight:700,letterSpacing:'-0.01em'}}>
              🔄 Transferir Senador → Alfonso
            </div>
            <div style={{fontSize:11,color:'#6B7280',marginTop:3}}>
              {transferRaw.length===0
                ? 'Tudo em dia ✓'
                : (produtosAcabandoAlfonso.length === transferRaw.length
                    ? (produtosAcabandoAlfonso.length+' produto'+(produtosAcabandoAlfonso.length!==1?'s':'')+' acionáve'+(produtosAcabandoAlfonso.length!==1?'is':'l')+' agora')
                    : (produtosAcabandoAlfonso.length+' de '+transferRaw.length+' produto'+(transferRaw.length!==1?'s':'')+' · filtros aplicados'))}
            </div>
          </div>
          {totalPages > 1 && (
            <div style={{display:'flex',alignItems:'center',gap:8,fontSize:12,color:'#6B7280'}}>
              <button onClick={function(){setPageIdx(Math.max(0, safePageIdx - 1));}}
                disabled={safePageIdx===0}
                style={{padding:'6px 12px',border:'1px solid #E5E7EB',background:safePageIdx===0?'#F9FAFB':'#fff',borderRadius:8,cursor:safePageIdx===0?'not-allowed':'pointer',color:safePageIdx===0?'#D1D5DB':'#374151',fontWeight:600,fontSize:14}}>
                ←
              </button>
              <span style={{fontWeight:600,minWidth:78,textAlign:'center'}}>Pg {safePageIdx+1} de {totalPages}</span>
              <button onClick={function(){setPageIdx(Math.min(totalPages-1, safePageIdx + 1));}}
                disabled={safePageIdx===totalPages-1}
                style={{padding:'6px 12px',border:'1px solid #E5E7EB',background:safePageIdx===totalPages-1?'#F9FAFB':'#fff',borderRadius:8,cursor:safePageIdx===totalPages-1?'not-allowed':'pointer',color:safePageIdx===totalPages-1?'#D1D5DB':'#374151',fontWeight:600,fontSize:14}}>
                →
              </button>
            </div>
          )}
        </div>
        {/* v224.39 · Barra horizontal filtros · search + chips status + sort dropdown */}
        {transferRaw.length > 0 && (
          <div style={{display:'flex',gap:10,alignItems:'center',flexWrap:'wrap',marginBottom:16,paddingBottom:16,borderBottom:'1px solid #F3F4F6'}}>
            <div style={{flex:'1 1 220px',minWidth:180,position:'relative'}}>
              <input type="text" value={transferSearch}
                onChange={function(e){setTransferSearch(e.target.value); setPageIdx(0);}}
                placeholder="🔍 Buscar nome ou marca..."
                style={{width:'100%',padding:'8px 12px',border:'1px solid #E5E7EB',borderRadius:8,fontSize:13,background:'#fff',boxSizing:'border-box',outline:'none'}}/>
            </div>
            <div style={{display:'flex',gap:6}}>
              {[
                {key:'all', label:'Todos', count:transferRaw.length, bg:'#F3F4F6', fg:'#374151', activeBg:'#1B2A4A', activeFg:'#fff'},
                {key:'zero', label:'🔴 Zero', count:countZero, bg:'#FEF2F2', fg:'#991B1B', activeBg:'#DC2626', activeFg:'#fff'},
                {key:'acabando', label:'🟡 Acabando', count:countAcabando, bg:'#FFF7ED', fg:'#9A3412', activeBg:'#EA580C', activeFg:'#fff'}
              ].map(function(c){
                const active = transferStatus === c.key;
                return (
                  <button key={c.key}
                    onClick={function(){setTransferStatus(c.key); setPageIdx(0);}}
                    style={{padding:'7px 13px',border:'1px solid '+(active?c.activeBg:'#E5E7EB'),borderRadius:8,background:active?c.activeBg:c.bg,color:active?c.activeFg:c.fg,fontSize:12,fontWeight:600,cursor:'pointer',transition:'all 0.15s',whiteSpace:'nowrap'}}>
                    {c.label} <span style={{opacity:0.8,marginLeft:4,fontWeight:500}}>({c.count})</span>
                  </button>
                );
              })}
            </div>
            <div style={{display:'flex',alignItems:'center',gap:6,marginLeft:'auto'}}>
              <span style={{fontSize:11,color:'#6B7280',fontWeight:600}}>Ordenar:</span>
              <select value={transferSort}
                onChange={function(e){setTransferSort(e.target.value); setPageIdx(0);}}
                style={{padding:'7px 10px',border:'1px solid #E5E7EB',borderRadius:8,fontSize:12,background:'#fff',color:'#374151',cursor:'pointer',outline:'none',fontWeight:600}}>
                <option value="default">Padrão (Zero 1º)</option>
                <option value="senador_desc">Maior Senador</option>
                <option value="alfonso_asc">Menor Alfonso</option>
                <option value="name_asc">Nome A-Z</option>
              </select>
            </div>
          </div>
        )}
        {produtosAcabandoAlfonso.length===0 ? (
          <div style={{color:'#16A34A',fontSize:14,padding:'24px 4px',textAlign:'center',background:'#F0FDF4',borderRadius:10,border:'1px dashed #BBF7D0'}}>
            {transferRaw.length === 0 ? '✓ Nenhum produto precisa transferir agora · Alfonso abastecido' : '🔍 Nenhum produto encontrado com os filtros aplicados'}
          </div>
        ) : (
          <div style={{display:'grid',gridTemplateColumns:'1fr',gap:10}}>
            {produtosPagina.map(function(p){
              const qa = p.qtyAlfonso;
              const qs = p.qtySenador;
              const isZero = qa === 0;
              const accent = isZero ? '#DC2626' : '#EA580C';
              const accentBg = isZero ? '#FEF2F2' : '#FFF7ED';
              const accentBorder = isZero ? '#FECACA' : '#FED7AA';
              const badgeLabel = isZero ? 'ZERO no Alfonso' : 'Acabando ('+qa+')';
              return (
                <div key={p.id}
                  style={{background:'#fff',border:'1px solid '+accentBorder,borderLeft:'4px solid '+accent,borderRadius:10,padding:'14px 16px',display:'flex',alignItems:'center',justifyContent:'space-between',gap:14,flexWrap:'wrap',transition:'box-shadow 0.15s'}}
                  onMouseEnter={function(e){e.currentTarget.style.boxShadow='0 4px 12px rgba(0,0,0,0.08)';}}
                  onMouseLeave={function(e){e.currentTarget.style.boxShadow='none';}}>
                  <div style={{flex:'1 1 280px',minWidth:0}}>
                    <div style={{display:'flex',alignItems:'center',gap:8,marginBottom:6,flexWrap:'wrap'}}>
                      <span style={{fontSize:10,padding:'3px 9px',background:accentBg,color:accent,borderRadius:999,fontWeight:700,letterSpacing:'0.02em',border:'1px solid '+accentBorder}}>
                        {isZero?'🔴':'🟡'} {badgeLabel}
                      </span>
                      <span style={{fontSize:10,padding:'2px 8px',background:'#F3F4F6',color:'#6B7280',borderRadius:6,fontWeight:600,textTransform:'uppercase',letterSpacing:'0.04em'}}>
                        {p.brand||'—'}
                      </span>
                    </div>
                    <div style={{fontSize:14,fontWeight:600,color:'#111827',lineHeight:1.35,wordBreak:'break-word'}}>
                      {p.name}
                    </div>
                  </div>
                  <div style={{display:'flex',alignItems:'center',gap:10,flexShrink:0}}>
                    <div style={{textAlign:'center',minWidth:64}}>
                      <div style={{fontSize:10,color:'#6B7280',fontWeight:600,marginBottom:3,letterSpacing:'0.04em'}}>ALFONSO</div>
                      <div style={{fontSize:18,fontWeight:700,color:isZero?'#DC2626':'#EA580C',fontVariantNumeric:'tabular-nums'}}>{isZero?'0':qa}</div>
                    </div>
                    <div style={{fontSize:22,color:'#9CA3AF',fontWeight:300}}>←</div>
                    <div style={{textAlign:'center',minWidth:64}}>
                      <div style={{fontSize:10,color:'#6B7280',fontWeight:600,marginBottom:3,letterSpacing:'0.04em'}}>SENADOR</div>
                      <div style={{fontSize:18,fontWeight:700,color:'#16A34A',fontVariantNumeric:'tabular-nums'}}>{qs}</div>
                    </div>
                  </div>
                </div>
              );
            })}
          </div>
        )}
        {totalPages > 1 && (
          <div style={{display:'flex',justifyContent:'center',alignItems:'center',gap:10,marginTop:18,paddingTop:14,borderTop:'1px solid #F3F4F6'}}>
            <button onClick={function(){setPageIdx(Math.max(0, safePageIdx - 1));}}
              disabled={safePageIdx===0}
              style={{padding:'8px 16px',border:'1px solid #E5E7EB',background:safePageIdx===0?'#F9FAFB':'#fff',borderRadius:8,cursor:safePageIdx===0?'not-allowed':'pointer',color:safePageIdx===0?'#D1D5DB':'#374151',fontWeight:600,fontSize:13}}>
              ← Anterior
            </button>
            <span style={{fontSize:12,color:'#6B7280',fontWeight:600,minWidth:100,textAlign:'center'}}>
              Pg {safePageIdx+1} de {totalPages}
            </span>
            <button onClick={function(){setPageIdx(Math.min(totalPages-1, safePageIdx + 1));}}
              disabled={safePageIdx===totalPages-1}
              style={{padding:'8px 16px',border:'1px solid #E5E7EB',background:safePageIdx===totalPages-1?'#F9FAFB':'#fff',borderRadius:8,cursor:safePageIdx===totalPages-1?'not-allowed':'pointer',color:safePageIdx===totalPages-1?'#D1D5DB':'#374151',fontWeight:600,fontSize:13}}>
              Próxima →
            </button>
          </div>
        )}
        </div>)}

        {transferTab === 'historico' && (<div>
          {/* [v224.40] Histórico filtros · search + status dropdown */}
          <div style={{display:'flex',gap:10,alignItems:'center',flexWrap:'wrap',marginBottom:14}}>
            <input type="text" value={historicoSearch}
              onChange={function(e){setHistoricoSearch(e.target.value); setHistoricoPage(0);}}
              placeholder="🔍 Buscar produto ou nº transferência..."
              style={{flex:'1 1 240px',minWidth:180,padding:'8px 12px',border:'1px solid #E5E7EB',borderRadius:8,fontSize:13,outline:'none'}}/>
            <select value={historicoStatus}
              onChange={function(e){setHistoricoStatus(e.target.value); setHistoricoPage(0);}}
              style={{padding:'8px 10px',border:'1px solid #E5E7EB',borderRadius:8,fontSize:12,background:'#fff',fontWeight:600,cursor:'pointer',outline:'none'}}>
              <option value="all">Todos status</option>
              <option value="solicitada">🟡 Solicitada</option>
              <option value="aprovada">🔵 Aprovada</option>
              <option value="em_transito">🟦 Em trânsito</option>
              <option value="recebida">🟢 Recebida</option>
              <option value="cancelada">🔴 Cancelada</option>
            </select>
          </div>

          {/* Tabela histórico */}
          {loadingHistorico ? (
            <div style={{padding:30,textAlign:'center',color:'#6B7280',fontSize:13}}>Carregando histórico...</div>
          ) : historicoFiltrado.length === 0 ? (
            <div style={{color:'#16A34A',fontSize:14,padding:'24px 4px',textAlign:'center',background:'#F0FDF4',borderRadius:10,border:'1px dashed #BBF7D0'}}>
              {transferHistorico.length === 0 ? 'Nenhuma transferência últimos 30 dias' : '🔍 Nenhuma transferência encontrada com filtros'}
            </div>
          ) : (
            <div style={{overflowX:'auto'}}>
              <table style={{width:'100%',fontSize:12,borderCollapse:'collapse'}}>
                <thead>
                  <tr style={{borderBottom:'2px solid #E5E7EB',color:'#6B7280',fontSize:11}}>
                    <th style={{textAlign:'left',padding:'8px 6px',fontWeight:600}}>Nº</th>
                    <th style={{textAlign:'left',padding:'8px 6px',fontWeight:600}}>Produto</th>
                    <th style={{textAlign:'left',padding:'8px 6px',fontWeight:600}}>Rota</th>
                    <th style={{textAlign:'right',padding:'8px 6px',fontWeight:600}}>Qty</th>
                    <th style={{textAlign:'center',padding:'8px 6px',fontWeight:600}}>Status</th>
                    <th style={{textAlign:'left',padding:'8px 6px',fontWeight:600}}>Solicitou</th>
                    <th style={{textAlign:'left',padding:'8px 6px',fontWeight:600}}>Recebeu</th>
                  </tr>
                </thead>
                <tbody>
                  {historicoPagina.map(function(t){
                    var prod = (products||[]).find(function(p){return p.id === t.product_id;});
                    var fromW = (warehouses||[]).find(function(w){return w.id === t.from_warehouse_id;});
                    var toW = (warehouses||[]).find(function(w){return w.id === t.to_warehouse_id;});
                    var reqUser = (allUsers||[]).find(function(u){return u.id === t.requested_by;});
                    var recUser = (allUsers||[]).find(function(u){return u.id === t.received_by;});
                    var hStatusBg = {'solicitada':'#FEF3C7','aprovada':'#E0E7FF','em_transito':'#DBEAFE','recebida':'#D1FAE5','cancelada':'#FEE2E2'}[t.status] || '#F3F4F6';
                    var hStatusFg = {'solicitada':'#92400E','aprovada':'#3730A3','em_transito':'#1E40AF','recebida':'#065F46','cancelada':'#991B1B'}[t.status] || '#374151';
                    var fmtH = function(iso){ if(!iso) return '—'; var d = new Date(iso); return d.toLocaleDateString('pt-BR',{day:'2-digit',month:'2-digit'}) + ' ' + d.toLocaleTimeString('pt-BR',{hour:'2-digit',minute:'2-digit'}); };
                    return (
                      <tr key={t.id} style={{borderBottom:'1px solid #F3F4F6'}}>
                        <td style={{padding:'9px 6px',fontWeight:600,color:'#1B2A4A',fontSize:11}}>{t.transfer_number}</td>
                        <td style={{padding:'9px 6px',color:'#111827',maxWidth:200,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{prod ? prod.name : '—'}</td>
                        <td style={{padding:'9px 6px',color:'#6B7280',fontSize:11,whiteSpace:'nowrap'}}>{(fromW?fromW.name:'?')} → {(toW?toW.name:'?')}</td>
                        <td style={{padding:'9px 6px',textAlign:'right',fontWeight:600,fontVariantNumeric:'tabular-nums'}}>{t.quantity_requested}{t.quantity_received != null && t.quantity_received !== t.quantity_requested ? ' / '+t.quantity_received : ''}</td>
                        <td style={{padding:'9px 6px',textAlign:'center'}}>
                          <span style={{padding:'2px 8px',borderRadius:999,fontSize:10,fontWeight:600,background:hStatusBg,color:hStatusFg}}>{t.status}</span>
                        </td>
                        <td style={{padding:'9px 6px',color:'#374151',fontSize:11}}>
                          <div style={{fontWeight:600}}>{reqUser ? reqUser.name : '—'}</div>
                          <div style={{color:'#9CA3AF',fontSize:10}}>{fmtH(t.requested_at || t.created_at)}</div>
                        </td>
                        <td style={{padding:'9px 6px',color:'#374151',fontSize:11}}>
                          <div style={{fontWeight:600}}>{recUser ? recUser.name : (t.cancelled_by ? '— cancelada' : '—')}</div>
                          <div style={{color:'#9CA3AF',fontSize:10}}>{fmtH(t.received_at || t.cancelled_at)}</div>
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          )}

          {/* Paginação histórico */}
          {historicoTotalPages > 1 && (
            <div style={{display:'flex',justifyContent:'center',alignItems:'center',gap:10,marginTop:14,paddingTop:12,borderTop:'1px solid #F3F4F6'}}>
              <button onClick={function(){setHistoricoPage(Math.max(0, historicoSafePage-1));}} disabled={historicoSafePage===0}
                style={{padding:'7px 14px',border:'1px solid #E5E7EB',background:historicoSafePage===0?'#F9FAFB':'#fff',borderRadius:8,cursor:historicoSafePage===0?'not-allowed':'pointer',color:historicoSafePage===0?'#D1D5DB':'#374151',fontWeight:600,fontSize:12}}>← Anterior</button>
              <span style={{fontSize:12,color:'#6B7280',fontWeight:600,minWidth:100,textAlign:'center'}}>Pg {historicoSafePage+1} de {historicoTotalPages}</span>
              <button onClick={function(){setHistoricoPage(Math.min(historicoTotalPages-1, historicoSafePage+1));}} disabled={historicoSafePage===historicoTotalPages-1}
                style={{padding:'7px 14px',border:'1px solid #E5E7EB',background:historicoSafePage===historicoTotalPages-1?'#F9FAFB':'#fff',borderRadius:8,cursor:historicoSafePage===historicoTotalPages-1?'not-allowed':'pointer',color:historicoSafePage===historicoTotalPages-1?'#D1D5DB':'#374151',fontWeight:600,fontSize:12}}>Próxima →</button>
            </div>
          )}
        </div>)}

      </div>

    </div>
    );
  }

  if(user.role==='financeiro') return(
    <div>
      <div style={{marginBottom:24}}><div style={{fontSize:13,color:'#9CA3AF'}}>Olá,</div><div style={{fontSize:24,fontWeight:700}}>{user.name}</div></div>
      <div style={{display:'grid',gridTemplateColumns:'repeat(3,1fr)',gap:16,marginBottom:24}}>
        <div className="stat-card"><div className="stat-label">Vencendo Hoje</div><div className="stat-value" style={{color:'#2563EB'}}>{todayPay.length}</div></div>
        <div className="stat-card"><div className="stat-label">Em Atraso (Pagar)</div><div className="stat-value" style={{color:'#DC2626'}}>{overduePay.length}</div></div>
        <div className="stat-card"><div className="stat-label">A Receber (Pendente)</div><div className="stat-value">{fmt(receivables.filter(r=>r.status==='Pendente').reduce((s,r)=>s+r.value,0))}</div></div>
      </div>
      {overduePay.map(p=><div key={p.id} className="alert-danger" style={{marginBottom:8,fontSize:13}}>{p.description} — Venceu {fmtDate(p.due)} — {fmt(p.value)}</div>)}
    </div>
  );

  return null;
}

  window.ZNX = window.ZNX || {};
  window.ZNX.components = window.ZNX.components || {};
  window.ZNX.components.Dashboard = Dashboard;
  window.Dashboard = Dashboard;

  window.ZNX.refactor_phase_6_loaded = window.ZNX.refactor_phase_6_loaded || {};
  window.ZNX.refactor_phase_6_loaded.Dashboard = true;

})();
