// ═══════════════════════════════════════════════════════
// BAUKO CRM v2 — Proposta (modal lifecycle + WhatsApp send)
// ═══════════════════════════════════════════════════════
/* global React, CRM_DATA, Modal, Badge, fR, fDate, fDateTime */
const { useState: usePropState, useMemo: usePropMemo } = React;

// ── helpers ──────────────────────────────────────────────────────────────────
const TIMELINE_ICON = {
  criada:        { icon: "file-plus",   color: "var(--tx-3)" },
  aprovacao_int: { icon: "shield-check", color: "var(--info)" },
  enviada_wpp:   { icon: "send",        color: "var(--grn)" },
  enviada:       { icon: "send",        color: "var(--grn)" },
  vista:         { icon: "eye",         color: "var(--info)" },
  download:      { icon: "download",    color: "var(--info)" },
  comentario:    { icon: "message-square", color: "var(--warn)" },
  aceita:        { icon: "check-circle-2", color: "var(--ok)" },
  pedido:        { icon: "package",     color: "var(--grn)" },
  perdida:       { icon: "x-circle",    color: "var(--danger)" },
  gerente_aprovou: { icon: "check-circle-2", color: "var(--ok)" },
  gerente_recusou: { icon: "x-circle",      color: "var(--danger)" },
  pdf_baixado:     { icon: "file-down",     color: "var(--info)" },
  enviada_email:   { icon: "mail",          color: "var(--grn)" },
  aceite_manual:   { icon: "pen-line",      color: "var(--ok)" },
  cliente_aprovou: { icon: "thumbs-up",     color: "var(--ok)" },
  em_negociacao:   { icon: "handshake",      color: "var(--warn)" },
  envio_confirmado: { icon: "send",           color: "var(--grn)" },
  pedido_enviado_cliente:  { icon: "send",      color: "var(--grn)" },
  pedido_assinado_cliente: { icon: "pen-line",  color: "var(--ok)"  },
  cancelado_correcao:        { icon: "rotate-ccw",  color: "var(--warn)"   },
  cancelado_apos_assinatura: { icon: "alert-octagon", color: "var(--danger)" },
};

const TIMELINE_LABEL = {
  criada: "Proposta criada",
  aprovacao_int: "Aprovação interna",
  enviada_wpp: "Enviada por WhatsApp",
  enviada: "Enviada por e-mail",
  vista: "Cliente visualizou",
  download: "Cliente baixou PDF",
  comentario: "Comentário do cliente",
  aceita: "Proposta aceita",
  pedido: "Pedido gerado",
  perdida: "Proposta recusada",
  gerente_aprovou: "Gerente aprovou",
  gerente_recusou: "Gerente recusou",
  pdf_baixado: "PDF baixado",
  enviada_email: "Enviada por e-mail",
  aceite_manual: "Aceite manual registrado",
  cliente_aprovou: "Cliente aprovou (link)",
  em_negociacao:   "Em negociação",
  envio_confirmado: "Envio confirmado",
  pedido_enviado_cliente:  "Pedido enviado ao cliente",
  pedido_assinado_cliente: "Cliente assinou o pedido",
  cancelado_correcao:        "Pedido cancelado para correção",
  cancelado_apos_assinatura: "Pedido cancelado após assinatura",
};

// ── Constantes de negócio ────────────────────────────────────────────────────
// Unidades Bauko: fonte única em CRM_CONFIG.getFiliaisAtivas() — lista SP
// "ConfigCRM_Filiais". Fallback inline roda só se CRM_CONFIG não carregou.
// Refatoração 2026-05-16: elimina duplicação com pedido-publica.html:250-273.
function getUnidadesBauko() {
  if (window.CRM_CONFIG && CRM_CONFIG.getFiliaisAtivas) {
    var filiais = CRM_CONFIG.getFiliaisAtivas();
    if (filiais && filiais.length > 0) return filiais.map(function(f){ return f.Title; });
  }
  return ['Bauko Osasco - SP','Bauko Rio Claro - SP','Bauko Serra - ES','Bauko Tanguá - RJ'];
}
const UNIDADES_BAUKO = getUnidadesBauko();

// ── ConfirmarEnvioModal ───────────────────────────────────────────────────────
function ConfirmarEnvioModal({ open, onClose, onConfirm }) {
  const [modalidade, setModalidade] = usePropState('WhatsApp');
  const [dataEnvio,  setDataEnvio]  = usePropState('');

  React.useEffect(() => {
    if (open) {
      setModalidade('WhatsApp');
      setDataEnvio(new Date().toISOString().slice(0, 10));
    }
  }, [open]);

  if (!open) return null;
  return (
    <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,.55)', zIndex: 10001,
      display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16 }}
      onClick={e => { if (e.target === e.currentTarget) onClose(); }}>
      <div style={{ background: 'var(--surface)', borderRadius: 'var(--r-lg)', padding: '24px 28px',
        width: '100%', maxWidth: 420, boxShadow: 'var(--shadow-3)', display: 'flex', flexDirection: 'column', gap: 18 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <i data-lucide="send" style={{ width: 18, height: 18, color: 'var(--grn)' }}></i>
          <span style={{ font: '600 15px/1 var(--ff-body)', color: 'var(--tx)' }}>Confirmar envio ao cliente</span>
        </div>
        <div className="f">
          <label>Modalidade de envio</label>
          <select className="inp select" value={modalidade} onChange={e => setModalidade(e.target.value)}>
            <option value="WhatsApp">WhatsApp</option>
            <option value="E-mail">E-mail</option>
            <option value="Outro">Outro</option>
          </select>
        </div>
        <div className="f">
          <label>Data do envio</label>
          <input type="date" className="inp" value={dataEnvio} onChange={e => setDataEnvio(e.target.value)} />
        </div>
        <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', marginTop: 4 }}>
          <button className="btn btn-ghost" onClick={onClose}>Cancelar</button>
          <button className="btn btn-primary"
            onClick={() => dataEnvio && onConfirm(modalidade, dataEnvio)}>
            <i data-lucide="check" style={{ width: 14, height: 14 }}></i> Confirmar
          </button>
        </div>
      </div>
    </div>
  );
}

// ── EmitirPedidoModal ─────────────────────────────────────────────────────────
function EmitirPedidoModal({ open, onClose, prop, cli, itens, valorTotal, addTimelineEvent, onSaved }) {
  const [unidade,      setUnidade]      = usePropState('');
  const [notas,        setNotas]        = usePropState('');
  const [saving,       setSaving]       = usePropState(false);
  const [erro,         setErro]         = usePropState(null);
  const [pedidoSalvo,  setPedidoSalvo]  = usePropState(null);
  // Condição de financiamento — estruturado
  const [finTipo,      setFinTipo]      = usePropState('');       // 'avista' | 'financiamento' | 'outro'
  const [finBanco,     setFinBanco]     = usePropState('');
  const [finMod,       setFinMod]       = usePropState('');       // 'CDC' | 'Finame' | 'Leasing' | 'outro'
  const [finModOutro,  setFinModOutro]  = usePropState('');
  const [finEntrada,   setFinEntrada]   = usePropState('');
  const [finEntTipo,   setFinEntTipo]   = usePropState('fixo');   // 'fixo' | 'percentual'
  const [finOutro,     setFinOutro]     = usePropState('');
  // H1: lock síncrono evita clique duplo criando pedidos duplicados
  const _emitLock = React.useRef(false);

  React.useEffect(() => {
    if (open) {
      setUnidade(''); setNotas(''); setErro(null); setPedidoSalvo(null);
      setFinTipo(''); setFinBanco(''); setFinMod(''); setFinModOutro('');
      setFinEntrada(''); setFinEntTipo('fixo'); setFinOutro('');
      _emitLock.current = false;
    }
  }, [open]);

  // Gera string legível de condição de financiamento
  function buildPgtoCondicao() {
    if (finTipo === 'avista') return 'À vista';
    if (finTipo === 'financiamento') {
      var parts = ['Financiamento bancário'];
      if (finBanco.trim()) parts.push(finBanco.trim());
      var mod = finMod === 'outro' ? (finModOutro.trim() || 'Outro') : finMod;
      if (mod) parts.push(mod);
      if (finEntrada.trim()) {
        var ent = finEntTipo === 'percentual'
          ? finEntrada.trim() + '% de entrada'
          : 'Entrada: R$ ' + finEntrada.trim();
        parts.push(ent);
      }
      return parts.join(' · ');
    }
    if (finTipo === 'outro') return finOutro.trim();
    return '';
  }

  async function handleEmitir() {
    // H1: bloqueia re-entrada síncrona (clique duplo)
    if (_emitLock.current || saving) return;
    _emitLock.current = true;
    if (!unidade) { setErro('Selecione a unidade Bauko responsável.'); _emitLock.current = false; return; }
    if (!finTipo) { setErro('Selecione a condição de financiamento.'); _emitLock.current = false; return; }
    if (finTipo === 'financiamento' && !finMod) { setErro('Selecione a modalidade de financiamento.'); _emitLock.current = false; return; }
    if (finTipo === 'financiamento' && finMod === 'outro' && !finModOutro.trim()) { setErro('Especifique a modalidade.'); _emitLock.current = false; return; }
    if (finTipo === 'outro' && !finOutro.trim()) { setErro('Especifique a condição de pagamento.'); _emitLock.current = false; return; }
    var pgtoCondicao = buildPgtoCondicao();
    setSaving(true); setErro(null);

    var pedidoId = 'PED-' + String(Date.now()).slice(-6);
    var valorNum = valorTotal || prop.valor || 0;
    var pedidoObj = {
      id:            pedidoId,
      proposta_id:   prop.id,
      op_id:         prop.op_id || '',
      cliente_id:    cli ? cli.id : '',
      vendedor_id:   prop.responsavel_id || '',
      unidade_bauko: unidade,
      valor:         String(valorNum),
      status:        'emitido',
      data:          new Date().toISOString(),
      pgto_condicao: pgtoCondicao,
      notas:         notas.trim(),
      itens:         (itens || []).map(function(it){ return { sku: it.sku, familia: it.familia||'', desc: it.desc||'', qtd: it.qtd||it.quantidade||1, total: it.total||0, desconto: it.desconto||0, impostos: it.icms_saida||it.impostos||0, local_entrega: it.frete_tipo||it.local_entrega||'', garantia: it.garantia||'', prazo: it.prazo||'' }; }),
      timeline:      [],
    };
    // Mantém valor como número em memória para cálculos e formatação
    pedidoObj._valorNum = valorNum;

    try {
      // PESSIMISTIC: só atualiza UI/estado local depois da confirmação do SharePoint.
      // Sem _spId não há como recuperar/editar o pedido depois — tratamos como falha.
      const pedidoCriado = await CRM_API.addItem('CRMPedidos', pedidoObj);
      if (!pedidoCriado || !pedidoCriado.id) {
        throw new Error('SharePoint não retornou ID do pedido criado');
      }
      pedidoObj._spId = String(pedidoCriado.id);
      // Push local SÓ após confirmação (evita "pedido fantasma" em caso de falha)
      if (window.CRM_DATA && Array.isArray(CRM_DATA.pedidos)) CRM_DATA.pedidos.push(pedidoObj);
      addTimelineEvent('pedido', pedidoId + ' · ' + unidade);
      if (prop._spId) {
        // Best-effort: status da proposta é secundário; não bloqueia sucesso do pedido
        await CRM_API.updateItem('Propostas', prop._spId, { status: 'pedido' }).catch(function(e){
          console.warn('[EmitirPedido] proposta status update falhou (não-crítico):', e && e.message);
        });
      }
      setPedidoSalvo(pedidoObj);
      if (onSaved) onSaved(pedidoObj);
    } catch(e) {
      console.error('[EmitirPedido]', e);
      setErro('Erro ao emitir pedido: ' + (e && e.message ? e.message : 'tente novamente'));
    } finally {
      setSaving(false);
      _emitLock.current = false;
    }
  }

  if (!open) return null;

  var cliNome = cli ? cli.razao : '—';

  return (
    <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,.55)', zIndex: 10000, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16 }}
      onClick={e => { if (e.target === e.currentTarget && !saving) onClose(); }}>
      <div style={{ background: 'var(--surface)', borderRadius: 'var(--r-lg)', padding: '28px 32px', width: '100%', maxWidth: 520, boxShadow: 'var(--shadow-3)', display: 'flex', flexDirection: 'column', gap: 18 }}>

        {/* Header */}
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <i data-lucide="package" style={{ width: 18, height: 18, color: 'var(--grn)' }}></i>
            <span style={{ font: '600 15px/1 var(--ff-body)', color: 'var(--tx)' }}>Emitir Pedido</span>
          </div>
          {!saving && (
            <button className="btn btn-ghost" style={{ padding: '4px 8px' }} onClick={onClose}>
              <i data-lucide="x" style={{ width: 16, height: 16 }}></i>
            </button>
          )}
        </div>

        {/* Resumo */}
        <div style={{ background: 'var(--surface-2)', border: '1px solid var(--border)', borderRadius: 'var(--r-md)', padding: '14px 16px', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '8px 20px' }}>
          {[
            ['Proposta', prop.id],
            ['Cliente',  cliNome],
            ['Itens',    (itens||[]).length + ' equipamento(s)'],
            ['Valor',    fR(valorTotal || prop.valor || 0)],
          ].map(function([lbl, val]) {
            return (
              <div key={lbl}>
                <div style={{ font: '600 9px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.08em', color: 'var(--tx-3)', marginBottom: 3 }}>{lbl}</div>
                <div style={{ font: '500 12px/1.2 var(--ff-mono)', color: 'var(--tx)' }}>{val}</div>
              </div>
            );
          })}
        </div>

        {pedidoSalvo ? (
          /* ── Estado: sucesso ── */
          <div style={{ textAlign: 'center', padding: '16px 0' }}>
            <div style={{ font: '400 36px/1 var(--ff-display)', color: 'var(--grn)', marginBottom: 10 }}>✓</div>
            <div style={{ font: '600 14px/1 var(--ff-body)', color: 'var(--tx)', marginBottom: 6 }}>Pedido emitido!</div>
            <div style={{ font: '400 22px/1 var(--ff-display)', color: 'var(--grn)', marginBottom: 4 }}>{pedidoSalvo.id}</div>
            <div style={{ font: '400 11px/1.4 var(--ff-body)', color: 'var(--tx-3)' }}>{pedidoSalvo.unidade_bauko}</div>
            <button className="btn btn-secondary" style={{ marginTop: 20 }} onClick={onClose}>Fechar</button>
          </div>
        ) : (
          /* ── Formulário ── */
          <>
            {erro && (
              <div style={{ padding: '9px 13px', background: 'var(--danger-050, #fef2f2)', border: '1px solid var(--danger)', borderRadius: 'var(--r-md)', font: '400 12px/1.4 var(--ff-body)', color: 'var(--danger)' }}>
                {erro}
              </div>
            )}

            {/* Unidade Bauko */}
            <div className="f">
              <label>Unidade Bauko responsável pelo faturamento <span style={{ color: 'var(--danger)' }}>*</span></label>
              <select className="inp select" value={unidade} onChange={e => setUnidade(e.target.value)}>
                <option value="">— Selecione a filial —</option>
                {UNIDADES_BAUKO.map(function(u){ return <option key={u} value={u}>{u}</option>; })}
              </select>
            </div>

            {/* Condição de Financiamento — estruturado */}
            <div className="f">
              <label>Condição de Financiamento <span style={{ color: 'var(--danger)' }}>*</span></label>
              {/* Opções principais */}
              <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginTop: 4 }}>
                {[
                  { v: 'avista',        l: 'À vista' },
                  { v: 'financiamento', l: 'Financiamento bancário' },
                  { v: 'outro',         l: 'Outro (especificar)' },
                ].map(function(opt) {
                  return (
                    <label key={opt.v} style={{ display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer', font: '400 13px/1 var(--ff-body)', color: 'var(--tx)', padding: '6px 0' }}>
                      <input type="radio" name="finTipo" value={opt.v} checked={finTipo === opt.v}
                        onChange={function() { setFinTipo(opt.v); }}
                        style={{ accentColor: 'var(--grn)', width: 14, height: 14, cursor: 'pointer' }} />
                      {opt.l}
                    </label>
                  );
                })}
              </div>

              {/* Sub-campos: Financiamento bancário */}
              {finTipo === 'financiamento' && (
                <div style={{ marginTop: 12, padding: '14px 16px', background: 'var(--surface-2)', border: '1px solid var(--border)', borderRadius: 'var(--r-md)', display: 'flex', flexDirection: 'column', gap: 12 }}>
                  {/* Banco */}
                  <div>
                    <div style={{ font: '600 10px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.06em', color: 'var(--tx-3)', marginBottom: 6 }}>Banco</div>
                    <input className="inp" value={finBanco} onChange={function(e){ setFinBanco(e.target.value); }}
                      placeholder="ex: BKB, Bradesco, Sicoob…" style={{ fontSize: 13 }} />
                  </div>
                  {/* Modalidade */}
                  <div>
                    <div style={{ font: '600 10px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.06em', color: 'var(--tx-3)', marginBottom: 6 }}>Modalidade</div>
                    <div style={{ display: 'flex', flexWrap: 'wrap', gap: '6px 16px' }}>
                      {['CDC', 'Finame', 'Leasing', 'outro'].map(function(m) {
                        return (
                          <label key={m} style={{ display: 'flex', alignItems: 'center', gap: 6, cursor: 'pointer', font: '400 12px/1 var(--ff-body)', color: 'var(--tx)' }}>
                            <input type="radio" name="finMod" value={m} checked={finMod === m}
                              onChange={function() { setFinMod(m); }}
                              style={{ accentColor: 'var(--grn)', width: 13, height: 13 }} />
                            {m === 'outro' ? 'Outro' : m}
                          </label>
                        );
                      })}
                    </div>
                    {finMod === 'outro' && (
                      <input className="inp" value={finModOutro} onChange={function(e){ setFinModOutro(e.target.value); }}
                        placeholder="Especifique a modalidade…" style={{ marginTop: 8, fontSize: 13 }} />
                    )}
                  </div>
                  {/* Entrada */}
                  <div>
                    <div style={{ font: '600 10px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.06em', color: 'var(--tx-3)', marginBottom: 6 }}>Entrada <span style={{ font: '400 9px/1 var(--ff-body)', color: 'var(--tx-3)', textTransform: 'none' }}>(opcional)</span></div>
                    <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
                      <input className="inp" type="number" min="0" value={finEntrada} onChange={function(e){ setFinEntrada(e.target.value); }}
                        placeholder={finEntTipo === 'percentual' ? '% de entrada' : 'Valor em R$'}
                        style={{ fontSize: 13, flex: 1 }} />
                      {/* Toggle fixo / percentual */}
                      <div style={{ display: 'flex', border: '1px solid var(--border-2)', borderRadius: 'var(--r-sm)', overflow: 'hidden', flexShrink: 0 }}>
                        {[{ v: 'fixo', l: 'R$' }, { v: 'percentual', l: '%' }].map(function(t) {
                          var active = finEntTipo === t.v;
                          return (
                            <button key={t.v} type="button"
                              onClick={function() { setFinEntTipo(t.v); }}
                              style={{ padding: '6px 12px', background: active ? 'var(--grn)' : 'var(--surface)', color: active ? '#fff' : 'var(--tx-2)', border: 'none', cursor: 'pointer', font: '600 12px/1 var(--ff-mono)', transition: 'background .12s' }}>
                              {t.l}
                            </button>
                          );
                        })}
                      </div>
                    </div>
                  </div>
                </div>
              )}

              {/* Sub-campo: Outro */}
              {finTipo === 'outro' && (
                <input className="inp" value={finOutro} onChange={function(e){ setFinOutro(e.target.value); }}
                  placeholder="Especifique a condição de pagamento…"
                  style={{ marginTop: 8, fontSize: 13 }} />
              )}
            </div>

            {/* Notas */}
            <div className="f">
              <label>Notas internas <span style={{ font: '400 10px/1 var(--ff-body)', color: 'var(--tx-3)', marginLeft: 4 }}>(opcional)</span></label>
              <textarea className="inp" rows={3} value={notas} onChange={e => setNotas(e.target.value)}
                placeholder="Observações sobre entrega, instalação, condições especiais…"
                style={{ resize: 'vertical', fontFamily: 'var(--ff-body)', fontSize: 13 }} />
            </div>

            {/* Ações */}
            <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', paddingTop: 4 }}>
              <button className="btn btn-secondary" onClick={onClose} disabled={saving}>Cancelar</button>
              <button className="btn btn-primary" onClick={handleEmitir} disabled={saving}
                style={{ opacity: saving ? 0.6 : 1, gap: 6 }}>
                {saving
                  ? <><i data-lucide="loader" style={{ width: 13, height: 13 }}></i> Emitindo…</>
                  : <><i data-lucide="package" style={{ width: 13, height: 13 }}></i> Emitir Pedido</>}
              </button>
            </div>
          </>
        )}
      </div>
    </div>
  );
}

// ── CorrigirPedidoModal ──────────────────────────────────────────────────────
// Permite ao vendedor (dono) ou gerente cancelar um pedido emitido para refazê-lo.
// Cenários: emitido / enviado-não-assinado (cancelado_correcao) · já assinado (cancelado_apos_assinatura).
function CorrigirPedidoModal({ open, onClose, pedido, isAfterAssinatura, onConfirm }) {
  var _us = React.useState;
  var _motivo = _us(''),     motivo = _motivo[0],     setMotivo = _motivo[1];
  var _check  = _us(false),  check  = _check[0],      setCheck  = _check[1];
  var _saving = _us(false),  saving = _saving[0],     setSaving = _saving[1];
  var _erro   = _us(null),   erro   = _erro[0],       setErro   = _erro[1];

  React.useEffect(function() {
    if (open) { setMotivo(''); setCheck(false); setSaving(false); setErro(null); }
  }, [open]);
  React.useEffect(function() { try { if (typeof lucide !== 'undefined') lucide.createIcons(); } catch(e) {} });

  if (!open) return null;

  var motivoOk = motivo.trim().length >= 10;
  var podeConfirmar = motivoOk && check && !saving;

  function handleConfirmar() {
    if (!podeConfirmar) return;
    setSaving(true); setErro(null);
    Promise.resolve(onConfirm(motivo.trim()))
      .then(function() { /* parent fecha o modal */ })
      .catch(function(e) {
        setSaving(false);
        setErro('Falha ao cancelar: ' + (e && e.message ? e.message : 'erro desconhecido'));
      });
  }

  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.6)', zIndex:10100, display:'flex', alignItems:'center', justifyContent:'center', padding:16 }}
      onClick={function(e){ if (e.target === e.currentTarget && !saving) onClose(); }}>
      <div style={{ background:'var(--surface)', borderRadius:'var(--r-lg)', padding:'28px 32px', width:'100%', maxWidth:520, boxShadow:'var(--shadow-3)' }}>
        {/* Header */}
        <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:16 }}>
          <div style={{ width:36, height:36, borderRadius:'50%', background: isAfterAssinatura ? '#fef2f2' : '#fff7ed', display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
            <i data-lucide={isAfterAssinatura ? 'alert-octagon' : 'rotate-ccw'} style={{ width:18, height:18, color: isAfterAssinatura ? 'var(--danger)' : '#c2410c' }}></i>
          </div>
          <div>
            <div style={{ font:'600 15px/1.2 var(--ff-body)', color:'var(--tx)' }}>
              Corrigir pedido {pedido && pedido.id ? pedido.id : ''}
            </div>
            <div style={{ font:'400 11px/1.4 var(--ff-mono)', color:'var(--tx-3)', marginTop:3 }}>
              O pedido atual será cancelado. Você poderá emitir um novo em seguida.
            </div>
          </div>
        </div>

        {/* Aviso cenário 3 */}
        {isAfterAssinatura && (
          <div style={{ background:'#fef2f2', border:'1px solid var(--danger)', borderRadius:'var(--r-sm)', padding:'12px 14px', marginBottom:16, display:'flex', gap:10, alignItems:'flex-start' }}>
            <i data-lucide="alert-triangle" style={{ width:16, height:16, color:'var(--danger)', flexShrink:0, marginTop:1 }}></i>
            <div style={{ font:'400 12px/1.55 var(--ff-body)', color:'#7f1d1d' }}>
              <strong>Atenção:</strong> este pedido <strong>já foi assinado pelo cliente</strong>.
              O gerente será notificado deste cancelamento. Após cancelar, lembre-se de avisar o cliente diretamente
              sobre a correção antes de enviar o novo link.
            </div>
          </div>
        )}

        {/* Aviso cenário 2 (genérico) */}
        {!isAfterAssinatura && (
          <div style={{ background:'#fff7ed', border:'1px solid #fed7aa', borderRadius:'var(--r-sm)', padding:'12px 14px', marginBottom:16, display:'flex', gap:10, alignItems:'flex-start' }}>
            <i data-lucide="info" style={{ width:16, height:16, color:'#c2410c', flexShrink:0, marginTop:1 }}></i>
            <div style={{ font:'400 12px/1.55 var(--ff-body)', color:'#7c2d12' }}>
              Se o cliente já recebeu o link deste pedido, avise-o diretamente sobre a correção antes de enviar o novo link.
              O link antigo deixará de aceitar assinatura automaticamente.
            </div>
          </div>
        )}

        {/* Motivo */}
        <div style={{ marginBottom:14 }}>
          <label style={{ font:'600 10px/1 var(--ff-body)', textTransform:'uppercase', letterSpacing:'.07em', color:'var(--tx-3)', display:'block', marginBottom:6 }}>
            Motivo da correção <span style={{ color:'var(--danger)' }}>*</span>
            <span style={{ font:'400 9px/1 var(--ff-body)', color:'var(--tx-3)', textTransform:'none', marginLeft:6 }}>(mín. 10 caracteres)</span>
          </label>
          <textarea rows={3} value={motivo} onChange={function(e){ setMotivo(e.target.value); }}
            placeholder="Ex: valor incorreto, máquina trocada, condição de pagamento errada…"
            style={{ width:'100%', padding:'9px 11px', border:'1px solid var(--border-2)', borderRadius:'var(--r-sm)', background:'var(--surface)', fontFamily:'var(--ff-body)', fontSize:13, color:'var(--tx)', outline:'none', boxSizing:'border-box', resize:'vertical', lineHeight:1.5 }} />
          <div style={{ font:'400 10px/1.2 var(--ff-body)', color: motivoOk ? 'var(--tx-3)' : 'var(--danger)', marginTop:4 }}>
            {motivo.trim().length}/10 caracteres
          </div>
        </div>

        {/* Checkbox confirmação */}
        <label style={{ display:'flex', alignItems:'flex-start', gap:10, cursor:'pointer', marginBottom:18, padding:'12px 14px', background:'var(--surface-2)', border:'1px solid var(--border)', borderRadius:'var(--r-sm)' }}>
          <input type="checkbox" checked={check} onChange={function(e){ setCheck(e.target.checked); }}
            style={{ marginTop:2, width:15, height:15, accentColor:'var(--warn)', flexShrink:0, cursor:'pointer' }} />
          <span style={{ font:'400 12px/1.5 var(--ff-body)', color:'var(--tx-2)' }}>
            Confirmo que o pedido <strong>{pedido && pedido.id ? pedido.id : ''}</strong> será cancelado
            e um novo pedido será emitido em seguida.
          </span>
        </label>

        {/* Erro */}
        {erro && (
          <div style={{ padding:'9px 13px', background:'#fef2f2', border:'1px solid var(--danger)', borderRadius:'var(--r-sm)', font:'400 12px/1.4 var(--ff-body)', color:'var(--danger)', marginBottom:12 }}>
            {erro}
          </div>
        )}

        {/* Ações */}
        <div style={{ display:'flex', gap:10, justifyContent:'flex-end', borderTop:'1px solid var(--border)', paddingTop:14 }}>
          <button className="btn btn-ghost" onClick={onClose} disabled={saving}>Cancelar</button>
          <button className="btn"
            disabled={!podeConfirmar}
            onClick={handleConfirmar}
            style={{
              background: podeConfirmar ? 'var(--warn)' : 'var(--border)',
              color: podeConfirmar ? '#fff' : 'var(--tx-3)',
              border:'none', cursor: podeConfirmar ? 'pointer' : 'not-allowed',
              gap:6, transition:'background .15s',
            }}>
            {saving
              ? <><i data-lucide="loader" style={{ width:13, height:13 }}></i> Cancelando…</>
              : <><i data-lucide="rotate-ccw" style={{ width:13, height:13 }}></i> Cancelar pedido e voltar para Em Negociação</>}
          </button>
        </div>
      </div>
    </div>
  );
}

// ── ProposalLifecycle ────────────────────────────────────────────────────────
// Horizontal step indicator: rascunho → aprovação → envio → negociação → pedido → pedido assinado
const LIFECYCLE_ICONS = {
  "file-edit":      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>,
  "check-circle-2": <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z"/><polyline points="9 12 11 14 15 10"/></svg>,
  "send":           <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>,
  "message-circle": <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>,
  "package":        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="16.5" y1="9.4" x2="7.5" y2="4.21"/><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg>,
  "receipt":        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 2 3 6 3 23 21 23 21 6 18 2 6 2"/><line x1="3" y1="6" x2="21" y2="6"/><line x1="12" y1="6" x2="12" y2="2"/><line x1="8" y1="10" x2="16" y2="10"/><line x1="8" y1="14" x2="16" y2="14"/></svg>,
  "file-check":     <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><polyline points="9 15 11 17 15 13"/></svg>,
  "x":              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>,
};
function ProposalLifecycle({ status, hasOrder, onStepClick, skipAprovacao }) {
  const steps = [
    { key: "rascunho",        label: "Rascunho",        icon: "file-edit" },
    { key: "aprovacao",       label: "Aprovação",       icon: "check-circle-2" },
    { key: "enviada",         label: "Envio",           icon: "send" },
    { key: "negociacao",      label: "Negociação",      icon: "message-circle" },
    { key: "pedido",          label: "Pedido",          icon: "package" },
    { key: "pedido_assinado", label: "Ped. Assinado",   icon: "file-check" },
  ];
  // statusKeys usados pelo onStepClick para navegação regressiva
  const statusKeys = ['rascunho', 'aguardando_aprovacao', 'aprovada', 'enviada', 'em_negociacao', 'pedido', 'pedido_assinado'];
  const _idxMap = {
    rascunho: 0, aguardando_aprovacao: 1, aprovada: 2, enviada: 2, em_negociacao: 3,
    pedido: 4, pedido_assinado: 5,
    faturamento: 5, // backward compat: propostas antigas com status faturamento → mesmo slot
    perdida: 3,
    cancelada: 0,
  };
  // H9: avisa em console se status fora do mapping (proposta corrompida ou status novo não previsto)
  if (status && !(status in _idxMap)) {
    console.warn('[CRM] ProposalLifecycle: status desconhecido:', status, '— renderizando como rascunho');
  }
  const idx = _idxMap[status] ?? 0;

  return (
    <div style={{ display: "flex", alignItems: "center", gap: 0, padding: "8px 4px" }}>
      {steps.map((s, i) => {
        const done = i < idx;
        const current = i === idx && status !== "perdida";
        const failed = status === "perdida" && i === 3;
        const isAprovacaoSkipped = skipAprovacao && s.key === "aprovacao";
        const canGoBack = !!onStepClick && i < idx && !isAprovacaoSkipped;
        const tone = failed ? "var(--danger)" : (done || current) ? "var(--grn)" : "var(--border-2)";
        const bg = failed ? "var(--danger-050)" : done ? "var(--grn)" : "var(--surface)";
        const iconColor = failed ? "var(--danger)" : current ? "var(--grn)" : done ? "#fff" : "var(--tx-3)";
        const borderWidth = current ? "3px" : "2px";
        return (
          <React.Fragment key={s.key}>
            <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 6, minWidth: 86 }}>
              <div
                style={{
                  width: 32, height: 32, borderRadius: "50%",
                  background: bg, border: `${borderWidth} solid ${tone}`,
                  display: "grid", placeItems: "center",
                  transition: "all 200ms",
                  cursor: canGoBack ? "pointer" : "default",
                }}
                onClick={canGoBack ? () => onStepClick(statusKeys[i], s.label) : undefined}
                title={canGoBack ? `Voltar para ${s.label}` : undefined}
              >
                {done && !failed
                  ? (<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12" /></svg>)
                  : (<span style={{ color: iconColor, display: 'contents' }}>{LIFECYCLE_ICONS[failed ? "x" : s.icon]}</span>)
                }
              </div>
              <div style={{
                font: "600 10px/1.1 var(--ff-body)", textTransform: "uppercase", letterSpacing: ".06em",
                color: current || done ? "var(--tx)" : "var(--tx-3)",
                textAlign: "center",
              }}>{s.label}</div>
            </div>
            {i < steps.length - 1 && (
              <div style={{
                flex: 1, height: 2, background: i < idx ? "var(--grn)" : "var(--border-2)",
                marginTop: -16, minWidth: 16,
              }}></div>
            )}
          </React.Fragment>
        );
      })}
    </div>
  );
}
window.ProposalLifecycle = ProposalLifecycle;

// ── ProposalTimeline ─────────────────────────────────────────────────────────
function ProposalTimeline({ events }) {
  if (!events.length) return (
    <div style={{ font: "400 12px/1.4 var(--ff-body)", color: "var(--tx-3)", padding: 8 }}>
      Sem eventos registrados ainda.
    </div>
  );
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 0, position: "relative" }}>
      <div style={{ position: "absolute", left: 11, top: 8, bottom: 8, width: 2, background: "var(--border)" }}></div>
      {events.slice().reverse().map((e, i) => {
        const meta = TIMELINE_ICON[e.tipo] || TIMELINE_ICON.criada;
        const autor = e.autor ? CRM_DATA.getUsuario(e.autor) : null;
        return (
          <div key={e.id} style={{ display: "flex", gap: 12, position: "relative", padding: "8px 0" }}>
            <div style={{
              width: 24, height: 24, borderRadius: "50%",
              background: "var(--surface)", border: `2px solid ${meta.color}`,
              display: "grid", placeItems: "center", flexShrink: 0, zIndex: 1,
            }}>
              <i data-lucide={meta.icon} style={{ width: 11, height: 11, color: meta.color }}></i>
            </div>
            <div style={{ flex: 1, paddingTop: 2 }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: 8 }}>
                <span style={{ font: "600 12px/1.2 var(--ff-body)", color: "var(--tx)" }}>
                  {TIMELINE_LABEL[e.tipo] || e.tipo}
                </span>
                <span style={{ font: "400 10px/1 var(--ff-mono)", color: "var(--tx-3)", whiteSpace: "nowrap" }}>
                  {fDateTime(e.data)}
                </span>
              </div>
              <div style={{ font: "400 12px/1.45 var(--ff-body)", color: "var(--tx-2)", marginTop: 4 }}>
                {e.detalhe}
              </div>
              {autor && (
                <div style={{ font: "400 10px/1 var(--ff-mono)", color: "var(--tx-3)", marginTop: 4 }}>
                  por {autor.nome}
                </div>
              )}
            </div>
          </div>
        );
      })}
    </div>
  );
}
window.ProposalTimeline = ProposalTimeline;

// ── Constantes ───────────────────────────────────────────────────────────────
const SALDO_OPTIONS = [
  'À Vista', 'Recursos Próprios', 'FINAME', 'CDC', 'Leasing', 'Consórcio',
  'Cartão BNDES', 'Pronamp', 'BB Agro', 'Parcelamento Direto',
  'Trade-in / Troca', 'Fundo / Linha Regional', 'Outros',
];

// ── PropostaModal ────────────────────────────────────────────────────────────
function PropostaModal({ open, onClose, propId, onOpenWpp, onDelete, initialTab }) {
  const [tab, setTab]                   = usePropState("doc");

  const [localStatus, setLocalStatus]   = usePropState(null);
  const [editDNet, setEditDNet]         = usePropState(0);
  const [editAprovMax, setEditAprovMax] = usePropState(0);
  const [editAprovDesc, setEditAprovDesc] = usePropState(0);
  const [prazos, setPrazos]             = usePropState({});
  // Envio ao cliente
  const [showEnvioForm, setShowEnvioForm] = usePropState(false);
  const [envioData, setEnvioData]         = usePropState('');
  const [envioCanal, setEnvioCanal]       = usePropState('email');
  const [envioObs, setEnvioObs]           = usePropState('');
  // Itens locais (fonte de verdade — sobrepõe mock, acumula do simulador)
  const [localItens, setLocalItens]       = usePropState([]);
  const loadedItensRef = React.useRef([]); // referência do último load — sync só dispara quando diferente

  const [orphanedItens, setOrphanedItens]   = usePropState([]); // itens da proposta removidos da oportunidade
  const [editValidade, setEditValidade]       = usePropState('');
  const [aprovMaxItems, setAprovMaxItems]     = usePropState({});
  // Linha do tempo local (atualiza sem reload de prop)
  const [localTimeline, setLocalTimeline]   = usePropState([]);
  // Modais de envio
  const [showWppModal, setShowWppModal]     = usePropState(false);
  const [wppPhone, setWppPhone]             = usePropState('');
  const [wppMsgIdx, setWppMsgIdx]           = usePropState(0);
  const [wppLink, setWppLink]               = usePropState('');
  const [wppLinkLoading, setWppLinkLoading] = usePropState(false);
  const [wppModeloSel, setWppModeloSel]     = usePropState(0);
  const [customWppMsg, setCustomWppMsg]     = usePropState('');
  const [showEmailModal, setShowEmailModal] = usePropState(false);
  const [emailDestinatario, setEmailDestinatario] = usePropState('');
  const [emailAssunto, setEmailAssunto]   = usePropState('');
  const [emailCorpoEdit, setEmailCorpoEdit] = usePropState('');
  const [emailEnviando, setEmailEnviando]   = usePropState(false);
  const [emailModeloSel, setEmailModeloSel] = usePropState(0);
  const [showPedidoModal, setShowPedidoModal] = usePropState(false);
  const [showConfirmarEnvio, setShowConfirmarEnvio] = usePropState(false);
  const [showExcluirModal,  setShowExcluirModal]   = usePropState(false);
  const [excluirChecked,    setExcluirChecked]     = usePropState(false);
  const [excluirMotivo,     setExcluirMotivo]      = usePropState('');
  const [excluirModoDelete, setExcluirModoDelete]  = usePropState(false); // false=cancelar, true=excluir definitivo
  const [showCorrigirModal, setShowCorrigirModal] = usePropState(false);
  const [localPedido, setLocalPedido] = usePropState(null);

  const prop = usePropMemo(() => CRM_DATA.propostas.find(p => p.id === propId), [propId]);

  // useEffect ANTES do early return — regra dos hooks: não pode ser condicional
  React.useEffect(() => {
    if (open && prop) {
      setLocalStatus(null);
      setTab(initialTab || (prop && prop.status === 'pedido_assinado' ? 'pedido' : 'doc'));
      setEditAprovMax(prop.valor);
      setEditAprovDesc(0);
      // Tenta itens do CRM_DATA local (sessão atual) ou do SP (prop.itens vem do itens_json)
      const itensLocal = CRM_DATA.itens_proposta?.[prop.id]?.length
        ? CRM_DATA.itens_proposta[prop.id]
        : (prop.itens || []);
      // Garante _localId em itens vindos do SP
      const itensComId = itensLocal.map(it =>
        it._localId ? it : { ...it, _localId: it.sku + '_' + (it._spId || Math.random().toString(36).slice(2)) }
      );
      if (itensComId.length && !CRM_DATA.itens_proposta?.[prop.id]?.length) {
        if (!CRM_DATA.itens_proposta) CRM_DATA.itens_proposta = {};
        CRM_DATA.itens_proposta[prop.id] = itensComId;
      }
      // Calcular DNET inicial a partir dos itens já carregados (dnet_final = após desconto vigente)
      var dnetFinalTotal = itensComId.reduce(function(s, it) {
        return s + (it.dnet_final || it.dnet || 0) * (it.qtd || it.quantidade || 1);
      }, 0);
      setEditDNet(dnetFinalTotal || prop.dnet || Math.round(prop.valor * 0.82));
      loadedItensRef.current = itensComId; // marca como "recém carregado"
      setLocalItens(itensComId);
      // Detectar itens da proposta que não estão mais na oportunidade
      const opItens = (CRM_DATA.itens_op && prop.op_id && CRM_DATA.itens_op[prop.op_id]) || null;
      if (opItens && itensLocal.length > 0) {
        const opIds = new Set(opItens.map(it => it._spId || it._localId).filter(Boolean));
        const orphans = itensLocal.filter(it => (it._spId || it._localId) && !opIds.has(it._spId || it._localId));
        setOrphanedItens(orphans);
      } else {
        setOrphanedItens([]);
      }
      const prazosInit = {};
      itensLocal.forEach(it => {
        prazosInit[it.sku] = it.prazo_entrega || (prop.prazos || {})[it.sku] || '';
      });
      setPrazos(prazosInit);
      // Validade: carrega do prop ou calcula +30 dias
      const propValidade = prop.validade
        ? (() => { try { return new Date(prop.validade).toISOString().split('T')[0]; } catch(e) { return ''; } })()
        : (() => {
            const d = prop.data ? new Date(prop.data) : new Date();
            d.setDate(d.getDate() + 30);
            return d.toISOString().split('T')[0];
          })();
      setEditValidade(propValidade);
      // Aprovação máxima por item (já gravada em itens_json)
      const initAprovMax = {};
      itensComId.forEach(function(it) { if (it.desconto_max != null) initAprovMax[it._localId] = it.desconto_max; });
      setAprovMaxItems(initAprovMax);
      // Linha do tempo e contato do cliente
      setLocalTimeline(prop.timeline || []);
      var opInit = CRM_DATA.getOp ? CRM_DATA.getOp(prop.op_id) : null;
      var cliInit = opInit ? CRM_DATA.getCliente(opInit.cliente_id) : null;
      setWppPhone((cliInit && cliInit.telefone) ? cliInit.telefone.replace(/\D/g,'') : '');
      setEmailDestinatario((cliInit && cliInit.email) || '');
      setWppLink(''); setWppMsgIdx(0); setCustomWppMsg('');
      setShowWppModal(false); setShowEmailModal(false);
      setEmailAssunto(''); setEmailCorpoEdit('');
      // Envio
      setShowEnvioForm(false);
      setEnvioData(new Date().toISOString().split('T')[0]);
      setEnvioCanal('email');
      setEnvioObs('');
      setLocalPedido(null);
    }
  }, [open, propId]);

  // Recuperacao de pedido: proposta em status de pedido sem pedido em memoria
  // (cache stale ou dados carregados antes do pedido ser criado).
  React.useEffect(function() {
    if (!open || !prop) return;
    var _pedRecStatus = prop.status;
    if (!['pedido', 'pedido_assinado', 'faturamento'].includes(_pedRecStatus)) return;
    // Primeiro tenta memoria (caso mais comum: mesmo sessao)
    var fromMem = window.CRM_DATA && window.CRM_DATA.getPedidoProp
      ? window.CRM_DATA.getPedidoProp(prop.id) : null;
    if (fromMem) { setLocalPedido(fromMem); return; }
    // Nao encontrado em memoria: tenta refresh assincrono do SP (cache stale)
    if (!window.CRM_API || !window.CRM_API.loadPedidos) return;
    var _pedRecCancelled = false;
    window.CRM_API.loadPedidos().then(function(freshPedidos) {
      if (_pedRecCancelled) return;
      if (!Array.isArray(window.CRM_DATA.pedidos)) return;
      window.CRM_DATA.pedidos.length = 0;
      freshPedidos.forEach(function(p) { window.CRM_DATA.pedidos.push(p); });
      var found = window.CRM_DATA.getPedidoProp
        ? window.CRM_DATA.getPedidoProp(prop.id) : null;
      if (found) setLocalPedido(found);
    }).catch(function(e) {
      console.warn('[PropostaModal] refreshPedidos:', e && e.message);
    });
    return function() { _pedRecCancelled = true; };
  }, [open, propId]);

  // Auto-avança proposta para 'pedido_assinado' se pedido já foi assinado (ex: via n8n)
  React.useEffect(function() {
    if (!open || !prop) return;
    var ped = window.CRM_DATA && window.CRM_DATA.getPedidoProp ? window.CRM_DATA.getPedidoProp(prop.id) : null;
    if (!ped) return;
    var jaAssinado = ped.assinatura || ped.assinatura_nome;
    var statusAtual = localStatus || prop.status;
    if (jaAssinado && statusAtual === 'pedido') {
      // Avança em memória
      setLocalStatus('pedido_assinado');
      // Persiste no SP e em CRM_DATA se ainda não estava salvo
      if (prop._spId && window.CRM_API) {
        window.CRM_API.updateItem('Propostas', prop._spId, { status: 'pedido_assinado' })
          .catch(function(e){
            console.warn('[CRM] auto-advance pedido_assinado:', e.message);
            if (typeof window.CRM_TOAST === 'function') {
              window.CRM_TOAST('Pedido foi assinado mas falha ao atualizar status. Recarregue a página.', 'error');
            }
          });
      }
      if (window.CRM_DATA && window.CRM_DATA.propostas) {
        var pIdx = window.CRM_DATA.propostas.findIndex(function(p){ return p.id === prop.id; });
        if (pIdx >= 0) window.CRM_DATA.propostas[pIdx] = Object.assign({}, window.CRM_DATA.propostas[pIdx], { status: 'pedido_assinado' });
      }
      window.dispatchEvent(new CustomEvent('crm_prop_status_changed', {
        detail: { propId: prop.id, newStatus: 'pedido_assinado', opId: prop.op_id }
      }));
    }
  }, [open, prop && prop.id]);

  // Self-heal: proposta com pedido ATIVO vinculado mas status atras de 'pedido'.
  // Causa: na emissao o updateItem de status e best-effort; se falhar (blip de rede),
  // o pedido e criado mas o status fica em 'aprovada'/'enviada'/etc. Reconcilia ao abrir.
  React.useEffect(function() {
    if (!open || !prop) return;
    var statusAtual = localStatus || prop.status;
    var atrasados = ['rascunho', 'aguardando_aprovacao', 'aprovada', 'enviada', 'em_negociacao'];
    if (atrasados.indexOf(statusAtual) === -1) return;
    var ped = window.CRM_DATA && window.CRM_DATA.getPedidoProp ? window.CRM_DATA.getPedidoProp(prop.id) : null;
    if (!ped) return;
    var pedCancelado = ped.status === 'cancelado' || ped.status === 'cancelado_correcao' || ped.status === 'cancelado_apos_assinatura';
    if (pedCancelado) return; // pedido cancelado nao forca avanco de status
    var assinado = !!(ped.assinatura || ped.assinatura_nome || ped.cliente_aprovado_em || ped.status === 'pedido_assinado');
    var novoStatus = assinado ? 'pedido_assinado' : 'pedido';
    console.info('[CRM] self-heal: proposta ' + prop.id + ' ' + statusAtual + ' -> ' + novoStatus + ' (pedido ' + ped.id + ' vinculado)');
    setLocalStatus(novoStatus);
    if (prop._spId && window.CRM_API) {
      window.CRM_API.updateItem('Propostas', prop._spId, { status: novoStatus })
        .catch(function(e){ console.warn('[CRM] self-heal status ' + novoStatus + ':', e && e.message); });
    }
    if (window.CRM_DATA && window.CRM_DATA.propostas) {
      var pIdx = window.CRM_DATA.propostas.findIndex(function(p){ return p.id === prop.id; });
      if (pIdx >= 0) window.CRM_DATA.propostas[pIdx] = Object.assign({}, window.CRM_DATA.propostas[pIdx], { status: novoStatus });
    }
    window.dispatchEvent(new CustomEvent('crm_prop_status_changed', {
      detail: { propId: prop.id, newStatus: novoStatus, opId: prop.op_id }
    }));
  }, [open, prop && prop.id]);

  // Inicializa assunto e corpo padrão quando o modal de email abre
  React.useEffect(function() {
    if (!showEmailModal || emailAssunto) return;
    var modeloStr  = (op && op.modelo)   ? op.modelo   : 'Equipamento';
    var empresaStr = (cli && cli.razao)  ? cli.razao   : 'sua empresa';
    var nomeContato = (cli && cli.contato) ? cli.contato : 'cliente';
    var vendNome   = (vend && vend.nome) ? vend.nome   : 'Equipe Bauko';
    var valorStr   = fR(totalComDesconto || prop.valor || 0);
    var validadeStr = editValidade
      ? new Date(editValidade + 'T12:00:00').toLocaleDateString('pt-BR')
      : '—';
    var equipListEmail = (localItens && localItens.length > 0)
      ? localItens.map(function(it){ return it.sku || it.modelo || it.familia || 'equipamento'; }).join(', ')
      : modeloStr;
    setEmailAssunto('Proposta Comercial: ' + equipListEmail + ' – ' + empresaStr);
    setEmailModeloSel(0);
    setEmailCorpoEdit(
      'Prezado(a) ' + nomeContato + ',\n\n' +
      'É um prazer dar continuidade ao nosso atendimento.\n\n' +
      'Conforme conversamos, segue a proposta comercial da Bauko referente ao(s) equipamento(s):\n' +
      equipListEmail + '\n\n' +
      'Ref.: ' + prop.id + ' • Valor do Investimento: ' + valorStr + ' • Validade: ' + validadeStr + '\n\n' +
      'Para conferir todos os detalhes técnicos, condições de pagamento e prazos, acesse o documento completo:\n\n' +
      '[Visualizar Proposta Completa]\n\n' +
      'Colocamo-nos à disposição para qualquer esclarecimento.\n\n' +
      'Atenciosamente,\n' + vendNome + '\nBauko Soluções em Equipamentos'
    );
  }, [showEmailModal]);

  // Re-inicializa ícones Lucide após cada render do modal (try/catch contra reconciliação React)
  React.useEffect(() => {
    try { if (typeof lucide !== 'undefined') lucide.createIcons(); } catch(e) {}
  });

  // Sincroniza localItens → CRM_DATA e notifica Oportunidade via CustomEvent
  // Só dispara quando usuário alterou algo — não no carregamento inicial
  React.useEffect(() => {
    if (!prop || !open || localItens.length === 0) return;
    if (localItens === loadedItensRef.current) return; // mesmo array do load → ignora
    if (!CRM_DATA.itens_proposta) CRM_DATA.itens_proposta = {};
    CRM_DATA.itens_proposta[prop.id] = localItens;
    // Recalcula e persiste valor total (com descontos por item) + itens_json no SP
    var newValor = localItens.reduce(function(s, it){ return s + Math.round(it.total * (1 - (it.desconto || 0) / 100)); }, 0);
    if (newValor > 0 && CRM_DATA.propostas) {
      var pIdx = CRM_DATA.propostas.findIndex(function(p){ return p.id === prop.id; });
      if (pIdx >= 0) CRM_DATA.propostas[pIdx] = Object.assign({}, CRM_DATA.propostas[pIdx], { valor: newValor });
    }
    if (window.CRM_API && prop._spId) {
      // Embute prazo_entrega em cada item para persistir sem coluna SP extra
      var itensComPrazo = localItens.map(function(it) {
        var prazo = (typeof prazos === 'object' && prazos) ? (prazos[it.sku] || '') : '';
        return prazo ? Object.assign({}, it, { prazo_entrega: prazo }) : it;
      });
      var spPayload = { itens: itensComPrazo };
      if (newValor > 0) spPayload.valor = newValor;
      CRM_API.updateItem('Propostas', prop._spId, spPayload).catch(function(e) {
        console.warn('[CRM] updateItem Propostas itens_json:', e.message);
      });
    }
    // Suprime o primeiro dispatch ao abrir proposta recém-criada (evita duplicata na oportunidade)
    if (window._baukoPropJustCreated === prop.id) {
      window._baukoPropJustCreated = null;
      return;
    }
    window.dispatchEvent(new CustomEvent('crm_prop_itens', {
      detail: { propId: prop.id, opId: prop.op_id, itens: localItens }
    }));
  }, [localItens, open]);

  // Persiste prazos ao SP quando o usuário preenche/altera um prazo de entrega
  React.useEffect(function() {
    if (!prop || !open || !window.CRM_API || !prop._spId) return;
    var itensComPrazo = localItens.map(function(it) {
      var prazo = prazos[it.sku] || '';
      return prazo ? Object.assign({}, it, { prazo_entrega: prazo }) : it;
    });
    var timer = setTimeout(function() {
      CRM_API.updateItem('Propostas', prop._spId, { itens: itensComPrazo })
        .catch(function(e){ console.warn('[CRM] prazos save:', e.message); });
    }, 1200); // debounce 1.2s para não salvar a cada tecla
    return function() { clearTimeout(timer); };
  }, [prazos, open]);

  if (!prop) return (
    <Modal open={open} onClose={onClose} title="Proposta" subtitle="Em elaboração">
      <div style={{ padding: '40px 0', textAlign: 'center', color: 'var(--tx-3)' }}>
        <i data-lucide="file-clock" style={{ width: 40, height: 40, marginBottom: 16 }}></i>
        <div style={{ font: '500 14px/1.5 var(--ff)', marginBottom: 8 }}>Proposta em elaboração</div>
        <div style={{ font: '400 12px/1.5 var(--ff)', color: 'var(--tx-4)' }}>
          Os dados serão disponibilizados após confirmação do gerente.
        </div>
      </div>
    </Modal>
  );

  // I-D7: guard de acesso — vendedor só pode abrir propostas onde é responsável
  const _meuId = window.CRM_USER && (window.CRM_USER.userId || window.CRM_USER.email);
  const _podeVerAlheia = !!(window.CRM_USER && (window.CRM_USER.podeVerOpAlheia || window.CRM_USER.isGerente || window.CRM_USER.isAdmin || window.CRM_USER.isBDR));
  if (_meuId && !_podeVerAlheia && prop.responsavel_id && prop.responsavel_id !== _meuId) {
    return (
      <Modal open={open} onClose={onClose} title="Proposta" subtitle="Acesso restrito">
        <div style={{ padding: '40px 0', textAlign: 'center', color: 'var(--tx-3)' }}>
          <i data-lucide="lock" style={{ width: 40, height: 40, marginBottom: 16 }}></i>
          <div style={{ font: '500 14px/1.5 var(--ff-body)', marginBottom: 8 }}>Acesso restrito</div>
          <div style={{ font: '400 12px/1.5 var(--ff-body)', color: 'var(--tx-4)' }}>
            Você não tem permissão para visualizar esta proposta.
          </div>
        </div>
      </Modal>
    );
  }

  const op   = CRM_DATA.getOp(prop.op_id);
  const cli  = op ? CRM_DATA.getCliente(op.cliente_id) : null;
  const vend = CRM_DATA.getUsuario(prop.responsavel_id);
  const itens = localItens;
  const events = localTimeline.length ? localTimeline : ((CRM_DATA.timeline || []).filter(t => t.prop_id === prop.id));
  const pedido = localPedido || CRM_DATA.getPedidoProp?.(prop.id);
  // Aprovação foi realmente usada se existe evento do tipo aguardando_aprovacao ou aprovada na timeline
  const approvalWasUsed = events.some(function(e){ return e.tipo === 'aguardando_aprovacao' || e.tipo === 'aprovada'; });

  const subtotal = itens.reduce((s, it) => s + it.total, 0);
  const desconto = subtotal * (prop.desconto || 0) / 100;
  const total = prop.valor;

  // Status efetivo: localStatus sobrescreve prop.status para demo sem SharePoint
  const effectiveStatus = localStatus || prop.status;
  const isGerente = !!(window.CRM_USER && window.CRM_USER.isGerente);
  // vT1: soma de valor_t1 × qtd por item. Se qualquer item não tiver valor_t1
  // (criado antes da correção do simulador), desativa o aviso (vT1=0 → sem banner)
  const vT1 = (function() {
    if (!localItens.length) return 0;
    if (!localItens.every(function(it){ return it.valor_t1 > 0; })) return 0;
    return localItens.reduce(function(s, it) {
      return s + it.valor_t1 * (it.qtd || it.quantidade || 1);
    }, 0);
  })();

  // ── Registrar evento na linha do tempo ──────────────────────────────────
  function addTimelineEvent(tipo, detalhe) {
    // Autor do log: usuario REAL logado (auditoria - nao muda com Visualizar como)
    var autor = (window.CRM_USER && window.CRM_USER.realEmail) || '';
    var evento = { id: Date.now().toString(36) + Math.random().toString(36).slice(2,5), tipo: tipo, data: new Date().toISOString(), detalhe: detalhe || '', autor: autor };
    setLocalTimeline(function(prev) {
      var novaTimeline = prev.concat([evento]);
      if (window.CRM_API && prop._spId) {
        CRM_API.updateItem('Propostas', prop._spId, { timeline: novaTimeline })
          .catch(function(e){ console.warn('[CRM] timeline save:', e.message); });
      }
      if (CRM_DATA.propostas) {
        var pIdx = CRM_DATA.propostas.findIndex(function(p){ return p.id === prop.id; });
        if (pIdx >= 0) CRM_DATA.propostas[pIdx] = Object.assign({}, CRM_DATA.propostas[pIdx], { timeline: novaTimeline });
      }
      return novaTimeline;
    });
  }

  // Persiste status no SP e atualiza CRM_DATA em memória
  function persistStatus(newStatus) {
    setLocalStatus(newStatus);
    // Atualiza memória IMEDIATAMENTE — não espera o SP responder
    if (CRM_DATA.propostas) {
      var idx = CRM_DATA.propostas.findIndex(function(p){ return p.id === prop.id; });
      if (idx >= 0) CRM_DATA.propostas[idx] = Object.assign({}, CRM_DATA.propostas[idx], { status: newStatus });
    }
    // Notifica OportunidadeModal para atualizar badge do card de proposta
    window.dispatchEvent(new CustomEvent('crm_prop_status_changed', {
      detail: { propId: prop.id, newStatus: newStatus, opId: prop.op_id }
    }));
    // Persiste no SP em background — H4: avisa usuário em falha
    if (prop._spId && window.CRM_API) {
      CRM_API.updateItem('Propostas', prop._spId, { status: newStatus })
        .catch(function(e){
          console.warn('[CRM] persistStatus SP:', e.message);
          if (typeof window.CRM_TOAST === 'function') {
            window.CRM_TOAST('Falha ao salvar status no servidor. Recarregue a página antes de continuar.', 'error');
          }
        });
    }
  }

  // Persiste status + timeline num único PATCH (evita race condition)
  function persistStatusComEvento(newStatus, tipoEvento, detalhe) {
    // Autor do log: usuario REAL logado (auditoria - nao muda com Visualizar como)
    var autor = (window.CRM_USER && window.CRM_USER.realEmail) || '';
    var evento = { id: Date.now().toString(36) + Math.random().toString(36).slice(2,5), tipo: tipoEvento, data: new Date().toISOString(), detalhe: detalhe || '', autor: autor };
    setLocalTimeline(function(prev) {
      var novaTimeline = prev.concat([evento]);
      if (window.CRM_API && prop._spId) {
        CRM_API.updateItem('Propostas', prop._spId, { status: newStatus, timeline: novaTimeline })
          .catch(function(e){
            console.warn('[CRM] persistStatusComEvento SP:', e.message);
            if (typeof window.CRM_TOAST === 'function') {
              window.CRM_TOAST('Falha ao salvar status no servidor. Recarregue a página antes de continuar.', 'error');
            }
          });
      }
      if (CRM_DATA.propostas) {
        var pIdx = CRM_DATA.propostas.findIndex(function(p){ return p.id === prop.id; });
        if (pIdx >= 0) CRM_DATA.propostas[pIdx] = Object.assign({}, CRM_DATA.propostas[pIdx], { status: newStatus, timeline: novaTimeline });
      }
      return novaTimeline;
    });
    setLocalStatus(newStatus);
    window.dispatchEvent(new CustomEvent('crm_prop_status_changed', {
      detail: { propId: prop.id, newStatus: newStatus, opId: prop.op_id }
    }));
  }

  // Avança etapa: valida condições obrigatórias antes de avançar
  function handleProximaEtapa() {
    // Aprovada → abre modal de confirmação de envio (igual a 'enviada')
    if (effectiveStatus === 'aprovada') {
      setShowConfirmarEnvio(true);
      return;
    }
    // Enviada → popup confirmar envio → em_negociacao
    if (effectiveStatus === 'enviada') {
      setShowConfirmarEnvio(true);
      return;
    }
    // Rascunho → valida prazos/validade/itens
    // H3: bloqueia avanço com 0 itens
    if (!localItens || localItens.length === 0) {
      window.CRM_TOAST('Adicione ao menos um item antes de avançar a proposta.', 'warn');
      return;
    }
    const itensSemPrazo = localItens.filter(it => !prazos[it.sku] || prazos[it.sku].trim() === '');
    if (itensSemPrazo.length > 0) {
      const skus = itensSemPrazo.map(it => it.sku).join(', ');
      window.CRM_TOAST(`Preencha o prazo de entrega para: ${skus}`, 'warn');
      return;
    }
    if (!editValidade) {
      window.CRM_TOAST('Informe a validade da proposta antes de avançar.', 'warn');
      return;
    }
    // H2: bloqueia avanço com validade no passado
    var _hojeStr = new Date().toISOString().slice(0, 10);
    if (editValidade < _hojeStr) {
      window.CRM_TOAST('A validade da proposta está no passado. Atualize antes de avançar.', 'warn');
      return;
    }
    if (totalComDesconto > 0 && totalComDesconto < vT1) {
      // Precisa de aprovação gerencial (interno)
      // I-D9: avisa se já houve rejeição prévia — possível loop de aprovação com mesmo desconto
      if (events.some(function(ev){ return ev.tipo === 'gerente_recusou'; })) {
        window.CRM_TOAST('Atenção: este desconto já foi recusado pelo gerente. Certifique-se de que os valores foram revisados antes de reenviar.', 'warn');
      }
      persistStatusComEvento('aguardando_aprovacao', 'aprovacao_int', 'Enviada para aprovação gerencial');
    } else {
      // Sem aprovação gerencial → vai direto para enviada
      persistStatusComEvento('enviada', 'enviada', 'Proposta enviada ao cliente sem aprovação gerencial');
    }
  }

  // Callback do ConfirmarEnvioModal — registra envio e avança para em_negociacao
  function handleConfirmarEnvio(modalidade, dataEnvio) {
    var dataStr = dataEnvio
      ? new Date(dataEnvio + 'T12:00:00').toLocaleDateString('pt-BR')
      : new Date().toLocaleDateString('pt-BR');
    persistStatusComEvento('em_negociacao', 'envio_confirmado', 'Enviada ao cliente via ' + modalidade + ' em ' + dataStr);
    setShowConfirmarEnvio(false);
  }

  // Derivados para painel gerencial
  const subtotalBruto   = localItens.reduce((s, it) => s + it.total, 0);
  const totalComDesconto = localItens.reduce((s, it) => s + Math.round(it.total * (1 - (it.desconto || 0) / 100)), 0);
  const descGlobal      = subtotalBruto > 0 && totalComDesconto < subtotalBruto ? +(((1 - totalComDesconto / subtotalBruto) * 100).toFixed(1)) : 0;
  // Margem líquida real (solic.) — mesma fórmula do simulador, usando desconto solicitado pelo vendedor
  const margSolic = (function() {
    if (totalComDesconto <= 0) return '—';
    var totalCustoSolic = localItens.reduce(function(s, it) {
      var qtd = it.qtd || it.quantidade || 1;
      var sVV = it.valor_total * (1 - (it.desconto || 0) / 100) * qtd;
      var unitCusto = (it.custo || 0) + (it.frete || 0) + (it.prep || 15500)
                    + (it.extras || 0) + (it.pmp || 0) + (it.subsidio || 0);
      var impostos = ((it.icms_saida || 0) / 100 + (it.diferencial || 0) / 100) * sVV;
      var comissao = (it.com || 0.0050592) * sVV;
      return s + unitCusto * qtd + impostos + comissao;
    }, 0);
    return ((totalComDesconto - totalCustoSolic) / totalComDesconto * 100).toFixed(1);
  })();
  const totalAprovado = localItens.reduce(function(s, it) {
    var mmax = aprovMaxItems[it._localId] != null ? aprovMaxItems[it._localId] : (it.desconto || 0);
    return s + Math.round(it.total * (1 - mmax / 100));
  }, 0);
  // Margem líquida real (mesma fórmula do simulador)
  // Itens sem custo/icms_saida (criados antes da correção) → fallback fórmula antiga
  const margAprov = (function() {
    if (totalAprovado <= 0) return '—';
    var temDados = localItens.some(function(it){ return (it.custo || 0) > 0 || (it.icms_saida || 0) > 0; });
    if (!temDados) return ((totalAprovado - editDNet) / totalAprovado * 100).toFixed(1);
    // Ajusta custo proporcionalmente se gerente alterou o DNET global
    var dnetOrigTotal = localItens.reduce(function(s, it) {
      return s + (it.dnet_final || it.dnet || 0) * (it.qtd || it.quantidade || 1);
    }, 0);
    var dnetRatio = (dnetOrigTotal > 0 && editDNet > 0) ? editDNet / dnetOrigTotal : 1;
    var totalCusto = localItens.reduce(function(s, it) {
      var qtd = it.qtd || it.quantidade || 1;
      var mmax = aprovMaxItems[it._localId] != null ? aprovMaxItems[it._localId] : (it.desconto || 0);
      var aprovVV = it.total * (1 - mmax / 100) * qtd;
      var unitCusto = ((it.custo || 0) * dnetRatio) + (it.frete || 0) + (it.prep || 15500)
                    + (it.extras || 0) + (it.pmp || 0) + (it.subsidio || 0);
      var impostos = ((it.icms_saida || 0) / 100 + (it.diferencial || 0) / 100) * aprovVV;
      var comissao = (it.com || 0.0050592) * aprovVV;
      return s + unitCusto * qtd + impostos + comissao;
    }, 0);
    return ((totalAprovado - totalCusto) / totalAprovado * 100).toFixed(1);
  })();
  const desvioT1pct = vT1 > 0 ? ((totalComDesconto - vT1) / vT1 * 100).toFixed(1) : '0';

  function handleExcluirProposta() {
    setExcluirChecked(false);
    setExcluirMotivo('');
    setExcluirModoDelete(false);
    setShowExcluirModal(true);
  }

  // Cancela a proposta (soft delete) + cascade pra pedido vinculado ativo.
  async function handleCancelarProposta(motivo) {
    if (!prop) throw new Error('Proposta não encontrada');
    var canceladaEm = new Date().toISOString();
    // Autor do log: usuario REAL logado (auditoria - nao muda com Visualizar como)
    var autor = (window.CRM_USER && window.CRM_USER.realEmail) || '';

    // 1. Cascade pra pedido ATIVO (se houver)
    var updatePromises = [];
    if (pedido && !(pedido.status === 'cancelado' || pedido.status === 'cancelado_correcao' || pedido.status === 'cancelado_apos_assinatura')) {
      var eventoPed = {
        id: Date.now().toString(36) + Math.random().toString(36).slice(2,5),
        tipo: 'cancelado_cascade',
        data: canceladaEm,
        detalhe: 'Pedido cancelado porque a proposta ' + prop.id + ' foi cancelada. Motivo: ' + motivo,
        autor: autor,
      };
      var novaTimelinePed = (pedido.timeline || []).concat([eventoPed]);
      pedido.status = 'cancelado';
      pedido.timeline = novaTimelinePed;
      pedido.cancelado_em = canceladaEm;
      pedido.motivo_cancelamento = motivo;
      if (CRM_DATA.pedidos) {
        var pIdx = CRM_DATA.pedidos.findIndex(function(p){ return p.id === pedido.id; });
        if (pIdx >= 0) CRM_DATA.pedidos[pIdx] = Object.assign({}, CRM_DATA.pedidos[pIdx], { status: 'cancelado', timeline: novaTimelinePed, cancelado_em: canceladaEm, motivo_cancelamento: motivo });
      }
      if (window.CRM_API && pedido._spId) {
        updatePromises.push(
          CRM_API.updateItem('CRMPedidos', pedido._spId, { status: 'cancelado', timeline: novaTimelinePed })
            .then(function(){ return { ok: true, tipo: 'pedido' }; })
            .catch(function(e){
              console.warn('[CRM] cascade pedido (proposta):', e.message);
              return { ok: false, tipo: 'pedido', err: e };
            })
        );
      }
    }

    // 2. Atualiza proposta — status cancelada + timeline event
    var detalheProp = 'Proposta cancelada' + (pedido ? ' (cascade pra pedido ' + pedido.id + ')' : '') + ' · ' + motivo;
    persistStatusComEvento('cancelada', 'proposta_cancelada', detalheProp);
    // Marca cancelada_em em memória pro modal fechar e UI atualizar
    if (CRM_DATA.propostas) {
      var pIdx2 = CRM_DATA.propostas.findIndex(function(p){ return p.id === prop.id; });
      if (pIdx2 >= 0) CRM_DATA.propostas[pIdx2] = Object.assign({}, CRM_DATA.propostas[pIdx2], { cancelada_em: canceladaEm, motivo_cancelamento: motivo });
    }
    if (window.CRM_API && prop._spId) {
      // Persiste motivo na timeline_json (já feito pelo persistStatusComEvento) — não precisa coluna separada
    }

    // H12: rastreia falhas no cascade
    var resultados = await Promise.allSettled(updatePromises);
    var falhas = resultados.filter(function(r){
      return r.status === 'rejected' || (r.value && r.value.ok === false);
    });

    // 3. Notifica oportunidade
    window.dispatchEvent(new CustomEvent('crm_prop_status_changed', {
      detail: { propId: prop.id, newStatus: 'cancelada', opId: prop.op_id }
    }));
    setShowExcluirModal(false);
    if (typeof window.CRM_TOAST === 'function') {
      if (falhas.length > 0) {
        window.CRM_TOAST('Proposta cancelada localmente, mas ' + falhas.length + ' atualização(ões) no servidor falharam. Recarregue a página para sincronizar.', 'warn');
      } else {
        var msgPed = pedido ? ' Pedido vinculado também cancelado.' : '';
        window.CRM_TOAST('Proposta cancelada.' + msgPed, 'ok');
      }
    }
    onClose && onClose();
  }

  // Cancela o pedido atual (status `cancelado_correcao` ou `cancelado_apos_assinatura`)
  // e volta a proposta para `em_negociacao`, liberando reemissão.
  // O pedido NÃO é deletado — apenas marcado como cancelado para preservar rastreabilidade.
  async function cancelarPedidoComCorrecao(motivo) {
    if (!pedido) throw new Error('Nenhum pedido vinculado');
    var assinado = !!(pedido.assinatura || pedido.assinatura_nome || pedido.cliente_aprovado_em || pedido.status === 'pedido_assinado');
    var novoStatus = assinado ? 'cancelado_apos_assinatura' : 'cancelado_correcao';
    var tipoEvento = novoStatus;
    // Autor do log: usuario REAL logado (auditoria - nao muda com Visualizar como)
    var autor = (window.CRM_USER && window.CRM_USER.realEmail) || '';
    var evento = {
      id: Date.now().toString(36) + Math.random().toString(36).slice(2,5),
      tipo: tipoEvento,
      data: new Date().toISOString(),
      detalhe: motivo,
      autor: autor,
    };
    // 1. Atualiza pedido em memória
    var pedTimeline = (pedido.timeline || []).concat([evento]);
    pedido.status = novoStatus;
    pedido.timeline = pedTimeline;
    pedido.motivo_cancelamento = motivo;
    pedido.cancelado_em = evento.data;
    if (CRM_DATA.pedidos) {
      var pIdx = CRM_DATA.pedidos.findIndex(function(p){ return p.id === pedido.id; });
      if (pIdx >= 0) CRM_DATA.pedidos[pIdx] = Object.assign({}, CRM_DATA.pedidos[pIdx], { status: novoStatus, timeline: pedTimeline, motivo_cancelamento: motivo, cancelado_em: evento.data });
    }
    // 2. Persiste pedido no SP — H5: se falhar, ROLLBACK memória e ABORTA volta da proposta
    if (window.CRM_API && pedido._spId) {
      try {
        await CRM_API.updateItem('CRMPedidos', pedido._spId, { status: novoStatus, timeline: pedTimeline });
      } catch(e) {
        console.error('[CRM] updateItem CRMPedidos cancelamento falhou:', e.message);
        // Rollback: restaura estado anterior do pedido em memória
        var pedidoStatusAnterior = assinado ? 'pedido_assinado' : 'emitido';
        pedido.status = pedidoStatusAnterior;
        pedido.timeline = pedido.timeline.slice(0, -1);
        delete pedido.motivo_cancelamento;
        delete pedido.cancelado_em;
        if (CRM_DATA.pedidos && pIdx >= 0) {
          CRM_DATA.pedidos[pIdx] = Object.assign({}, CRM_DATA.pedidos[pIdx], { status: pedidoStatusAnterior, timeline: pedido.timeline, motivo_cancelamento: undefined, cancelado_em: undefined });
        }
        if (typeof window.CRM_TOAST === 'function') {
          window.CRM_TOAST('Falha ao cancelar pedido no servidor. Tente novamente.', 'error');
        }
        throw e;
      }
    }
    // 3. Volta proposta para em_negociacao + registra evento na timeline da proposta
    var detalheProp = (novoStatus === 'cancelado_apos_assinatura' ? 'Pedido assinado ' : 'Pedido ') + pedido.id + ' cancelado · ' + motivo;
    persistStatusComEvento('em_negociacao', tipoEvento, detalheProp);
    // 4. Notifica oportunidade pra atualizar card
    window.dispatchEvent(new CustomEvent('crm_prop_status_changed', {
      detail: { propId: prop.id, newStatus: 'em_negociacao', opId: prop.op_id }
    }));
    // 5. Fecha modal
    setShowCorrigirModal(false);
  }

  async function handleConfirmarExclusao() {
    // H6: SP primeiro, memória depois — evita exclusão fantasma se SP falhar
    var deletePromises = [];
    if (window.CRM_API && prop._spId) {
      deletePromises.push(
        CRM_API.deleteItem('Propostas', prop._spId)
          .then(function(){ return { ok: true, tipo: 'proposta' }; })
          .catch(function(e){ return { ok: false, tipo: 'proposta', err: e }; })
      );
    }
    if (pedido && window.CRM_API && pedido._spId) {
      deletePromises.push(
        CRM_API.deleteItem('CRMPedidos', pedido._spId)
          .then(function(){ return { ok: true, tipo: 'pedido' }; })
          .catch(function(e){ return { ok: false, tipo: 'pedido', err: e }; })
      );
    }
    var resultados = await Promise.all(deletePromises);
    var falhas = resultados.filter(function(r){ return !r.ok; });
    if (falhas.length > 0) {
      console.error('[CRM] handleConfirmarExclusao falhas SP:', falhas);
      if (typeof window.CRM_TOAST === 'function') {
        var tipos = falhas.map(function(f){ return f.tipo; }).join(' e ');
        window.CRM_TOAST('Falha ao excluir ' + tipos + ' no servidor. Nada foi removido localmente. Tente novamente.', 'error');
      }
      return;
    }
    // SP confirmou — agora remove de CRM_DATA
    if (CRM_DATA.propostas) {
      var idx = CRM_DATA.propostas.findIndex(function(p){ return p.id === prop.id; });
      if (idx >= 0) CRM_DATA.propostas.splice(idx, 1);
    }
    if (pedido && CRM_DATA.pedidos) {
      var pi = CRM_DATA.pedidos.findIndex(function(p){ return p.id === pedido.id; });
      if (pi >= 0) CRM_DATA.pedidos.splice(pi, 1);
    }
    // Notifica OportunidadeModal
    window.dispatchEvent(new CustomEvent('crm_prop_deleted', { detail: { propId: prop.id, opId: prop.op_id } }));
    setShowExcluirModal(false);
    onDelete && onDelete(prop.id);
    onClose && onClose();
  }

  // Gera URL pública da proposta (usada em WhatsApp, e-mail e Baixar PDF)
  function gerarLinkUrl() {
    var dados = JSON.stringify({
      id: prop.id, versao: prop.versao || 1, data: prop.data,
      validade: editValidade || prop.validade, status: prop.status || '',
      op: op ? { titulo: op.titulo||'', familia: op.familia||'', modelo: op.modelo||'', descricao: (op.descricao||'').slice(0,200), fabricante: (localItens&&localItens[0]&&localItens[0].familia)||op.familia||'', descricao_tecnica: (localItens&&localItens[0]&&localItens[0].descricao_tecnica)||'' } : {},
      cli: cli ? { razao: cli.razao||'', cnpj: cli.cnpj||'', cidade: cli.cidade||'', uf: cli.uf||'', contato: cli.contato||'', contato_nome: (op&&op.contato_nome)||'' } : {},
      vend: vend ? { nome: vend.nome||'', cargo: vend.cargo||'', email: vend.email||'' } : {},
      itens: localItens.map(function(it){ var dm=aprovMaxItems[it._localId]; return { sku: it.sku, familia: it.familia||'', desc: it.desc||'', descricao_tecnica: it.descricao_tecnica||'', qtd: it.qtd||it.quantidade||1, total: it.total||0, desconto: dm!=null?dm:(it.desconto||0), prazo: (prazos&&prazos[it.sku])||'', frete_tipo: it.frete_tipo||'', garantia: it.garantia||'', icms_saida: it.icms_saida||0, composicao: it.composicao||[] }; }),
    });
    if (typeof LZString !== 'undefined') {
      return window.location.origin + '/crm/proposta-publica.html?d=' + LZString.compressToEncodedURIComponent(dados);
    }
    return window.location.origin + '/crm/proposta-publica.html?d=' + btoa(unescape(encodeURIComponent(dados)));
  }

  // Gera URL pública do pedido (pedido-publica.html) — mesmo padrão de compressão
  function gerarLinkPedido() {
    if (!pedido) return '';
    var valorNum = pedido._valorNum || parseFloat(pedido.valor) || prop.valor || 0;
    var dados = JSON.stringify({
      tipo:  'pedido',
      id:    pedido.id,
      propId: prop.id,
      opId:  prop.op_id || '',
      data:  pedido.data || new Date().toISOString(),
      pgto_condicao: pedido.pgto_condicao || '',
      notas: pedido.notas || '',
      unidade: pedido.unidade_bauko || '',
      valor: valorNum,
      cli:  cli  ? { razao: cli.razao||'', cnpj: cli.cnpj||'', contato: cli.contato||'', contato_nome: (op&&op.contato_nome)||'', cidade: cli.cidade||'', uf: cli.uf||'', telefone: cli.telefone||'', email: cli.email||'', endereco: cli.endereco||'', ie: cli.ie||'', cep: cli.cep||'', segmento: cli.segmento||'', atividade: cli.atividade||'' } : {},
      vend: vend ? { nome: vend.nome||'', cargo: vend.cargo||'', email: vend.email||'' } : {},
      op:   op   ? { titulo: op.titulo||'', familia: op.familia||'', modelo: op.modelo||'', descricao: (op.descricao||'').slice(0, 300) } : {},
      entrada:       pedido.pgto_entrada || pedido.entrada || '',
      local_entrega: (pedido.itens && pedido.itens[0] && pedido.itens[0].local_entrega) || pedido.local_entrega || '',
      validade:      pedido.validade || prop.validade || '',
      itens: (pedido.itens || localItens || []).map(function(it) {
        return { sku: it.sku||'', familia: it.familia||'', desc: it.desc||it.modelo||'', qtd: it.qtd||it.quantidade||1, total: it.total||0, desconto: it.desconto||0, prazo: it.prazo||'', impostos: it.impostos||0, garantia: it.garantia||'' };
      }),
    });
    if (typeof LZString !== 'undefined') {
      return window.location.origin + '/crm/pedido-publica.html?d=' + LZString.compressToEncodedURIComponent(dados);
    }
    return window.location.origin + '/crm/pedido-publica.html?d=' + btoa(unescape(encodeURIComponent(dados)));
  }

  return (
    <Modal open={open} onClose={onClose} title={`Proposta ${prop.id}`} subtitle={`${op?.titulo} · ${cli?.razao}`} wide xl>
      {/* Lifecycle */}
      <div style={{
        margin: "16px -6px 18px", padding: "16px 8px",
        background: "var(--surface-2)", border: "1px solid var(--border)", borderRadius: "var(--r-md)",
      }}>
        <ProposalLifecycle
          status={effectiveStatus}
          hasOrder={!!pedido}
          skipAprovacao={!approvalWasUsed}
          onStepClick={effectiveStatus === "cancelada" ? null : (targetStatus, stepLabel) => {
            // G1: pedido emitido -- regressao deve usar "Cancelar pedido"
            if (['pedido', 'pedido_assinado', 'faturamento'].includes(effectiveStatus)) {
              if (typeof window.CRM_TOAST === 'function') {
                window.CRM_TOAST('Use "Cancelar pedido" na aba Pedido para voltar desta etapa.', 'warn');
              }
              return;
            }
            const voltaParaRascunho = targetStatus === 'rascunho';
            const eraNegociado = ['enviada', 'em_negociacao', 'pedido', 'pedido_assinado', 'faturamento'].includes(effectiveStatus);
            const msg = (voltaParaRascunho || targetStatus === 'aguardando_aprovacao') && eraNegociado
              ? `Voltar para "${stepLabel}"?

Atenção: qualquer aprovação concedida será cancelada e uma nova aprovação gerencial será necessária antes de reenviar ao cliente.`
              : `Voltar para a etapa "${stepLabel}"? Aprovações pendentes serão canceladas.`;
            window.CRM_CONFIRM(msg, { danger: false, confirmLabel: 'Confirmar' }).then(function(ok) {
              if (!ok) return;
              if (voltaParaRascunho) {
                // Limpa desconto_max aprovado e reinicia aprovMaxItems
                setLocalItens(function(prev) {
                  return prev.map(function(it) {
                    var c = Object.assign({}, it);
                    delete c.desconto_max;
                    return c;
                  });
                });
                setAprovMaxItems({});
              }
              persistStatus(targetStatus);
            });
          }}
        />
      </div>

      {/* Banner: pedido emitido — proposta bloqueada para edição */}
      {['pedido', 'pedido_assinado', 'faturamento'].includes(effectiveStatus) && (
        <div style={{ display:'flex', alignItems:'flex-start', gap:12, padding:'14px 18px', marginBottom:18,
                      background: pedido ? '#f0faf4' : '#fff7ed',
                      border: pedido ? '1px solid #b6d9c4' : '1px solid var(--warn)',
                      borderRadius:'var(--r-md)' }}>
          <i data-lucide={pedido ? "lock" : "alert-triangle"} style={{ width:20, height:20, color: pedido ? 'var(--grn)' : 'var(--warn)', flexShrink:0, marginTop:2 }}></i>
          <div style={{ flex:1 }}>
            <div style={{ font:'600 13px/1.3 var(--ff-body)', color: pedido ? 'var(--grn)' : 'var(--warn)' }}>
              {pedido ? 'Proposta bloqueada para edição' : 'Estado inconsistente: pedido não encontrado'}
            </div>
            <div style={{ font:'400 12px/1.5 var(--ff-body)', color:'var(--tx-2)', marginTop:4 }}>
              {pedido
                ? 'Um pedido foi emitido a partir desta proposta. Itens e condições comerciais não podem ser alterados.'
                : 'A proposta está marcada como pedido emitido, mas o pedido não foi localizado. Um gerente pode corrigir o estado.'
              }
            </div>
            {!pedido && isGerente && (
              <button className="btn btn-secondary" style={{ marginTop:10, fontSize:12 }}
                onClick={function() {
                  window.CRM_CONFIRM('Resetar esta proposta para "Em negociação"? O estado ficou inconsistente (nenhum pedido vinculado).',
                    { danger: true, confirmLabel: 'Resetar estado' }
                  ).then(function(ok) { if (ok) persistStatus('em_negociacao'); });
                }}>
                <i data-lucide="rotate-ccw" style={{ width:12, height:12 }}></i> Corrigir estado (gerente)
              </button>
            )}
          </div>
        </div>
      )}

      {/* Banner: proposta cancelada */}
      {effectiveStatus === "cancelada" && (
        <div style={{ display:'flex', alignItems:'flex-start', gap:12, padding:'14px 18px', marginBottom:18, background:'#fef2f2', border:'1px solid var(--danger)', borderRadius:'var(--r-md)' }}>
          <i data-lucide="x-circle" style={{ width:20, height:20, color:'var(--danger)', flexShrink:0, marginTop:2 }}></i>
          <div style={{ flex:1 }}>
            <div style={{ font:'600 13px/1.3 var(--ff-body)', color:'var(--danger)' }}>Proposta cancelada</div>
            <div style={{ font:'400 12px/1.5 var(--ff-body)', color:'var(--tx-2)', marginTop:4 }}>
              {prop.motivo_cancelamento ? <><strong>Motivo:</strong> {prop.motivo_cancelamento}</> : 'Sem motivo registrado.'}
              {prop.cancelada_em && <> · {new Date(prop.cancelada_em).toLocaleString('pt-BR')}</>}
            </div>
            <div style={{ font:'400 11px/1.4 var(--ff-body)', color:'var(--tx-3)', marginTop:4 }}>
              Esta proposta é somente leitura. {pedido && (pedido.status === 'cancelado' || pedido.status === 'cancelado_correcao' || pedido.status === 'cancelado_apos_assinatura') ? 'Pedido vinculado também foi cancelado em cascata.' : ''}
            </div>
          </div>
        </div>
      )}

      {/* Header summary strip */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 10, marginBottom: 18 }}>
        <SummaryStat label="Valor total" value={totalComDesconto > 0 ? fR(totalComDesconto) : fR(prop.valor)} mono accent />
        <SummaryStat label="Equipamentos" value={`${localItens.length} ${localItens.length === 1 ? 'item' : 'itens'}`} />
        <SummaryStat label="Prev. faturamento" value={op?.previsao_fechamento ? fDate(op.previsao_fechamento) : '—'} />
        <SummaryStat label="Status" value={<Badge status={effectiveStatus} />} />
      </div>

      {/* ── Rascunho: 4 cards ─────────────────────────────────────────────────── */}
      {effectiveStatus === "rascunho" && (
        <>
          {/* Validade da Proposta */}
          <div style={{
            padding: '14px 16px', marginBottom: 10,
            background: 'var(--surface-2)',
            border: `1px solid ${!editValidade ? 'var(--danger)' : 'var(--border)'}`,
            borderRadius: 'var(--r-md)',
          }}>
            <div style={{ font: '600 10px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.07em', color: 'var(--tx-3)', marginBottom: 10 }}>
              Validade <span style={{ color: 'var(--danger)' }}>*</span>
            </div>
            <input type="date" value={editValidade} onChange={e => setEditValidade(e.target.value)}
              style={{ width: 220, padding: '7px 8px', border: `1px solid ${!editValidade ? 'var(--danger)' : 'var(--border-2)'}`, borderRadius: 'var(--r-sm)', background: 'var(--surface)', fontFamily: 'var(--ff-mono)', fontSize: 13, color: 'var(--tx)', outline: 'none', boxSizing: 'border-box' }} />
            {!editValidade
              ? <div style={{ font: '400 10px/1.2 var(--ff-body)', color: 'var(--danger)', marginTop: 5 }}>Campo obrigatório</div>
              : <div style={{ font: '400 10px/1.2 var(--ff-body)', color: 'var(--tx-3)', marginTop: 5 }}>
                  {Math.round((new Date(editValidade + 'T12:00:00') - new Date()) / 86400000)} dias restantes
                </div>
            }
          </div>

          {/* Card 4 — Ação + alerta T1 */}
          <div style={{ margin: '0 0 18px' }}>
            {/* Banner de sem itens */}
            {localItens.length === 0 && (
              <div style={{
                display: 'flex', alignItems: 'center', gap: 10,
                padding: '10px 14px', marginBottom: 10,
                background: 'var(--surface-2)', border: '1px solid var(--border)',
                borderRadius: 'var(--r-md)', borderLeft: '3px solid var(--border-2)',
                font: '400 12px/1.4 var(--ff-body)', color: 'var(--tx-3)',
              }}>
                <span style={{ fontSize: 15, flexShrink: 0 }}>ℹ</span>
                <span>Adicione ao menos um item à proposta antes de avançar.</span>
              </div>
            )}
            {/* Banner de aprovação necessária — só aparece quando abaixo do T1 */}
            {localItens.length > 0 && totalComDesconto > 0 && totalComDesconto < vT1 && (
              <div style={{
                display: 'flex', alignItems: 'flex-start', gap: 12,
                padding: '12px 16px', marginBottom: 10,
                background: 'var(--warn-050)', border: '1px solid var(--warn)',
                borderRadius: 'var(--r-md)', borderLeft: '3px solid var(--warn)',
                font: '400 12px/1.5 var(--ff-body)', color: 'var(--tx-2)',
              }}>
                <span style={{ fontSize: 16, flexShrink: 0 }}>⚠️</span>
                <span>
                  Valor da proposta <strong>{fR(totalComDesconto)}</strong> está{' '}
                  <strong style={{ color: 'var(--warn)' }}>{Math.abs(+desvioT1pct)}% abaixo do T1</strong> ({fR(vT1)}) —
                  esta proposta precisará de <strong>aprovação gerencial</strong> antes do envio ao cliente.
                </span>
              </div>
            )}

          </div>
        </>
      )}

      {/* ── Prazos de Entrega — sempre visível ─────────────────────────────── */}
      {itens.length > 0 && Object.keys(prazos).some(k => prazos[k]) || effectiveStatus === 'rascunho' ? (
        <div style={{
          margin: '0 0 14px', padding: '14px 16px',
          background: 'var(--surface-2)', border: '1px solid var(--border)',
          borderRadius: 'var(--r-md)',
        }}>
          <div style={{ font: '600 10px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.07em', color: 'var(--tx-3)', marginBottom: 10 }}>
            Prazos de Entrega
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {itens.map(function(it) {
              var isEditable = effectiveStatus === 'rascunho';
              return (
                <div key={it.sku} style={{ display: 'grid', gridTemplateColumns: '1fr 220px', gap: 12, alignItems: 'center' }}>
                  <div style={{ font: '400 12px/1.2 var(--ff-body)', color: 'var(--tx-2)' }}>
                    <span style={{ font: '600 12px/1 var(--ff-mono)', color: 'var(--tx)' }}>{it.sku}</span> × {it.qtd}
                  </div>
                  {isEditable ? (
                    <input type="text" placeholder="ex: 30 dias, imediato, dez/2026…"
                      value={prazos[it.sku] || ''}
                      style={{ padding: '7px 10px', border: '1px solid var(--border-2)', borderRadius: 'var(--r-sm)', background: 'var(--surface)', fontFamily: 'var(--ff-body)', fontSize: 13, color: 'var(--tx)', outline: 'none', width: '100%', boxSizing: 'border-box' }}
                      onChange={function(e) { setPrazos(function(prev) { return Object.assign({}, prev, { [it.sku]: e.target.value }); }); }} />
                  ) : (
                    <div style={{ padding: '7px 10px', border: '1px solid var(--border)', borderRadius: 'var(--r-sm)', background: 'var(--surface)', fontFamily: 'var(--ff-body)', fontSize: 13, color: prazos[it.sku] ? 'var(--tx)' : 'var(--tx-3)', minHeight: 32 }}>
                      {prazos[it.sku] || <em>Não informado</em>}
                    </div>
                  )}
                </div>
              );
            })}
          </div>
        </div>
      ) : null}

      {/* ── Consultor: aguardando aprovação ─────────────────────────────────── */}
      {effectiveStatus === "aguardando_aprovacao" && !isGerente && (
        <div style={{
          margin: '0 0 18px', padding: '14px 18px',
          background: 'var(--surface-2)', border: '1px solid var(--border)',
          borderRadius: 'var(--r-md)', borderLeft: '3px solid var(--warn)',
        }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>
            <i data-lucide="clock" style={{ width: 18, height: 18, color: 'var(--warn)', flexShrink: 0 }}></i>
            <div style={{ font: '600 12px/1.2 var(--ff-body)', color: 'var(--warn)' }}>Aguardando aprovação gerencial</div>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 0 }}>
            {localItens.map((it, idx) => {
              const valorSolic = Math.round(it.total * (1 - (it.desconto || 0) / 100));
              const aprovado = it.desconto_max != null;
              return (
                <div key={it._localId} style={{ display: 'grid', gridTemplateColumns: '1fr auto auto', gap: 14, alignItems: 'center', padding: '7px 0', borderBottom: idx < localItens.length - 1 ? '1px solid var(--border)' : 'none' }}>
                  <div style={{ font: '600 12px/1 var(--ff-mono)', color: 'var(--tx)' }}>{it.sku}</div>
                  <div style={{ font: '400 11px/1 var(--ff-mono)', color: 'var(--warn)', whiteSpace: 'nowrap' }}>
                    Solicitado: {it.desconto || 0}% → {fR(valorSolic)}
                  </div>
                  {aprovado
                    ? <div style={{ font: '600 11px/1 var(--ff-mono)', color: 'var(--grn)', whiteSpace: 'nowrap' }}>máx {it.desconto_max}% ✓</div>
                    : <div style={{ font: '400 10px/1 var(--ff-body)', color: 'var(--tx-3)', whiteSpace: 'nowrap' }}>pendente</div>
                  }
                </div>
              );
            })}
          </div>
          <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 10, paddingTop: 8, borderTop: '1px solid var(--border)', font: '400 11px/1.5 var(--ff-body)', color: 'var(--tx-3)' }}>
            <span>Total solicitado: <strong style={{ color: 'var(--warn)' }}>{fR(totalComDesconto)}</strong></span>
            <span>Mínimo T1: {fR(vT1)}</span>
          </div>
        </div>
      )}

      {/* ── Gerente: painel de aprovação ────────────────────────────────────── */}
      {effectiveStatus === "aguardando_aprovacao" && isGerente && (
        <div style={{
          margin: '0 0 18px', padding: '16px 18px',
          background: 'var(--surface-2)', border: '1px solid var(--border)',
          borderRadius: 'var(--r-md)', borderLeft: '3px solid var(--warn)',
        }}>
          <div style={{ font: '600 10px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.07em', color: 'var(--warn)', marginBottom: 14 }}>
            ⚠ Aprovação gerencial — desconto máximo por máquina
          </div>

          {/* Tabela por item */}
          <div style={{ overflowX: 'auto', marginBottom: 16 }}>
            <table style={{ width: '100%', borderCollapse: 'collapse', minWidth: 560 }}>
              <thead>
                <tr style={{ background: 'var(--surface)', borderBottom: '2px solid var(--border)' }}>
                  {['Modelo', 'Valor base', 'Desc solic.', 'Valor solic.', 'Desc máx %', 'Valor mín'].map((h, i) => (
                    <th key={i} style={{ padding: '6px 10px', font: '600 10px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.07em', color: 'var(--tx-3)', textAlign: i > 0 ? 'right' : 'left', whiteSpace: 'nowrap' }}>{h}</th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {localItens.map(it => {
                  const valorSolic = Math.round(it.total * (1 - (it.desconto || 0) / 100));
                  const descMax = aprovMaxItems[it._localId] != null ? aprovMaxItems[it._localId] : (it.desconto || 0);
                  const valorMin = Math.round(it.total * (1 - descMax / 100));
                  return (
                    <tr key={it._localId} style={{ borderBottom: '1px solid var(--border)' }}>
                      <td style={{ padding: '8px 10px', font: '600 12px/1 var(--ff-mono)', color: 'var(--tx)', whiteSpace: 'nowrap' }}>{it.sku}</td>
                      <td style={{ padding: '8px 10px', font: '400 12px/1 var(--ff-mono)', color: 'var(--tx-2)', textAlign: 'right' }}>{fR(it.total)}</td>
                      <td style={{ padding: '8px 10px', font: '600 12px/1 var(--ff-mono)', color: 'var(--warn)', textAlign: 'right' }}>{it.desconto || 0}%</td>
                      <td style={{ padding: '8px 10px', font: '400 12px/1 var(--ff-mono)', color: 'var(--warn)', textAlign: 'right' }}>{fR(valorSolic)}</td>
                      <td style={{ padding: '8px 10px', textAlign: 'right' }}>
                        <input
                          type="number" min={0} max={50} step={0.5}
                          value={descMax}
                          style={{ width: 64, padding: '4px 6px', border: '1px solid var(--border-2)', borderRadius: 'var(--r-sm)', background: 'var(--surface)', fontFamily: 'var(--ff-mono)', fontSize: 12, color: 'var(--tx)', textAlign: 'right', outline: 'none' }}
                          onChange={e => {
                            const v = Math.max(0, Math.min(50, +(parseFloat(e.target.value).toFixed(1)) || 0));
                            setAprovMaxItems(prev => ({ ...prev, [it._localId]: v }));
                          }}
                        />
                      </td>
                      <td style={{ padding: '8px 10px', font: '600 12px/1 var(--ff-mono)', color: 'var(--grn)', textAlign: 'right' }}>{fR(valorMin)}</td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>

          {/* DNet + Margens */}
          <div style={{ display: 'grid', gridTemplateColumns: '220px 1fr 1fr', gap: 12, marginBottom: 16 }}>
            <div>
              <label style={{ font: '600 10px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.07em', color: 'var(--tx-3)', display: 'block', marginBottom: 5 }}>DNet global (custo fábrica)</label>
              <input type="number" step={10000} value={editDNet}
                style={{ width: '100%', padding: '7px 8px', border: '1px solid var(--border-2)', borderRadius: 'var(--r-sm)', background: 'var(--surface)', fontFamily: 'var(--ff-mono)', fontSize: 13, color: 'var(--tx)', textAlign: 'right', outline: 'none', boxSizing: 'border-box' }}
                onChange={e => setEditDNet(Math.max(0, Math.round(parseFloat(e.target.value) || 0)))} />
            </div>
            <div style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 'var(--r-sm)', padding: '8px 12px' }}>
              <div style={{ font: '600 9px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.07em', color: 'var(--tx-3)', marginBottom: 4 }}>Margem (solic.)</div>
              <div style={{ font: '600 18px/1 var(--ff-mono)', color: parseFloat(margSolic) < 10 ? 'var(--danger)' : 'var(--ok)' }}>{margSolic}%</div>
              <div style={{ font: '400 10px/1 var(--ff-mono)', color: 'var(--tx-3)', marginTop: 3 }}>sobre {fR(totalComDesconto)}</div>
            </div>
            <div style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 'var(--r-sm)', padding: '8px 12px' }}>
              <div style={{ font: '600 9px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.07em', color: 'var(--tx-3)', marginBottom: 4 }}>Margem (aprovado)</div>
              <div style={{ font: '600 18px/1 var(--ff-mono)', color: parseFloat(margAprov) < 10 ? 'var(--danger)' : 'var(--ok)' }}>{margAprov}%</div>
              <div style={{ font: '400 10px/1 var(--ff-mono)', color: 'var(--tx-3)', marginTop: 3 }}>sobre {fR(totalAprovado)}</div>
            </div>
          </div>

          {/* Recusar / Aprovar */}
          <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
            <button className="btn btn-secondary"
              onClick={() => {
                persistStatusComEvento('rascunho', 'gerente_recusou', 'Aprovação recusada — proposta devolvida ao rascunho');
                // Email ao consultor
                (function() {
                  try {
                    var consultor = window.CRM_DATA && window.CRM_DATA.getUsuario ? window.CRM_DATA.getUsuario(prop.vendedor_id) : null;
                    if (!consultor || !consultor.email) return;
                    var gNome = ''; try { gNome = localStorage.getItem('bauko_user_name') || ''; } catch(e) {}
                    var clienteNome = (window.CRM_DATA && window.CRM_DATA.getCliente ? window.CRM_DATA.getCliente(prop.cliente_id) : null);
                    clienteNome = clienteNome ? clienteNome.razao : prop.cliente_id;
                    var assunto = 'Proposta ' + prop.id + ' — Desconto não aprovado';
                    var corpo = '<p>Olá, <strong>' + consultor.nome + '</strong>!</p>' +
                      '<p>O desconto solicitado para a proposta <strong>' + prop.id + '</strong>' +
                      (clienteNome ? ' (cliente: ' + clienteNome + ')' : '') +
                      ' foi <strong style="color:#c0392b">recusado</strong>' +
                      (gNome ? ' por ' + gNome : '') + '.</p>' +
                      '<p>A proposta foi devolvida ao status <em>Rascunho</em> para revisão.</p>' +
                      '<p style="color:#888;font-size:12px">CRM Bauko Máquinas</p>';
                    window.CRM_API.sendMail(consultor.email, assunto, corpo).catch(function(e) { console.warn('[CRM] sendMail recusou:', e.message); });
                  } catch(err) { console.warn('[CRM] email recusou:', err.message); }
                })();
              }}>
              <i data-lucide="x-circle" style={{ width: 13, height: 13 }}></i> Recusar
            </button>
            <button className="btn btn-primary"
              onClick={() => {
                // Grava desconto_max por item
                setLocalItens(function(prev) {
                  return prev.map(function(it) {
                    var mmax = aprovMaxItems[it._localId];
                    return mmax != null ? Object.assign({}, it, { desconto_max: mmax }) : it;
                  });
                });
                // Atualiza valor da oportunidade com total aprovado
                if (op && totalAprovado > 0) {
                  var opIdx = CRM_DATA.oportunidades ? CRM_DATA.oportunidades.findIndex(function(o){ return o.id === op.id; }) : -1;
                  if (opIdx >= 0) CRM_DATA.oportunidades[opIdx] = Object.assign({}, CRM_DATA.oportunidades[opIdx], { valor: totalAprovado });
                  if (window.CRM_API && op._spId) {
                    CRM_API.updateItem('Oportunidades', op._spId, { valor: totalAprovado }).catch(function(e){ console.warn('[CRM] update op valor aprovado:', e.message); });
                  }
                }
                var gNome=''; try{gNome=localStorage.getItem('bauko_user_name')||'';}catch(e){}
                persistStatusComEvento('aprovada', 'gerente_aprovou', 'Proposta aprovada'+(gNome?' por '+gNome:''));
                // Email ao consultor
                (function() {
                  try {
                    var consultor = window.CRM_DATA && window.CRM_DATA.getUsuario ? window.CRM_DATA.getUsuario(prop.vendedor_id) : null;
                    if (!consultor || !consultor.email) return;
                    var clienteNome = (window.CRM_DATA && window.CRM_DATA.getCliente ? window.CRM_DATA.getCliente(prop.cliente_id) : null);
                    clienteNome = clienteNome ? clienteNome.razao : prop.cliente_id;
                    var assunto = 'Proposta ' + prop.id + ' — Desconto aprovado!';
                    var corpo = '<p>Olá, <strong>' + consultor.nome + '</strong>!</p>' +
                      '<p>O desconto solicitado para a proposta <strong>' + prop.id + '</strong>' +
                      (clienteNome ? ' (cliente: ' + clienteNome + ')' : '') +
                      ' foi <strong style="color:#27ae60">aprovado</strong>' +
                      (gNome ? ' por ' + gNome : '') + '. Você já pode enviar a proposta ao cliente!</p>' +
                      '<p style="color:#888;font-size:12px">CRM Bauko Máquinas</p>';
                    window.CRM_API.sendMail(consultor.email, assunto, corpo).catch(function(e) { console.warn('[CRM] sendMail aprovou:', e.message); });
                  } catch(err) { console.warn('[CRM] email aprovou:', err.message); }
                })();
              }}>
              <i data-lucide="check-circle-2" style={{ width: 13, height: 13 }}></i> Aprovar
            </button>
          </div>
        </div>
      )}

      {/* ── 3 botões de envio ao cliente ──────────────────────────────────── */}
      {(effectiveStatus === "aprovada" || effectiveStatus === "enviada") && (
        <div style={{
          margin: '0 0 18px', padding: '16px 18px',
          background: 'var(--surface-2)', border: '1px solid var(--border)',
          borderRadius: 'var(--r-md)', borderLeft: '3px solid var(--grn)',
        }}>
          <div style={{ font: '600 10px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.07em', color: 'var(--grn)', marginBottom: 14 }}>
            Enviar proposta ao cliente
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 10 }}>
            {/* PDF */}
            <button className="btn btn-secondary" style={{ flexDirection: 'column', padding: '18px 12px', height: 'auto', gap: 8, fontSize: 13, display: 'flex', alignItems: 'center', justifyContent: 'center', lineHeight: 1.3 }}
              onClick={() => { addTimelineEvent('pdf_baixado', 'PDF da proposta baixado/impresso'); window.open(gerarLinkUrl() + '&int=1&print=1', '_blank'); }}>
              <i data-lucide="file-down" style={{ width: 24, height: 24, color: 'var(--info)' }}></i>
              <strong>Baixar PDF</strong>
              <span style={{ font: '400 11px/1.3 var(--ff-body)', color: 'var(--tx-3)', textAlign: 'center' }}>Imprimir ou salvar arquivo</span>
            </button>
            {/* WhatsApp */}
            <button className="btn btn-secondary" style={{ flexDirection: 'column', padding: '18px 12px', height: 'auto', gap: 8, fontSize: 13, display: 'flex', alignItems: 'center', justifyContent: 'center', lineHeight: 1.3 }}
              onClick={() => {
              var cNome = (cli && cli.contato) ? cli.contato.split(' ')[0] : 'Cliente';
              var vldStr = editValidade ? new Date(editValidade + 'T12:00:00').toLocaleDateString('pt-BR') : '—';
              var mdlStr = (op && op.modelo) ? op.modelo : 'equipamento';
              var longLink = gerarLinkUrl();
              var msg1 = 'Olá ' + cNome + ', seguem as condições comerciais da Bauko para o ' + mdlStr + ':\n\n' + longLink + '\n\nValidade: ' + vldStr + '.\nQualquer dúvida estou à disposição!';
              setCustomWppMsg(msg1);
              setWppModeloSel(0);
              setWppLink('');
              if (window.CRM_API && window.CRM_API.encurtarLink) {
                window.CRM_API.encurtarLink(longLink).then(function(short) {
                  setWppLink(short || longLink);
                  if (short && short !== longLink) {
                    setCustomWppMsg(function(prev) { return prev ? prev.replace(longLink, short) : prev; });
                  }
                }).catch(function() { setWppLink(longLink); });
              } else { setWppLink(longLink); }
              setShowWppModal(true);
            }}>
              <i data-lucide="message-circle" style={{ width: 24, height: 24, color: '#25d366' }}></i>
              <strong>WhatsApp</strong>
              <span style={{ font: '400 11px/1.3 var(--ff-body)', color: 'var(--tx-3)', textAlign: 'center' }}>Mensagem + link da proposta</span>
            </button>
            {/* E-mail */}
            <button className="btn btn-secondary" style={{ flexDirection: 'column', padding: '18px 12px', height: 'auto', gap: 8, fontSize: 13, display: 'flex', alignItems: 'center', justifyContent: 'center', lineHeight: 1.3 }}
              onClick={function() { setShowEmailModal(true); }}>
              <i data-lucide="mail" style={{ width: 24, height: 24, color: 'var(--info)' }}></i>
              <strong>E-mail</strong>
              <span style={{ font: '400 11px/1.3 var(--ff-body)', color: 'var(--tx-3)', textAlign: 'center' }}>Enviar pelo serviço de e-mail</span>
            </button>
          </div>
        </div>
      )}

      {/* ── Modal WhatsApp ──────────────────────────────────────────────────── */}
      {showWppModal && (function() {
        var clienteNome = (cli && cli.contato) ? cli.contato.split(' ')[0] : 'Cliente';
        var clienteNomeCompleto = (cli && cli.contato) ? cli.contato : 'Cliente';
        var valorStr = fR(totalComDesconto || prop.valor || 0);
        var validadeStr = editValidade ? new Date(editValidade + 'T12:00:00').toLocaleDateString('pt-BR') : '—';
        var modeloStr = (op && op.modelo) ? op.modelo : 'equipamento';
        var linkDisp = wppLink || gerarLinkUrl();
        var vendNomeWpp = (vend && vend.nome) ? vend.nome : 'Consultor Bauko';
        var equipListWpp = (localItens && localItens.length > 0)
          ? localItens.map(function(it){ var nm = it.sku || it.modelo || it.familia || 'equipamento'; return nm + ((it.qtd||1) > 1 ? ' ×' + (it.qtd||1) : ''); }).join(', ')
          : modeloStr;
        var formatTelWpp = function(d){ var s=(d||'').replace(/\D/g,''); if(s.length===11) return '('+s.slice(0,2)+') '+s.slice(2,7)+'-'+s.slice(7); if(s.length===10) return '('+s.slice(0,2)+') '+s.slice(2,6)+'-'+s.slice(6); return s; };
        var phoneDigitsWpp = wppPhone.replace(/\D/g,'');
        var phoneValidoWpp = phoneDigitsWpp.length >= 10 && phoneDigitsWpp.length <= 11;
        var wppToneLabels = ['Formal', 'Amigável', 'Direto'];
        var msgs = [
          'Prezado(a) ' + clienteNomeCompleto + ',\n\nTenho o prazer de encaminhar a proposta comercial da Bauko referente ao(s) equipamento(s): ' + equipListWpp + '.\n\nRef.: ' + prop.id + ' • Valor: ' + valorStr + ' • Validade: ' + validadeStr + '\n\nAcesse o documento completo pelo link:\n' + linkDisp + '\n\nColoco-me à disposição para esclarecimentos.\n\n' + vendNomeWpp + ' | Bauko Soluções em Equipamentos',
          'Olá ' + clienteNome + '! Segue a proposta Bauko para: ' + equipListWpp + '.\n\n' + prop.id + ' • ' + valorStr + ' • Válida até ' + validadeStr + '\n\n' + linkDisp + '\n\nQualquer dúvida, é só chamar!',
          prop.id + ' | ' + equipListWpp + '\n' + valorStr + ' | Val: ' + validadeStr + '\n' + linkDisp + ' – ' + vendNomeWpp + '/Bauko',
        ];
        return (
          <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,.55)', zIndex: 9999, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '16px' }}
            onClick={e => { if (e.target === e.currentTarget) { setShowWppModal(false); setWppLink(''); } }}>
            <div style={{ background: 'var(--surface)', borderRadius: 'var(--r-lg)', padding: '24px 28px', width: '100%', maxWidth: 560, maxHeight: '90vh', overflowY: 'auto', boxShadow: 'var(--shadow-3)' }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }}>
                <div style={{ font: '600 14px/1 var(--ff-body)', color: 'var(--tx)', display: 'flex', alignItems: 'center', gap: 8 }}>
                  <i data-lucide="message-circle" style={{ width: 18, height: 18, color: '#25d366' }}></i> Enviar via WhatsApp
                </div>
                <button className="btn btn-ghost" style={{ padding: '4px 8px' }} onClick={() => { setShowWppModal(false); setWppLink(''); }}>
                  <i data-lucide="x" style={{ width: 16, height: 16 }}></i>
                </button>
              </div>
              <div style={{ marginBottom: 14 }}>
                <label style={{ font: '600 10px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.07em', color: 'var(--tx-3)', display: 'block', marginBottom: 5 }}>Telefone do cliente (com DDD)</label>
                <input type="tel" value={formatTelWpp(wppPhone)} onChange={e => setWppPhone(e.target.value.replace(/\D/g,''))}
                  placeholder="(11) 99999-9999"
                  style={{ width: '100%', padding: '8px 10px', border: '1px solid ' + (wppPhone && !phoneValidoWpp ? 'var(--danger)' : 'var(--border-2)'), borderRadius: 'var(--r-sm)', background: 'var(--surface)', fontFamily: 'var(--ff-mono)', fontSize: 13, color: 'var(--tx)', outline: 'none', boxSizing: 'border-box' }} />
              </div>
              <div style={{ marginBottom: 14 }}>
                <label style={{ font: '600 10px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.07em', color: 'var(--tx-3)', display: 'block', marginBottom: 6 }}>Link da proposta</label>
                <div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>
                  <input readOnly value={wppLink || 'gerando link curto…'}
                    style={{ flex: 1, padding: '7px 10px', border: '1px solid var(--grn)', borderRadius: 'var(--r-sm)', background: 'var(--surface)', fontFamily: 'var(--ff-mono)', fontSize: 11, color: 'var(--tx)', outline: 'none', boxSizing: 'border-box' }} />
                  <button className="btn btn-secondary" style={{ fontSize: 11, padding: '7px 10px', whiteSpace: 'nowrap' }}
                    onClick={function() { try { navigator.clipboard.writeText(wppLink || gerarLinkUrl()); } catch(e){} }}>
                    <i data-lucide="copy" style={{ width: 12, height: 12 }}></i> Copiar
                  </button>
                </div>
              </div>
              <div style={{ marginBottom: 14 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
                  <label style={{ font: '600 10px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.07em', color: 'var(--tx-3)' }}>Mensagem</label>
                  <div style={{ display: 'flex', gap: 4 }}>
                    {msgs.map(function(m, i) {
                      var _atv = wppModeloSel === i;
                      return (
                        <button key={i} className="btn btn-ghost"
                          style={{ fontSize: 11, padding: '4px 9px',
                            border: '1px solid ' + (_atv ? 'var(--grn)' : 'var(--border-2)'),
                            background: _atv ? 'var(--ok-050)' : '',
                            color: _atv ? 'var(--grn)' : '',
                            fontWeight: _atv ? 600 : 400 }}
                          onClick={function() { setCustomWppMsg(m); setWppModeloSel(i); }}>
                          {wppToneLabels[i]}
                        </button>
                      );
                    })}
                  </div>
                </div>
                <textarea rows={7} value={customWppMsg} onChange={function(e) { setCustomWppMsg(e.target.value); setWppModeloSel(-1); }}
                  placeholder="Selecione um modelo acima ou escreva sua mensagem…"
                  style={{ width: '100%', padding: '8px 10px', border: '1px solid var(--border-2)', borderRadius: 'var(--r-sm)', background: 'var(--surface)', fontFamily: 'var(--ff-body)', fontSize: 13, color: 'var(--tx)', outline: 'none', boxSizing: 'border-box', resize: 'vertical', lineHeight: 1.6 }} />
              </div>
              <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', borderTop: '1px solid var(--border)', paddingTop: 16 }}>
                <button className="btn btn-secondary" onClick={() => { setShowWppModal(false); setWppLink(''); }}>Cancelar</button>
                <button disabled={!phoneValidoWpp || !wppLink} style={{ background: '#25d366', color: '#fff', border: 'none', borderRadius: 'var(--r-sm)', padding: '8px 16px', fontSize: 13, fontWeight: 600, cursor: (phoneValidoWpp && wppLink) ? 'pointer' : 'not-allowed', opacity: (phoneValidoWpp && wppLink) ? 1 : 0.5, display: 'flex', alignItems: 'center', gap: 6 }}
                  onClick={function() {
                    var phone = wppPhone.replace(/\D/g,'');
                    var msg = customWppMsg || '';
                    if (!msg.trim()) { window.CRM_TOAST('Escreva ou selecione uma mensagem antes de continuar.', 'warn'); return; }
                    var url = 'https://wa.me/' + (phone ? '55' + phone : '') + '?text=' + encodeURIComponent(msg);
                    window.open(url, '_blank');
                    addTimelineEvent('enviada_wpp', 'Proposta enviada por WhatsApp' + (phone ? ' para +55' + phone : ''));
                    setShowWppModal(false); setWppLink('');
                  }}>
                  <i data-lucide="send" style={{ width: 14, height: 14 }}></i> Abrir WhatsApp
                </button>
              </div>
            </div>
          </div>
        );
      })()}

      {/* ── Modal E-mail ────────────────────────────────────────────────────── */}
      {showEmailModal && (function() {
        // Após envio: se o email usado difere do cadastro → pergunta se quer salvar
        function verificarSalvarEmailCli(emailUsado) {
          if (!emailUsado || !cli || !cli._spId) return;
          if (emailUsado === (cli.email || '')) return; // já cadastrado, nada a fazer
          if (!window.CRM_CONFIRM) return;
          window.CRM_CONFIRM(
            'Adicionar "' + emailUsado + '" ao cadastro de ' + (cli.razao || 'este cliente') + '?',
            { confirmLabel: 'Salvar no cadastro' }
          ).then(function(ok) {
            if (!ok) return;
            cli.email = emailUsado;
            if (window.CRM_DATA && CRM_DATA.clientes) {
              var idx = CRM_DATA.clientes.findIndex(function(c){ return c.id === cli.id; });
              if (idx >= 0) CRM_DATA.clientes[idx] = Object.assign({}, CRM_DATA.clientes[idx], { email: emailUsado });
            }
            if (window.CRM_API) CRM_API.updateItem('Clientes', cli._spId, { email: emailUsado })
              .catch(function(e){ console.warn('[CRM] salvar email cliente:', e.message); });
          });
        }
        function enviarEmail() {
          if (!emailDestinatario || !emailDestinatario.includes('@')) { window.CRM_TOAST('Informe um e-mail válido.', 'warn'); return; }
          var dados = JSON.stringify({
            id: prop.id, versao: prop.versao||1, data: prop.data,
            validade: editValidade||prop.validade,
            op: op ? { titulo: op.titulo||'', familia: op.familia||'', modelo: op.modelo||'', descricao: (op.descricao||'').slice(0,200), fabricante: (localItens&&localItens[0]&&localItens[0].familia)||op.familia||'', descricao_tecnica: (localItens&&localItens[0]&&localItens[0].descricao_tecnica)||'' } : {},
            cli: cli ? { razao: cli.razao||'', cnpj: cli.cnpj||'', cidade: cli.cidade||'', uf: cli.uf||'', contato: cli.contato||'', contato_nome: (op&&op.contato_nome)||'' } : {},
            vend: vend ? { nome: vend.nome||'', cargo: vend.cargo||'', email: vend.email||'' } : {},
            itens: localItens.map(function(it){ var dm=aprovMaxItems[it._localId]; return { sku: it.sku, familia: it.familia||'', desc: it.desc||'', descricao_tecnica: it.descricao_tecnica||'', qtd: it.qtd||it.quantidade||1, total: it.total||0, desconto: dm!=null?dm:(it.desconto||0), prazo: (prazos&&prazos[it.sku])||'', frete_tipo: it.frete_tipo||'', garantia: it.garantia||'', icms_saida: it.icms_saida||0, composicao: it.composicao||[] }; }),
          });
          var compressed = (typeof LZString!=='undefined') ? LZString.compressToEncodedURIComponent(dados) : btoa(unescape(encodeURIComponent(dados)));
          var linkPublico = window.location.origin + '/crm/proposta-publica.html?d=' + compressed;
          var assunto = emailAssunto || ('Proposta Comercial — ' + prop.id);

          // Encurta link (Netlify Blobs) antes de montar o corpo (fallback: link original)
          function montarEEnviar(linkFinal) {
            // Converte corpo editável → HTML, substituindo tag do botão pelo link real
          var corpoHtml = (emailCorpoEdit || '')
            .replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
            .replace(/\[Visualizar Proposta Completa\]/g,
              '</p><p style="margin:20px 0"><a href="'+linkFinal+'" style="background:#007c44;color:#fff;padding:11px 22px;text-decoration:none;border-radius:5px;font-weight:600;display:inline-block">Visualizar Proposta Completa</a></p><p>')
            .replace(/\n/g,'<br>');
          var htmlBody = '<div style="font-family:Arial,sans-serif;font-size:14px;line-height:1.6;color:#333"><p>' + corpoHtml + '</p></div>';
          var bodyPlain = (emailCorpoEdit || '') + '\n\nLink da proposta:\n' + linkFinal;
            setEmailEnviando(true);
            function doMailto() {
              window.location.href='mailto:'+emailDestinatario+'?subject='+encodeURIComponent(assunto)+'&body='+encodeURIComponent(bodyPlain);
              addTimelineEvent('enviada_email','Proposta enviada por e-mail (mailto) para '+emailDestinatario);
              setEmailEnviando(false); setShowEmailModal(false);
              verificarSalvarEmailCli(emailDestinatario);
            }
            if (window.CRM_API && window.CRM_API.sendMail) {
              CRM_API.sendMail(emailDestinatario, assunto, htmlBody, bodyPlain).then(function() {
                addTimelineEvent('enviada_email','Proposta enviada por e-mail (Outlook) para '+emailDestinatario);
                setEmailEnviando(false); setShowEmailModal(false);
                verificarSalvarEmailCli(emailDestinatario);
              }).catch(function(e) {
                console.warn('[CRM] sendMail falhou, usando mailto:', e.message);
                doMailto();
              });
            } else { doMailto(); }
          } // fim montarEEnviar

          setEmailEnviando(true);
          // Tenta encurtar o link antes de enviar; fallback transparente
          if (window.CRM_API && window.CRM_API.encurtarLink) {
            window.CRM_API.encurtarLink(linkPublico).then(function(short) { montarEEnviar(short); }).catch(function() { montarEEnviar(linkPublico); });
          } else { montarEEnviar(linkPublico); }
        }
        return (
          <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,.55)', zIndex: 9999, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '16px' }}
            onClick={function(e) { if (e.target===e.currentTarget) setShowEmailModal(false); }}>
            <div style={{ background: 'var(--surface)', borderRadius: 'var(--r-lg)', padding: '24px 28px', width: '100%', maxWidth: 560, boxShadow: 'var(--shadow-3)', maxHeight: '90vh', overflowY: 'auto' }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }}>
                <div style={{ font: '600 14px/1 var(--ff-body)', color: 'var(--tx)', display: 'flex', alignItems: 'center', gap: 8 }}>
                  <i data-lucide="mail" style={{ width: 18, height: 18, color: 'var(--info)' }}></i> Enviar por E-mail
                </div>
                <button className="btn btn-ghost" style={{ padding: '4px 8px' }} onClick={function() { setShowEmailModal(false); }}>
                  <i data-lucide="x" style={{ width: 16, height: 16 }}></i>
                </button>
              </div>
              <div style={{ marginBottom: 14 }}>
                <label style={{ font: '600 10px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.07em', color: 'var(--tx-3)', display: 'block', marginBottom: 5 }}>Destinatário *</label>
                <input type="email" value={emailDestinatario} onChange={function(e) { setEmailDestinatario(e.target.value); }}
                  placeholder="email@cliente.com.br"
                  style={{ width: '100%', padding: '8px 10px', border: '1px solid var(--border-2)', borderRadius: 'var(--r-sm)', background: 'var(--surface)', fontFamily: 'var(--ff-mono)', fontSize: 13, color: 'var(--tx)', outline: 'none', boxSizing: 'border-box' }} />
              </div>
              <div style={{ marginBottom: 14 }}>
                <label style={{ font: '600 10px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.07em', color: 'var(--tx-3)', display: 'block', marginBottom: 5 }}>Assunto</label>
                <input type="text" value={emailAssunto} onChange={function(e) { setEmailAssunto(e.target.value); }}
                  style={{ width: '100%', padding: '8px 10px', border: '1px solid var(--border-2)', borderRadius: 'var(--r-sm)', background: 'var(--surface)', fontFamily: 'var(--ff-body)', fontSize: 13, color: 'var(--tx)', outline: 'none', boxSizing: 'border-box' }} />
              </div>
              <div style={{ marginBottom: 14 }}>
                {(function(){
                  var _nc = (cli && cli.contato) ? cli.contato : 'cliente';
                  var _vn = (vend && vend.nome) ? vend.nome : 'Equipe Bauko';
                  var _vs = fR(totalComDesconto || prop.valor || 0);
                  var _vd = editValidade ? new Date(editValidade + 'T12:00:00').toLocaleDateString('pt-BR') : '—';
                  var _eq = (localItens && localItens.length > 0) ? localItens.map(function(it){ return it.sku || it.modelo || it.familia || 'equipamento'; }).join(', ') : ((op&&op.modelo)||'equipamento');
                  var emailMsgs = [
                    'Prezado(a) ' + _nc + ',\n\nÉ um prazer dar continuidade ao nosso atendimento.\n\nConforme conversamos, segue a proposta comercial da Bauko referente ao(s) equipamento(s):\n' + _eq + '\n\nRef.: ' + prop.id + ' • Valor do Investimento: ' + _vs + ' • Validade: ' + _vd + '\n\nPara conferir todos os detalhes técnicos, condições de pagamento e prazos, acesse o documento completo:\n\n[Visualizar Proposta Completa]\n\nColocamo-nos à disposição para qualquer esclarecimento.\n\nAtenciosamente,\n' + _vn + '\nBauko Soluções em Equipamentos',
                    'Olá ' + _nc + ',\n\nSegue a proposta da Bauko para: ' + _eq + '.\n\n' + prop.id + ' • Valor: ' + _vs + ' • Válida até: ' + _vd + '\n\nAcesse pelo link — qualquer dúvida é só falar!\n\n[Visualizar Proposta Completa]\n\nAbraços,\n' + _vn + ' – Bauko',
                    'Caro(a) ' + _nc + ',\n\n' + prop.id + ' | ' + _eq + ' | ' + _vs + ' | Val. ' + _vd + '\n\n[Visualizar Proposta Completa]\n\n' + _vn + ' – Bauko',
                  ];
                  var _emailTones = ['Formal', 'Amigável', 'Direto'];
                  return (
                    <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:8 }}>
                      <label style={{ font: '600 10px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.07em', color: 'var(--tx-3)' }}>Mensagem</label>
                      <div style={{ display:'flex', gap:4 }}>
                        {_emailTones.map(function(lbl, i) {
                          var _atv = emailModeloSel === i;
                          return (
                            <button key={i} className="btn btn-ghost"
                              style={{ fontSize:11, padding:'4px 9px',
                                border:'1px solid ' + (_atv ? 'var(--info)' : 'var(--border-2)'),
                                background: _atv ? 'var(--info-050)' : '',
                                color: _atv ? 'var(--info)' : '',
                                fontWeight: _atv ? 600 : 400 }}
                              onClick={function(){ setEmailCorpoEdit(emailMsgs[i]); setEmailModeloSel(i); }}>
                              {lbl}
                            </button>
                          );
                        })}
                      </div>
                    </div>
                  );
                })()}
                <textarea value={emailCorpoEdit} onChange={function(e) { setEmailCorpoEdit(e.target.value); }}
                  rows={12}
                  style={{ width: '100%', padding: '9px 10px', border: '1px solid var(--border-2)', borderRadius: 'var(--r-sm)', background: 'var(--surface)', fontFamily: 'var(--ff-body)', fontSize: 13, color: 'var(--tx)', outline: 'none', boxSizing: 'border-box', resize: 'vertical', lineHeight: 1.5 }} />
              </div>
              <div style={{ padding: '9px 12px', background: 'var(--info-050)', border: '1px solid var(--info)', borderRadius: 'var(--r-sm)', font: '400 11px/1.4 var(--ff-body)', color: 'var(--tx-2)', marginBottom: 16 }}>
                Se o envio via Outlook falhar, o app de e-mail padrão será aberto.
              </div>
              <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
                <button className="btn btn-secondary" disabled={emailEnviando} onClick={function() { setShowEmailModal(false); }}>Cancelar</button>
                <button className="btn btn-primary" disabled={emailEnviando || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailDestinatario.trim())} onClick={enviarEmail}>
                  <i data-lucide="send" style={{ width: 14, height: 14 }}></i> {emailEnviando ? 'Enviando…' : 'Enviar e-mail'}
                </button>
              </div>
            </div>
          </div>
        );
      })()}

      {/* ── Em negociação ───────────────────────────────────────────────── */}
      {effectiveStatus === "em_negociacao" && (
        <div style={{
          margin: '0 0 18px', padding: '14px 18px',
          background: 'var(--surface-2)', border: '1px solid var(--border)',
          borderRadius: 'var(--r-md)', borderLeft: '3px solid var(--info)',
          display: 'flex', alignItems: 'center', gap: 14,
        }}>
          <i data-lucide="message-circle" style={{ width: 22, height: 22, color: 'var(--info)', flexShrink: 0 }}></i>
          <div>
            <div style={{ font: '600 12px/1.2 var(--ff-body)', color: 'var(--info)', marginBottom: 4 }}>Em negociação</div>
            <div style={{ font: '400 11px/1.5 var(--ff-body)', color: 'var(--tx-3)' }}>
              Proposta enviada · aguardando decisão do cliente. Quando confirmado, clique em <strong>Emitir Pedido</strong> no rodapé.
            </div>
          </div>
        </div>
      )}

      {/* Tabs */}
      <div className="tabs" style={{ marginBottom: 16 }}>
        <button className={tab === "doc" ? "is-on" : ""} onClick={() => setTab("doc")}><i data-lucide="file-text"></i> Proposta</button>
        <button className={tab === "items" ? "is-on" : ""} onClick={() => setTab("items")}><i data-lucide="list"></i> Itens</button>
        <button className={tab === "pedido" ? "is-on" : ""} onClick={() => setTab("pedido")}><i data-lucide="file-check"></i> Pedido</button>
        <button className={tab === "timeline" ? "is-on" : ""} onClick={() => setTab("timeline")}><i data-lucide="git-commit"></i> Linha do tempo</button>
      </div>

      {/* Tab content */}
      {tab === "doc" && <DocViewerTab prop={prop} cli={cli} op={op} vend={vend} itens={itens} subtotal={subtotal} desconto={desconto} total={total} />}
      {tab === "items" && <ItemsTab
              itens={itens}
              prop={prop}
              isGerente={isGerente}
              onUpdateDesconto={(localId, desc) => setLocalItens(prev => prev.map(it => it._localId === localId ? { ...it, desconto: desc } : it))}
              orphanedItens={orphanedItens}
              onMantarOrfaos={() => setOrphanedItens([])}
              onRemoverOrfaos={() => {
                const orphanIds = new Set(orphanedItens.map(it => it._spId || it._localId));
                setLocalItens(prev => prev.filter(it => !orphanIds.has(it._spId || it._localId)));
                setOrphanedItens([]);
              }}
              readonlyDesconto={["enviada", "em_negociacao", "pedido", "pedido_assinado", "faturamento"].includes(effectiveStatus) || (effectiveStatus === "aguardando_aprovacao" && !isGerente)}
              readOnly={['enviada', 'em_negociacao', 'pedido', 'pedido_assinado', 'faturamento'].includes(effectiveStatus)}
            />}
      {tab === "timeline" && <ProposalTimeline events={events} />}
      {tab === "pedido" && (pedido ? (
        <PedidoDocTab
          pedido={pedido}
          prop={prop}
          cli={cli}
          op={op}
          vend={vend}
          gerarLinkPedido={gerarLinkPedido}
          addTimelineEvent={addTimelineEvent}
          persistStatusComEvento={persistStatusComEvento}
          effectiveStatus={effectiveStatus}
          wppPhoneInit={(cli && cli.telefone) ? cli.telefone.replace(/\D/g,'') : ''}
          emailInit={(cli && cli.email) || ''}
          isGerente={isGerente}
          onCorrigirPedido={function(){ setShowCorrigirModal(true); }}
        />
      ) : (
        <div style={{ padding: '48px 24px', textAlign: 'center', color: 'var(--tx-3)' }}>
          {['pedido', 'pedido_assinado', 'faturamento'].includes(effectiveStatus) ? (
            <>
              <i data-lucide="alert-triangle" style={{ width: 36, height: 36, color: 'var(--warn)', display: 'block', margin: '0 auto 14px' }}></i>
              <div style={{ font: '500 14px/1 var(--ff-body)', color: 'var(--warn)', marginBottom: 6 }}>Estado inconsistente</div>
              <div style={{ font: '400 12px/1.6 var(--ff-body)', color: 'var(--tx-2)', maxWidth: 300, margin: '0 auto 16px' }}>
                A proposta está marcada como pedido emitido, mas nenhum pedido foi encontrado.
                {isGerente ? ' Um gerente pode corrigir o estado abaixo.' : ' Solicite ao gerente que corrija o estado.'}
              </div>
              {isGerente && (
                <div style={{ display:'flex', gap:8, justifyContent:'center', flexWrap:'wrap' }}>
                  <button className="btn btn-primary" style={{ fontSize:12, gap:6 }}
                    onClick={function(){ setShowPedidoModal(true); persistStatus('em_negociacao'); }}>
                    <i data-lucide="package" style={{ width:12, height:12 }}></i> Emitir Pedido agora
                  </button>
                  <button className="btn btn-secondary" style={{ fontSize:12 }}
                    onClick={function() {
                      window.CRM_CONFIRM('Resetar esta proposta para "Em negociação"?',
                        { danger: true, confirmLabel: 'Resetar estado' }
                      ).then(function(ok) { if (ok) persistStatus('em_negociacao'); });
                    }}>
                    <i data-lucide="rotate-ccw" style={{ width:12, height:12 }}></i> Corrigir estado
                  </button>
                </div>
              )}
            </>
          ) : (
            <>
              <i data-lucide="package" style={{ width: 36, height: 36, color: 'var(--border-2)', display: 'block', margin: '0 auto 14px' }}></i>
              <div style={{ font: '500 14px/1 var(--ff-body)', color: 'var(--tx-3)', marginBottom: 6 }}>Nenhum pedido emitido</div>
              <div style={{ font: '400 12px/1.6 var(--ff-body)', color: 'var(--tx-3)', maxWidth: 280, margin: '0 auto' }}>
                {effectiveStatus === 'em_negociacao'
                  ? 'Clique em "Emitir Pedido" abaixo para gerar o pedido.'
                  : 'Avance a proposta para "Em negociação" e clique em "Emitir Pedido".'}
              </div>
            </>
          )}
        </div>
      ))}

      {/* Footer actions */}
      <div style={{
        marginTop: 22, paddingTop: 16, borderTop: "1px solid var(--border)",
        display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10, flexWrap: "wrap",
      }}>
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          <div style={{ display: "flex", gap: 6, alignItems: "center", font: "400 11px/1 var(--ff-mono)", color: "var(--tx-3)" }}>
            <i data-lucide="user" style={{ width: 13, height: 13 }}></i>
            Responsável: {vend?.nome} · {vend?.cargo}
          </div>

        </div>
        <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
          {effectiveStatus !== "cancelada" && (
            <button
              className="btn btn-ghost"
              onClick={handleExcluirProposta}
              title="Cancelar proposta"
              style={{ color: "var(--warn)", borderColor: "var(--warn)", marginRight: 4 }}
            >
              <i data-lucide="x-circle" style={{ width: 15, height: 15 }}></i> Cancelar
            </button>
          )}
{(effectiveStatus === "rascunho" || effectiveStatus === "aprovada" || effectiveStatus === "enviada") && (
            <button className="btn btn-primary" onClick={handleProximaEtapa} style={{ gap: 6 }}>
              <i data-lucide="arrow-right" style={{ width: 14, height: 14 }}></i>
              {effectiveStatus === "rascunho" && "Próxima etapa"}
              {effectiveStatus === "aprovada" && "Confirmar envio"}
              {effectiveStatus === "enviada" && "Confirmar envio"}
            </button>
          )}


          {((effectiveStatus === "em_negociacao" && (!pedido || pedido.status === 'cancelado_correcao' || pedido.status === 'cancelado_apos_assinatura')) || (effectiveStatus === 'pedido' && !pedido)) && (
            <button className="btn btn-primary" onClick={() => setShowPedidoModal(true)} style={{ gap: 6 }}>
              <i data-lucide="package" style={{ width: 14, height: 14 }}></i>
              {pedido ? 'Emitir novo pedido' : 'Emitir Pedido'}
            </button>
          )}
          {pedido && (function() {
            var pedCancelado = pedido.status === 'cancelado_correcao' || pedido.status === 'cancelado_apos_assinatura';
            var bg = pedCancelado ? '#fef2f2' : 'var(--grn-050, #f0faf4)';
            var border = pedCancelado ? '1px solid #fecaca' : '1px solid var(--grn-100, #c3e6d3)';
            var iconColor = pedCancelado ? 'var(--danger)' : 'var(--grn)';
            var textColor = pedCancelado ? 'var(--danger)' : 'var(--grn)';
            var icon = pedCancelado ? 'rotate-ccw' : 'package';
            return (
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '6px 12px', background: bg, border: border, borderRadius: 'var(--r-md)' }}>
                <i data-lucide={icon} style={{ width: 13, height: 13, color: iconColor }}></i>
                <span style={{ font: '600 12px/1 var(--ff-mono)', color: textColor, textDecoration: pedCancelado ? 'line-through' : 'none' }}>{pedido.id}</span>
                <span style={{ font: '400 11px/1 var(--ff-body)', color: 'var(--tx-3)' }}>{pedCancelado ? '· Cancelado' : '· ' + pedido.unidade_bauko}</span>
              </div>
            );
          })()}
        </div>
      </div>
      <ConfirmarEnvioModal
        open={showConfirmarEnvio}
        onClose={() => setShowConfirmarEnvio(false)}
        onConfirm={handleConfirmarEnvio}
      />
      {/* Modal Cancelar/Excluir Proposta — unificado */}
      {showExcluirModal && (function() {
        var pedidoAtivo = pedido && pedido.status !== 'cancelado' && pedido.status !== 'cancelado_correcao' && pedido.status !== 'cancelado_apos_assinatura';
        var motivoOk = excluirMotivo.trim().length >= 10;
        var podeCancelar = motivoOk && excluirChecked;
        var podeExcluir  = excluirChecked;
        var isExcluir = excluirModoDelete;
        return (
          <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.6)', zIndex:10100, display:'flex', alignItems:'center', justifyContent:'center', padding:16 }}
            onClick={e => { if (e.target === e.currentTarget) setShowExcluirModal(false); }}>
            <div style={{ background:'var(--surface)', borderRadius:'var(--r-lg)', padding:'28px 32px', width:'100%', maxWidth:500, boxShadow:'var(--shadow-3)' }}>
              {/* Header */}
              <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:16 }}>
                <div style={{ width:36, height:36, borderRadius:'50%', background: isExcluir ? '#fef2f2' : '#fff7ed', display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
                  <i data-lucide={isExcluir ? 'trash-2' : 'x-circle'} style={{ width:18, height:18, color: isExcluir ? 'var(--danger)' : '#c2410c' }}></i>
                </div>
                <div>
                  <div style={{ font:'600 15px/1.2 var(--ff-body)', color:'var(--tx)' }}>
                    {isExcluir ? 'Excluir proposta definitivamente' : 'Cancelar proposta'} {prop.id}
                  </div>
                  <div style={{ font:'400 11px/1.4 var(--ff-mono)', color:'var(--tx-3)', marginTop:3 }}>
                    {isExcluir ? 'Esta ação removerá os registros do SharePoint.' : 'Mantém histórico no SharePoint para auditoria.'}
                  </div>
                </div>
              </div>

              {/* Cascade impacts */}
              {pedidoAtivo && (
                <div style={{ background:'var(--surface-2)', border:'1px solid var(--border)', borderRadius:'var(--r-md)', padding:'12px 14px', marginBottom:14 }}>
                  <div style={{ font:'600 10px/1 var(--ff-body)', textTransform:'uppercase', letterSpacing:'.07em', color:'var(--tx-3)', marginBottom:8 }}>
                    Itens vinculados que serão {isExcluir ? 'excluídos' : 'cancelados em cascata'}
                  </div>
                  <ul style={{ margin:0, paddingLeft:16, font:'400 12px/1.7 var(--ff-body)', color:'var(--tx-2)' }}>
                    <li>Pedido <strong>{pedido.id}</strong> ({pedido.unidade_bauko || 'sem unidade'})</li>
                  </ul>
                </div>
              )}

              {/* Motivo — só pra cancelar */}
              {!isExcluir && (
                <div style={{ marginBottom:14 }}>
                  <label style={{ font:'600 10px/1 var(--ff-body)', textTransform:'uppercase', letterSpacing:'.07em', color:'var(--tx-3)', display:'block', marginBottom:6 }}>
                    Motivo do cancelamento <span style={{ color:'var(--danger)' }}>*</span>
                    <span style={{ font:'400 9px/1 var(--ff-body)', color:'var(--tx-3)', textTransform:'none', marginLeft:6 }}>(mín. 10 caracteres)</span>
                  </label>
                  <textarea rows={3} value={excluirMotivo} onChange={e => setExcluirMotivo(e.target.value)}
                    placeholder="Ex: cliente decidiu não seguir, proposta substituída por outra…"
                    style={{ width:'100%', padding:'9px 11px', border:'1px solid var(--border-2)', borderRadius:'var(--r-sm)', background:'var(--surface)', fontFamily:'var(--ff-body)', fontSize:13, color:'var(--tx)', outline:'none', boxSizing:'border-box', resize:'vertical', lineHeight:1.5 }} />
                  <div style={{ font:'400 10px/1.2 var(--ff-body)', color: motivoOk ? 'var(--tx-3)' : 'var(--danger)', marginTop:4 }}>
                    {excluirMotivo.trim().length}/10 caracteres
                  </div>
                </div>
              )}

              {/* Aviso pra excluir */}
              {isExcluir && (
                <div style={{ background:'#fef2f2', border:'1px solid var(--danger)', borderRadius:'var(--r-sm)', padding:'12px 14px', marginBottom:14, display:'flex', gap:10, alignItems:'flex-start' }}>
                  <i data-lucide="alert-triangle" style={{ width:16, height:16, color:'var(--danger)', flexShrink:0, marginTop:1 }}></i>
                  <div style={{ font:'400 12px/1.55 var(--ff-body)', color:'#7f1d1d' }}>
                    <strong>Atenção:</strong> esta ação é irreversível. A proposta{pedidoAtivo ? ' e o pedido vinculado' : ''} serão removidos do SharePoint e não poderão ser recuperados.
                  </div>
                </div>
              )}

              {/* Checkbox confirmação */}
              <label style={{ display:'flex', alignItems:'flex-start', gap:10, cursor:'pointer', marginBottom:14, padding:'12px 14px', background: isExcluir ? 'var(--danger-050)' : 'var(--surface-2)', border:'1px solid ' + (isExcluir ? 'var(--danger-100)' : 'var(--border)'), borderRadius:'var(--r-sm)' }}>
                <input type="checkbox" checked={excluirChecked} onChange={e => setExcluirChecked(e.target.checked)}
                  style={{ marginTop:2, width:15, height:15, accentColor: isExcluir ? 'var(--danger)' : 'var(--warn)', flexShrink:0, cursor:'pointer' }} />
                <span style={{ font:'500 12px/1.5 var(--ff-body)', color: isExcluir ? 'var(--danger)' : 'var(--tx-2)' }}>
                  {isExcluir
                    ? <>Confirmo que desejo excluir permanentemente a proposta <strong>{prop.id}</strong>{pedidoAtivo ? <> e o pedido <strong>{pedido.id}</strong></> : ''}.</>
                    : <>Confirmo que a proposta <strong>{prop.id}</strong>{pedidoAtivo ? <> e o pedido vinculado</> : ''} serão cancelados.</>}
                </span>
              </label>

              {/* Link de troca pra excluir (só gerente) */}
              {isGerente && !isExcluir && (
                <div style={{ paddingTop:10, borderTop:'1px dashed var(--border)', textAlign:'right' }}>
                  <button onClick={() => { setExcluirModoDelete(true); setExcluirChecked(false); }}
                    style={{ background:'none', border:'none', cursor:'pointer', font:'400 11px/1 var(--ff-body)', color:'var(--danger)', textDecoration:'underline', padding:0 }}>
                    Ou excluir definitivamente (apenas gerente)
                  </button>
                </div>
              )}
              {isGerente && isExcluir && (
                <div style={{ paddingTop:10, borderTop:'1px dashed var(--border)', textAlign:'right' }}>
                  <button onClick={() => { setExcluirModoDelete(false); setExcluirChecked(false); }}
                    style={{ background:'none', border:'none', cursor:'pointer', font:'400 11px/1 var(--ff-body)', color:'var(--tx-2)', textDecoration:'underline', padding:0 }}>
                    ← Voltar para cancelar (sem excluir)
                  </button>
                </div>
              )}

              {/* Botões */}
              <div style={{ display:'flex', gap:10, justifyContent:'flex-end', marginTop:18 }}>
                <button className="btn btn-ghost" onClick={() => setShowExcluirModal(false)}>Voltar</button>
                <button className="btn"
                  disabled={isExcluir ? !podeExcluir : !podeCancelar}
                  onClick={() => isExcluir ? handleConfirmarExclusao() : handleCancelarProposta(excluirMotivo.trim())}
                  style={{
                    background: isExcluir
                      ? (podeExcluir ? 'var(--danger)' : 'var(--border)')
                      : (podeCancelar ? 'var(--warn)' : 'var(--border)'),
                    color: ((isExcluir && podeExcluir) || (!isExcluir && podeCancelar)) ? '#fff' : 'var(--tx-3)',
                    border:'none',
                    cursor: ((isExcluir && podeExcluir) || (!isExcluir && podeCancelar)) ? 'pointer' : 'not-allowed',
                    gap:6,
                  }}>
                  {isExcluir
                    ? <><i data-lucide="trash-2" style={{ width:14, height:14 }}></i> Excluir definitivamente</>
                    : <><i data-lucide="x-circle" style={{ width:14, height:14 }}></i> Cancelar proposta</>}
                </button>
              </div>
            </div>
          </div>
        );
      })()}

      <EmitirPedidoModal
        open={showPedidoModal}
        onClose={() => setShowPedidoModal(false)}
        prop={prop}
        cli={cli}
        itens={localItens}
        valorTotal={totalComDesconto || prop.valor}
        addTimelineEvent={addTimelineEvent}
        onSaved={function(ped) {
          setLocalPedido(ped);
          setShowPedidoModal(false);
          persistStatus('pedido');
          setTab('pedido');
        }}
      />
      {/* Corrigir Pedido — cancela o pedido atual e volta proposta para Em Negociação */}
      <CorrigirPedidoModal
        open={showCorrigirModal}
        pedido={pedido}
        isAfterAssinatura={!!(pedido && (pedido.assinatura || pedido.assinatura_nome || pedido.cliente_aprovado_em || pedido.status === 'pedido_assinado'))}
        onClose={function(){ setShowCorrigirModal(false); }}
        onConfirm={cancelarPedidoComCorrecao}
      />
    </Modal>
  );
}
window.PropostaModal = PropostaModal;

// ── SummaryStat (small KPI inside modal) ─────────────────────────────────────
function SummaryStat({ label, value, mono, accent, tone }) {
  const valColor = tone === "warn" ? "var(--warn)" : (accent ? "var(--grn)" : "var(--tx)");
  return (
    <div style={{
      background: "var(--surface-2)", border: "1px solid var(--border)",
      borderRadius: "var(--r-md)", padding: "12px 14px",
      borderTop: accent ? "3px solid var(--grn)" : "1px solid var(--border)",
    }}>
      <div style={{
        font: "600 10px/1 var(--ff-body)", textTransform: "uppercase",
        letterSpacing: ".07em", color: "var(--tx-3)", marginBottom: 6,
      }}>{label}</div>
      <div style={{
        font: mono ? "400 22px/1 var(--ff-mono)" : "400 18px/1.1 var(--ff-body)",
        color: valColor, fontWeight: mono ? 400 : 600,
      }}>{value}</div>
    </div>
  );
}

// ── DocViewerTab — iframe do proposta-publica.html ───────────────────────────
function DocViewerTab({ prop, cli, op, vend, itens }) {
  const { useState: useStateD, useEffect: useEffectD, useRef: useRefD } = React;
  const [url, setUrl] = useStateD('');
  const [loading, setLoading] = useStateD(true);
  const iframeRef = useRefD(null);

  useEffectD(function() {
    // Montar payload idêntico ao gerarLinkUrl do PropostaModal
    var displayItens = (itens && itens.length)
      ? itens
      : [{ sku: op && op.modelo || '—', desc: op && op.titulo || prop.id, qtd: 1, total: prop.valor || 0, desconto: 0, prazo: '', frete_tipo: '' }];

    var dados = JSON.stringify({
      id: prop.id,
      versao: prop.versao || 1,
      data: prop.data,
      validade: prop.validade,
      op: op ? {
        titulo: op.titulo || '',
        familia: op.familia || '',
        modelo: op.modelo || '',
        descricao: (op.descricao || '').slice(0, 200),
        fabricante: (displayItens[0] && displayItens[0].familia) || op.familia || '',
        descricao_tecnica: (displayItens[0] && displayItens[0].descricao_tecnica) || '',
      } : {},
      cli: cli ? { razao: cli.razao || '', cnpj: cli.cnpj || '', cidade: cli.cidade || '', uf: cli.uf || '', contato: cli.contato || '', contato_nome: (op&&op.contato_nome)||'' } : {},
      vend: vend ? { nome: vend.nome || '', cargo: vend.cargo || '', email: vend.email || '' } : {},
      itens: displayItens.map(function(it) {
        return { sku: it.sku, familia: it.familia || '', desc: it.desc || '', descricao_tecnica: it.descricao_tecnica || '', qtd: it.qtd || it.quantidade || 1, total: it.total || 0, desconto: it.desconto || 0, prazo: it.prazo || '', frete_tipo: it.frete_tipo || '', icms_saida: it.icms_saida || 0, composicao: it.composicao || [] };
      }),
    });

    var base = window.location.origin + '/crm/proposta-publica.html';

    var compressed = (typeof LZString !== 'undefined')
      ? LZString.compressToEncodedURIComponent(dados)
      : btoa(unescape(encodeURIComponent(dados)));

    setUrl(base + '?d=' + compressed);
  }, [prop && prop.id, prop && prop.versao, prop && prop.validade,
      itens ? itens.map(function(i){return (i._spId||i.sku||'')+'x'+(i.total||0);}).join('|') : '']);

  return (
    <div style={{ background: '#dce0dc', borderRadius: 'var(--r-md)', overflow: 'hidden', position: 'relative', height: 680 }}>
      {loading && (
        <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', background: '#dce0dc', zIndex: 2, flexDirection: 'column', gap: 12 }}>
          <div style={{ width: 32, height: 32, border: '3px solid #c0c8c2', borderTopColor: '#007c44', borderRadius: '50%', animation: 'spin 0.8s linear infinite' }} />
          <div style={{ fontSize: 11, color: '#6a7870', letterSpacing: '.08em', textTransform: 'uppercase', fontFamily: 'var(--ff-mono)' }}>Carregando proposta...</div>
        </div>
      )}
      {url && (
        <iframe
          ref={iframeRef}
          src={url}
          style={{ width: '100%', height: '100%', border: 'none', display: 'block' }}
          onLoad={function() { setLoading(false); }}
          title="Preview da proposta"
        />
      )}
      <style>{`@keyframes spin { to { transform: rotate(360deg) } }`}</style>
    </div>
  );
}

function Row({ label, value, big, tone }) {
  return (
    <div style={{
      display: "flex", justifyContent: "space-between", alignItems: "baseline",
      padding: big ? "10px 0 0" : "4px 0",
      borderTop: big ? "2px solid #1a2b1e" : "none",
      marginTop: big ? 8 : 0,
    }}>
      <span style={{
        font: big ? "600 12px/1 var(--ff-body)" : "400 11px/1 var(--ff-body)",
        color: tone === "warn" ? "#8a5a00" : "#3c4740",
        textTransform: big ? "uppercase" : "none", letterSpacing: big ? ".08em" : 0,
      }}>{label}</span>
      <span style={{
        font: big ? "400 22px/1 var(--ff-mono)" : "400 11px/1 var(--ff-mono)",
        color: tone === "warn" ? "#8a5a00" : "#1a2b1e", fontWeight: big ? 500 : 400,
      }}>{value}</span>
    </div>
  );
}

// ── ItemsTab ─────────────────────────────────────────────────────────────────
function ItemsTab({ itens, prop, isGerente, onUpdateDesconto, orphanedItens, onMantarOrfaos, onRemoverOrfaos, readonlyDesconto, readOnly }) {
  if (!itens.length) {
    return (
      <div style={{
        padding: 32, textAlign: "center", color: "var(--tx-3)",
        background: "var(--surface-2)", border: "1px dashed var(--border-2)", borderRadius: "var(--r-md)",
      }}>
        <i data-lucide="package-search" style={{ width: 24, height: 24, margin: "0 auto 10px", display: "block" }}></i>
        <div style={{ font: "500 13px/1 var(--ff-body)", color: "var(--tx-2)", marginBottom: 8 }}>Nenhum item nesta proposta</div>
        <div style={{ font: "400 12px/1.5 var(--ff-body)", color: "var(--tx-3)" }}>
          Adicione máquinas na aba <strong>Itens</strong> da oportunidade — elas aparecerão aqui automaticamente.
        </div>
      </div>
    );
  }

  const subtotal       = itens.reduce((s, it) => s + it.total, 0);
  const totalCliente   = itens.reduce((s, it) => s + Math.round(it.total * (1 - (it.desconto || 0) / 100)), 0);
  const descontoTotal  = subtotal - totalCliente;
  const anyDesconto    = itens.some(it => (it.desconto || 0) > 0);
  const dnetTotal      = prop.dnet || 0;
  const margem        = totalCliente > 0 ? ((totalCliente - dnetTotal) / totalCliente * 100).toFixed(1) : '—';

  const TH = ({ children, right }) => (
    <th style={{ padding: '7px 10px', font: '600 10px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.07em', color: 'var(--tx-3)', textAlign: right ? 'right' : 'left', borderBottom: '1px solid var(--border)', background: 'var(--surface-2)', whiteSpace: 'nowrap' }}>
      {children}
    </th>
  );
  const TD = ({ children, right, mono, muted, warn, bold, colSpan }) => (
    <td colSpan={colSpan} style={{ padding: '8px 10px', font: `${bold ? 600 : 400} ${mono ? '12px' : '13px'}/1.2 ${mono ? 'var(--ff-mono)' : 'var(--ff-body)'}`, textAlign: right ? 'right' : 'left', color: warn ? 'var(--warn)' : muted ? 'var(--tx-3)' : 'var(--tx)', whiteSpace: 'nowrap' }}>
      {children}
    </td>
  );

  const hasOrphans = orphanedItens && orphanedItens.length > 0;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      {/* Banner de itens órfãos */}
      {hasOrphans && (
        <div style={{ display: 'flex', alignItems: 'flex-start', gap: 12, padding: '12px 16px',
          background: 'var(--warn-050, #fffbeb)', border: '1px solid var(--warn, #f59e0b)',
          borderRadius: 'var(--r-md)', font: '400 13px/1.4 var(--ff-body)' }}>
          <span style={{ fontSize: 16, flexShrink: 0 }}>⚠️</span>
          <div style={{ flex: 1 }}>
            <div style={{ font: '600 13px/1 var(--ff-body)', color: 'var(--tx)', marginBottom: 4 }}>
              {orphanedItens.length === 1
                ? `"${orphanedItens[0].sku || orphanedItens[0].modelo || 'Item'}" não está mais na oportunidade`
                : `${orphanedItens.length} itens desta proposta não estão mais na oportunidade`}
            </div>
            <div style={{ font: '400 12px/1.4 var(--ff-body)', color: 'var(--tx-3)' }}>
              Foram removidos da oportunidade após esta proposta ser criada.
            </div>
          </div>
          {!readOnly && (
            <div style={{ display: 'flex', gap: 8, flexShrink: 0 }}>
              <button className="btn btn-secondary" style={{ fontSize: 12, padding: '5px 10px' }}
                onClick={onMantarOrfaos}>Manter</button>
              <button className="btn btn-ghost" style={{ fontSize: 12, padding: '5px 10px', color: 'var(--danger)' }}
                onClick={onRemoverOrfaos}>Remover da proposta</button>
            </div>
          )}
        </div>
      )}
      {itens.map((item, idx) => (
        <div key={idx} style={{ border: '1px solid var(--border)', borderRadius: 'var(--r-md)', overflow: 'hidden' }}>
          {/* Cabeçalho do item */}
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '10px 14px', background: 'var(--surface-2)', borderBottom: '1px solid var(--border)' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <i data-lucide="box" style={{ width: 15, height: 15, color: 'var(--grn)' }}></i>
              <span style={{ font: '600 13px/1 var(--ff-body)', color: 'var(--tx)' }}>{item.desc}</span>
              <span style={{ font: '400 11px/1 var(--ff-mono)', color: 'var(--tx-3)', background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 4, padding: '2px 6px' }}>{item.sku}</span>
            </div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              {onUpdateDesconto && item._localId && !readonlyDesconto ? (
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
                    <label style={{ font: '600 10px/1 var(--ff-body)', color: 'var(--tx-3)', textTransform: 'uppercase', letterSpacing: '.06em', whiteSpace: 'nowrap' }}>Desc %</label>
                    <input
                      type="number" min={-100} max={item.desconto_max != null ? item.desconto_max : 50} step={0.5}
                      value={item.desconto || 0}
                      style={{ width: 74, padding: '3px 6px', border: '1px solid var(--border-2)', borderRadius: 'var(--r-sm)', background: 'var(--surface)', fontFamily: 'var(--ff-mono)', fontSize: 12, color: 'var(--tx)', textAlign: 'right', outline: 'none' }}
                      onChange={e => {
                        const cap = item.desconto_max != null ? item.desconto_max : 50;
                        const pct = +(parseFloat(e.target.value).toFixed(4)) || 0;
                        onUpdateDesconto(item._localId, pct > 0 ? Math.min(cap, pct) : Math.max(-100, pct));
                      }}
                    />
                  </div>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
                    <label style={{ font: '600 10px/1 var(--ff-body)', color: 'var(--tx-3)', textTransform: 'uppercase', letterSpacing: '.06em', whiteSpace: 'nowrap' }}>R$ final</label>
                    <input
                      key={'val-' + item._localId + '-' + (item.desconto || 0)}
                      type="number" min={0} step={100}
                      defaultValue={Math.round(item.total * (1 - (item.desconto || 0) / 100))}
                      style={{ width: 96, padding: '3px 6px', border: '1px solid var(--border-2)', borderRadius: 'var(--r-sm)', background: 'var(--surface)', fontFamily: 'var(--ff-mono)', fontSize: 12, color: 'var(--tx)', textAlign: 'right', outline: 'none' }}
                      onBlur={e => {
                        const v = parseFloat(e.target.value);
                        if (isNaN(v) || v <= 0) return;
                        const cap = item.desconto_max != null ? item.desconto_max : 50;
                        const rawPct = +((1 - v / item.total) * 100).toFixed(4);
                        const novaPct = rawPct > 0 ? Math.min(cap, rawPct) : Math.max(-100, rawPct);
                        onUpdateDesconto(item._localId, novaPct);
                      }}
                    />
                  </div>
                  {item.desconto_max != null && (
                    <span style={{ font: '400 10px/1 var(--ff-mono)', color: 'var(--grn)', whiteSpace: 'nowrap' }}>máx {item.desconto_max}%</span>
                  )}
                </div>
              ) : (item.desconto || 0) > 0 || item.desconto_max != null ? (
                <div style={{ display: 'flex', alignItems: 'center', gap: 5, flexWrap: 'wrap' }}>
                  {(item.desconto || 0) > 0 && (
                    <span style={{ font: '400 11px/1 var(--ff-mono)', color: 'var(--warn)', background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 4, padding: '2px 7px' }}>
                      Solic. {item.desconto}%
                    </span>
                  )}
                  {item.desconto_max != null && (
                    <span style={{ font: '600 11px/1 var(--ff-mono)', color: 'var(--grn)', background: 'var(--surface)', border: '1px solid var(--grn)', borderRadius: 4, padding: '2px 7px' }}>
                      Aprov. máx {item.desconto_max}%
                    </span>
                  )}
                </div>
              ) : null}

            </div>
          </div>

          {/* Tabela de composição */}
          <table style={{ width: '100%', borderCollapse: 'collapse' }}>
            <thead>
              <tr>
                <TH>Componente</TH>
                <TH right>Qtd</TH>
                <TH right>Unitário</TH>
                <TH right>Total</TH>
              </tr>
            </thead>
            <tbody>
              {(item.composicao || []).map((c, ci) => (
                <tr key={ci} style={{ borderBottom: '1px solid var(--border)' }}>
                  <TD>{c.desc}</TD>
                  <TD right mono muted>{c.informativo ? '' : (c.qtd || 1) + '×'}</TD>
                  <TD right mono>{c.informativo ? '' : (c.unit > 0 ? fR(c.unit) : '—')}</TD>
                  <TD right mono>{c.informativo ? <span style={{ font: '400 11px/1 var(--ff-body)', color: 'var(--tx-3)', fontStyle: 'italic' }}>incluso</span> : (c.total > 0 ? fR(c.total) : '—')}</TD>
                </tr>
              ))}
              {/* Subtotal do item */}
              <tr style={{ background: 'var(--surface-2)' }}>
                <TD bold colSpan={3}>
                  Subtotal {item.sku} × {item.qtd}
                  {(item.desconto || 0) > 0 && <span style={{ fontWeight: 400, fontSize: 11, color: 'var(--tx-3)', marginLeft: 8 }}>base {fR(item.total)}</span>}
                </TD>
                <TD right mono bold>
                  {(item.desconto || 0) > 0
                    ? <span style={{ color: 'var(--grn)' }}>{fR(Math.round(item.total * (1 - item.desconto / 100)))}</span>
                    : fR(item.total)}
                </TD>
              </tr>
            </tbody>
          </table>
        </div>
      ))}

      {/* Totais finais */}
      <div style={{ border: '1px solid var(--border)', borderRadius: 'var(--r-md)', overflow: 'hidden' }}>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <tbody>
            {anyDesconto && (
              <tr style={{ borderBottom: '1px solid var(--border)' }}>
                <TD muted>Subtotal bruto</TD>
                <TD right mono>{fR(subtotal)}</TD>
              </tr>
            )}
            {anyDesconto && (
              <tr style={{ borderBottom: '1px solid var(--border)' }}>
                <TD warn>Descontos aplicados</TD>
                <TD right mono warn>− {fR(descontoTotal)}</TD>
              </tr>
            )}
            <tr style={{ background: 'var(--grn-050)', borderBottom: isGerente ? '1px solid var(--border)' : 'none' }}>
              <td style={{ padding: '10px 14px', font: '600 12px/1 var(--ff-body)', textTransform: 'uppercase', letterSpacing: '.06em', color: 'var(--grn)' }}>Total ao cliente</td>
              <td style={{ padding: '10px 14px', font: '400 22px/1 var(--ff-mono)', color: 'var(--grn)', textAlign: 'right' }}>{fR(totalCliente)}</td>
            </tr>
            {isGerente && dnetTotal > 0 && (
              <>
                <tr style={{ borderBottom: '1px solid var(--border)', background: 'var(--surface-2)' }}>
                  <td style={{ padding: '8px 14px', font: '400 11px/1 var(--ff-body)', color: 'var(--tx-3)', display: 'flex', alignItems: 'center', gap: 6 }}>
                    <i data-lucide="lock" style={{ width: 10, height: 10 }}></i> DNet total (custo fábrica)
                  </td>
                  <td style={{ padding: '8px 14px', font: '400 13px/1 var(--ff-mono)', color: 'var(--tx-3)', textAlign: 'right' }}>{fR(dnetTotal)}</td>
                </tr>
                <tr style={{ background: 'var(--surface-2)' }}>
                  <td style={{ padding: '8px 14px', font: '600 11px/1 var(--ff-body)', color: 'var(--tx-3)', display: 'flex', alignItems: 'center', gap: 6 }}>
                    <i data-lucide="lock" style={{ width: 10, height: 10 }}></i> Margem bruta
                  </td>
                  <td style={{ padding: '8px 14px', font: '600 15px/1 var(--ff-mono)', color: parseFloat(margem) < 10 ? 'var(--danger)' : 'var(--ok)', textAlign: 'right' }}>{margem}%</td>
                </tr>
              </>
            )}
          </tbody>
        </table>
      </div>

    </div>
  );
}


// ════════════════════════════════════════════════════════════════════════════
// WHATSAPP MODAL
// ════════════════════════════════════════════════════════════════════════════
function WhatsAppModal({ open, onClose, prop, onSent }) {
  const op = prop ? CRM_DATA.getOp(prop.op_id) : null;
  const cli = op ? CRM_DATA.getCliente(op.cliente_id) : null;
  const vend = prop ? CRM_DATA.getUsuario(prop.responsavel_id) : null;

  const defaultMsg = prop ? buildWppMessage(prop, op, cli, vend) : "";
  const [msg, setMsg] = usePropState(defaultMsg);
  const [phone, setPhone] = usePropState(cli?.fone || "");
  const [includeAttachment, setIncludeAttachment] = usePropState(true);
  const [sent, setSent] = usePropState(false);

  React.useEffect(() => {
    if (open && prop) {
      setMsg(buildWppMessage(prop, op, cli, vend));
      setPhone(cli?.fone || "");
      setSent(false);
    }
  }, [open, prop?.id]);

  if (!prop) return null;

  function handleSend() {
    setSent(true);
    setTimeout(() => {
      onSent && onSent();
      onClose();
      setSent(false);
    }, 1400);
  }

  return (
    <Modal open={open} onClose={onClose} title="Enviar por WhatsApp" subtitle={`${prop.id} · ${cli?.razao}`} wide>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 320px", gap: 18, marginTop: 16 }}>
        {/* Editor */}
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <div className="f">
            <label>Destinatário</label>
            <div style={{ display: "flex", gap: 8 }}>
              <input className="inp" value={phone} onChange={e => setPhone(e.target.value)} placeholder="+55 41 99999-0000" style={{ flex: 1 }} />
              <select className="inp select" style={{ width: 200 }}>
                <option>{cli?.contato}</option>
                <option>Outro contato...</option>
              </select>
            </div>
          </div>

          <div className="f">
            <label>Template <span className="hint">· clique para inserir</span></label>
            <div style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
              {[
                { label: "Padrão", key: "padrao" },
                { label: "Follow-up", key: "followup" },
                { label: "Vencimento", key: "vencimento" },
                { label: "Curto", key: "curto" },
              ].map(t => (
                <button key={t.key} className="btn btn-secondary" style={{ padding: "6px 10px", fontSize: 12 }}
                  onClick={() => setMsg(buildWppMessage(prop, op, cli, vend, t.key))}>
                  {t.label}
                </button>
              ))}
            </div>
          </div>

          <div className="f">
            <label>Mensagem <span className="hint">· editável</span></label>
            <textarea
              className="inp"
              rows={10}
              value={msg}
              onChange={e => setMsg(e.target.value)}
              style={{ resize: "vertical", lineHeight: 1.55, fontFamily: "var(--ff-body)" }}
            />
          </div>

          <label style={{
            display: "flex", alignItems: "center", gap: 10, padding: "10px 12px",
            background: "var(--surface-2)", border: "1px solid var(--border)", borderRadius: "var(--r-md)",
            cursor: "pointer",
          }}>
            <input type="checkbox" checked={includeAttachment} onChange={e => setIncludeAttachment(e.target.checked)}
              style={{ width: 16, height: 16, accentColor: "var(--grn)" }} />
            <i data-lucide="paperclip" style={{ width: 15, height: 15, color: "var(--grn)" }}></i>
            <div style={{ flex: 1 }}>
              <div style={{ font: "500 12px/1 var(--ff-body)", color: "var(--tx)" }}>Anexar PDF da proposta</div>
              <div style={{ font: "400 11px/1 var(--ff-mono)", color: "var(--tx-3)", marginTop: 3 }}>Proposta-{prop.id}-v{prop.versao}.pdf · 342 KB</div>
            </div>
          </label>
        </div>

        {/* Preview WhatsApp */}
        <div style={{
          background: "#e5ddd5", border: "1px solid var(--border)",
          borderRadius: "var(--r-md)", padding: 14, display: "flex", flexDirection: "column", gap: 8,
          minHeight: 480, position: "relative", overflow: "hidden",
        }}>
          <div style={{
            position: "absolute", inset: 0,
            backgroundImage: `repeating-linear-gradient(45deg, rgba(255,255,255,.06) 0 2px, transparent 2px 10px)`,
            pointerEvents: "none",
          }}></div>
          <div style={{
            background: "#075E54", color: "#fff", padding: "8px 12px", borderRadius: "8px 8px 4px 4px",
            display: "flex", alignItems: "center", gap: 10, position: "relative", zIndex: 1, margin: -14, marginBottom: 0,
          }}>
            <div style={{ width: 30, height: 30, borderRadius: "50%", background: "#34B7F1", display: "grid", placeItems: "center", font: "600 11px/1 var(--ff-body)" }}>
              {cli?.contato?.split(" ").map(p => p[0]).slice(0, 2).join("")}
            </div>
            <div style={{ flex: 1 }}>
              <div style={{ font: "600 13px/1 var(--ff-body)" }}>{cli?.contato}</div>
              <div style={{ font: "400 10px/1 var(--ff-mono)", opacity: .8, marginTop: 3 }}>online</div>
            </div>
          </div>

          <div style={{ flex: 1, padding: "14px 6px 0", display: "flex", flexDirection: "column", gap: 8, position: "relative", zIndex: 1 }}>
            {includeAttachment && (
              <div style={{
                alignSelf: "flex-end", maxWidth: "85%",
                background: "#dcf8c6", borderRadius: "8px 8px 0 8px", padding: 6, paddingBottom: 4,
                boxShadow: "0 1px 0.5px rgba(0,0,0,.13)",
              }}>
                <div style={{
                  background: "#cae5b5", borderRadius: 6, padding: "10px 12px",
                  display: "flex", alignItems: "center", gap: 10,
                }}>
                  <div style={{ width: 36, height: 44, background: "#dc3545", borderRadius: 4, display: "grid", placeItems: "center", color: "#fff", font: "600 9px/1 var(--ff-body)" }}>PDF</div>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ font: "500 12px/1.2 var(--ff-body)", color: "#000", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>Proposta-{prop.id}-v{prop.versao}</div>
                    <div style={{ font: "400 10px/1 var(--ff-body)", color: "rgba(0,0,0,.5)", marginTop: 3 }}>342 KB · PDF</div>
                  </div>
                </div>
              </div>
            )}
            <div style={{
              alignSelf: "flex-end", maxWidth: "85%",
              background: "#dcf8c6", borderRadius: "8px 8px 0 8px", padding: "8px 10px",
              boxShadow: "0 1px 0.5px rgba(0,0,0,.13)",
              font: "400 13px/1.45 var(--ff-body)", color: "#000",
              whiteSpace: "pre-wrap", wordWrap: "break-word",
            }}>
              {msg}
              <div style={{
                font: "400 9px/1 var(--ff-body)", color: "rgba(0,0,0,.45)",
                textAlign: "right", marginTop: 4, display: "flex", justifyContent: "flex-end", alignItems: "center", gap: 4,
              }}>
                {new Date().toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" })}
                <i data-lucide="check-check" style={{ width: 12, height: 12, color: "#34B7F1" }}></i>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div style={{
        marginTop: 18, paddingTop: 16, borderTop: "1px solid var(--border)",
        display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10,
      }}>
        <div style={{ font: "400 11px/1.4 var(--ff-mono)", color: "var(--tx-3)", display: "flex", alignItems: "center", gap: 6 }}>
          <i data-lucide="info" style={{ width: 13, height: 13 }}></i>
          O envio fica registrado na linha do tempo da oportunidade.
        </div>
        <div style={{ display: "flex", gap: 8 }}>
          <button className="btn btn-secondary" onClick={onClose} disabled={sent}>Cancelar</button>
          <button className="btn btn-primary" onClick={handleSend} disabled={sent} style={{ minWidth: 160, justifyContent: "center" }}>
            {sent ? (<><i data-lucide="check"></i> Enviado!</>) : (<><i data-lucide="send"></i> Enviar agora</>)}
          </button>
        </div>
      </div>
    </Modal>
  );
}
window.WhatsAppModal = WhatsAppModal;

function buildWppMessage(prop, op, cli, vend, kind = "padrao") {
  const nome = cli?.contato?.split(" ")[0] || "Cliente";
  const valStr = fR(prop.valor);
  const validStr = fDate(prop.validade);
  switch (kind) {
    case "followup":
      return `Oi ${nome}, tudo bem?\n\nPassando pra saber se conseguiu avaliar a proposta ${prop.id} que enviei sobre ${op?.titulo}.\n\nFico à disposição pra ajustar prazos, condições ou tirar dúvidas técnicas.\n\nAbraço,\n${vend?.nome}`;
    case "vencimento":
      return `Oi ${nome},\n\nLembrando que a proposta ${prop.id} (${op?.titulo}) vence em ${validStr}. Posso prorrogar a validade ou ajustar as condições, é só me avisar.\n\nAbraço,\n${vend?.nome}`;
    case "curto":
      return `${nome}, segue a proposta ${prop.id} para ${op?.titulo} no valor de ${valStr}.\nValidade ${validStr}. Qualquer coisa me chama.`;
    default:
      return `Olá ${nome}, tudo bem?\n\nSegue em anexo a proposta *${prop.id}* (versão ${prop.versao}) para ${op?.titulo}.\n\n*Resumo:*\n• Valor: ${valStr}\n• Validade: ${validStr}\n• Condições: à vista ou financiamento BKB\n• Garantia: 12 meses ou 2.000h\n• Entrega: 45 dias\n\nFico à disposição pra esclarecer qualquer ponto técnico ou comercial.\n\nAbraço,\n*${vend?.nome}*\n${vend?.cargo} · Bauko`;
  }
}

// ═══════════════════════════════════════════════════════

// ─────────────────────────────────────────────────────────────────────────────
// ConfetiAnimado — confetti CSS puro, sem dependência externa
// ─────────────────────────────────────────────────────────────────────────────
function ConfetiAnimado() {
  var pieces = React.useMemo(function() {
    var colors = ['#ffd700','#ffffff','#a8ffcc','#ff8787','#74c0fc','#ffa94d','#b197fc','#63e6be'];
    var arr = [];
    for (var i = 0; i < 80; i++) {
      arr.push({
        id: i,
        left: Math.random() * 100,
        color: colors[Math.floor(Math.random() * colors.length)],
        size: 6 + Math.random() * 9,
        delay: Math.random() * 4,
        duration: 3.5 + Math.random() * 3,
        rotate: Math.random() * 360,
        circle: Math.random() > 0.6,
      });
    }
    return arr;
  }, []);
  return (
    <div style={{ position:'absolute', inset:0, overflow:'hidden', pointerEvents:'none', zIndex:1 }}>
      <style>{`
        @keyframes cffall {
          0%   { transform: translateY(-30px) rotate(0deg); opacity:1; }
          80%  { opacity:1; }
          100% { transform: translateY(110vh) rotate(900deg); opacity:0; }
        }
      `}</style>
      {pieces.map(function(p) {
        return (
          <div key={p.id} style={{
            position:'absolute', left: p.left+'%', top:'-30px',
            width: p.size+'px', height: p.circle ? p.size+'px' : Math.round(p.size*0.38)+'px',
            borderRadius: p.circle ? '50%' : '2px',
            background: p.color,
            animation: 'cffall '+p.duration+'s '+p.delay+'s linear infinite',
          }} />
        );
      })}
    </div>
  );
}
window.ConfetiAnimado = ConfetiAnimado;

// ─────────────────────────────────────────────────────────────────────────────
// PedidoDocTab — Preview formal do pedido + envio ao cliente
// ═══════════════════════════════════════════════════════
function PedidoDocTab({ pedido, prop, cli, op, vend, gerarLinkPedido, addTimelineEvent, persistStatusComEvento, effectiveStatus, wppPhoneInit, emailInit, isGerente, onCorrigirPedido }) {
  var _useState = React.useState;
  var _useEffect = React.useEffect;
  var _showWpp = _useState(false), showWpp = _showWpp[0], setShowWpp = _showWpp[1];
  var _wppPedidoMsg = _useState(''), wppPedidoMsg = _wppPedidoMsg[0], setWppPedidoMsg = _wppPedidoMsg[1];
  var _showEmail = _useState(false), showEmail = _showEmail[0], setShowEmail = _showEmail[1];
  var _wppPhone = _useState(wppPhoneInit||''), wppPhone = _wppPhone[0], setWppPhone = _wppPhone[1];
  var _wppLink = _useState(''), wppLink = _wppLink[0], setWppLink = _wppLink[1];
  var _wppLinkLoading = _useState(false), wppLinkLoading = _wppLinkLoading[0], setWppLinkLoading = _wppLinkLoading[1];
  var _emailDest = _useState(emailInit||''), emailDest = _emailDest[0], setEmailDest = _emailDest[1];
  var _emailCorpoPed = _useState(''), emailCorpoPed = _emailCorpoPed[0], setEmailCorpoPed = _emailCorpoPed[1];
  var _linkCopiado = _useState(false), linkCopiado = _linkCopiado[0], setLinkCopiado = _linkCopiado[1];
  var _assinaturaLocal = _useState(pedido.assinatura || null), assinaturaLocal = _assinaturaLocal[0], setAssinaturaLocal = _assinaturaLocal[1];
  var _showManualSign = _useState(false), showManualSign = _showManualSign[0], setShowManualSign = _showManualSign[1];
  var _manualSignName = _useState(''), manualSignName = _manualSignName[0], setManualSignName = _manualSignName[1];
  var _linkCurtoPed = _useState(''), linkCurtoPed = _linkCurtoPed[0], setLinkCurtoPed = _linkCurtoPed[1];
  var _pedWppModeloSel = _useState(0), pedWppModeloSel = _pedWppModeloSel[0], setPedWppModeloSel = _pedWppModeloSel[1];
  var _pedEmailModeloSel = _useState(0), pedEmailModeloSel = _pedEmailModeloSel[0], setPedEmailModeloSel = _pedEmailModeloSel[1];

  _useEffect(function() { try { if (typeof lucide !== 'undefined') lucide.createIcons(); } catch(e) {} });

  // Auto-encurtar link (Netlify Blobs) quando abre o modal WPP.
  // Sempre define wppLink (curto no sucesso, longo no fallback) p/ liberar o envio.
  _useEffect(function() {
    if (!showWpp) return;
    var longUrl = gerarLinkPedido();
    if (!window.CRM_API || !window.CRM_API.encurtarLink) { setWppLink(longUrl); return; }
    window.CRM_API.encurtarLink(longUrl).then(function(short) {
      setWppLink(short || longUrl);
      if (short && short !== longUrl) {
        setWppPedidoMsg(function(prev) { return prev ? prev.replace(longUrl, short) : prev; });
      }
    }).catch(function() { setWppLink(longUrl); });
  }, [showWpp]);

  // Pre-encurta o link no mount p/ o botao "Copiar link" ja entregar o link curto.
  _useEffect(function() {
    if (!window.CRM_API || !window.CRM_API.encurtarLink) return;
    var u = gerarLinkPedido();
    if (!u) return;
    window.CRM_API.encurtarLink(u).then(function(s) { if (s) setLinkCurtoPed(s); }).catch(function() {});
  }, []);

  var fRp = function(v) { return 'R$ ' + (v||0).toLocaleString('pt-BR', {minimumFractionDigits:0,maximumFractionDigits:0}); };
  var fDp = function(s) { if (!s) return '—'; try { return new Date(s).toLocaleDateString('pt-BR',{timeZone:'UTC'}); } catch(e){ return s; } };
  var valorNum = pedido._valorNum || parseFloat(pedido.valor) || 0;
  var INK='#1a2b1e', INK2='#3c4740', INK3='#706f6f', GRN='#007c44', HAIR='#e3e6e4';
  var MN='var(--ff-mono)', DP='var(--ff-display)', BD='var(--ff-body)';
  var PS = { background:'#fff', width:'100%', maxWidth:700, margin:'0 auto 20px', padding:'40px 48px 56px', boxShadow:'0 12px 36px rgba(0,0,0,.10)', color:INK, fontFamily:BD, position:'relative' };
  var assinatura = assinaturaLocal;
  var itensDoc = (pedido.itens && pedido.itens.length) ? pedido.itens : [];
  var numFormatado = pedido.id ? pedido.id.replace('PED-','').padStart(8,'0') : '—';
  // Endereço da filial: lê de CRM_CONFIG (lista SP "ConfigCRM_Filiais").
  // Fallback hardcoded só roda se CRM_CONFIG não carregou.
  var endBauko = (function() {
    if (window.CRM_CONFIG && CRM_CONFIG.getFilialEnderecoLinha) {
      var linha = CRM_CONFIG.getFilialEnderecoLinha(pedido.unidade_bauko);
      if (linha) return linha;
    }
    var UNIDADE_END_LEGADO = {
      'Bauko Osasco - SP':    'Rua Santa Erotildes, 200 – Vila dos Remédios · CEP 06298-060 · Osasco/SP\nCNPJ 62.092.754/0001-76 · I.E. 492.362.483.111',
      'Bauko Rio Claro - SP': 'Rodovia Washington Luiz (SP-310), Km 172 – Conpark · CEP 13501-600 · Rio Claro/SP\nCNPJ 62.092.754/0004-19 · I.E. 578.435.034.110',
      'Bauko Serra - ES':     'Av. Piracema, 1020 – Jacuhy · CEP 29161-250 · Serra/ES\nCNPJ 62.092.754/0006-80 · I.E. 082.529.83-0',
      'Bauko Tanguá - RJ':    'Rodovia BR-101, s/n, Km 280 – Duques · CEP 24890-000 · Tanguá/RJ\nCNPJ 62.092.754/0003-38 · I.E. 81.332.610'
    };
    return UNIDADE_END_LEGADO[pedido.unidade_bauko] || pedido.unidade_bauko || 'Bauko Máquinas';
  })();

  function copiarLink() {
    var url = linkCurtoPed || gerarLinkPedido();
    try { navigator.clipboard.writeText(url).then(function(){ setLinkCopiado(true); setTimeout(function(){ setLinkCopiado(false); }, 2500); }); }
    catch(e) { setLinkCopiado(true); setTimeout(function(){ setLinkCopiado(false); }, 2500); }
    addTimelineEvent('pedido_enviado_cliente', 'Link do pedido copiado');
  }

  // Permissão: vendedor dono OU gerente. Botão "Corrigir pedido" só aparece se for um dos dois.
  var emailLogado = '';
  emailLogado = (window.CRM_USER && window.CRM_USER.email) || '';
  var isDono = vend && (vend.email || '').toLowerCase() === emailLogado;
  var podeCancelar = !!(isDono || isGerente);
  var statusPedido = pedido.status || '';
  var pedidoCancelado = statusPedido === 'cancelado_correcao' || statusPedido === 'cancelado_apos_assinatura';

  return (
    <div>
      {/* Banner status assinatura / cancelamento */}
      {pedidoCancelado ? (
        <div style={{ display:'flex', alignItems:'flex-start', gap:10, padding:'12px 16px', marginBottom:16, background:'#fef2f2', border:'1px solid var(--danger)', borderRadius:'var(--r-md)' }}>
          <i data-lucide={statusPedido === 'cancelado_apos_assinatura' ? 'alert-octagon' : 'rotate-ccw'} style={{ width:18, height:18, color:'var(--danger)', flexShrink:0, marginTop:1 }}></i>
          <div style={{ flex:1 }}>
            <div style={{ font:'600 13px/1.3 var(--ff-body)', color:'var(--danger)' }}>
              {statusPedido === 'cancelado_apos_assinatura' ? 'Pedido cancelado após assinatura' : 'Pedido cancelado para correção'}
            </div>
            <div style={{ font:'400 11.5px/1.5 var(--ff-body)', color:'var(--tx-2)', marginTop:4 }}>
              {pedido.motivo_cancelamento ? <><strong>Motivo:</strong> {pedido.motivo_cancelamento}</> : 'Cancelado pelo vendedor.'}
              {pedido.cancelado_em && <> · {new Date(pedido.cancelado_em).toLocaleString('pt-BR')}</>}
            </div>
            <div style={{ font:'400 11px/1.4 var(--ff-body)', color:'var(--tx-3)', marginTop:4 }}>
              A proposta foi retornada para "Em Negociação". Emita um novo pedido quando estiver tudo certo.
            </div>
          </div>
        </div>
      ) : assinatura ? (
        <div style={{ display:'flex', alignItems:'center', gap:10, padding:'10px 16px', marginBottom:16, background:'var(--ok-050)', border:'1px solid var(--ok)', borderRadius:'var(--r-md)' }}>
          <i data-lucide="check-circle-2" style={{ width:16, height:16, color:'var(--ok)', flexShrink:0 }}></i>
          <div>
            <div style={{ font:'600 13px/1 var(--ff-body)', color:'var(--ok)' }}>Pedido assinado pelo cliente</div>
            <div style={{ font:'400 11px/1.4 var(--ff-body)', color:'var(--tx-3)', marginTop:3 }}>
              {assinatura.nome} · {assinatura.data ? new Date(assinatura.data).toLocaleString('pt-BR') : ''}
            </div>
          </div>
        </div>
      ) : (
        <div style={{ display:'flex', alignItems:'center', gap:10, padding:'10px 16px', marginBottom:16, background:'var(--warn-050)', border:'1px solid var(--warn)', borderRadius:'var(--r-md)' }}>
          <i data-lucide="clock" style={{ width:16, height:16, color:'var(--warn)', flexShrink:0 }}></i>
          <div style={{ font:'400 12px/1.4 var(--ff-body)', color:'#7a4a00' }}>Aguardando assinatura do cliente. Envie o link do pedido pelos canais abaixo.</div>
        </div>
      )}

      {/* Enviar ao cliente — escondido se pedido cancelado */}
      {!pedidoCancelado && (
      <div style={{ padding:'14px 16px', marginBottom:18, background:'var(--surface-2)', border:'1px solid var(--border)', borderRadius:'var(--r-md)', borderLeft:'3px solid var(--grn)' }}>
        <div style={{ font:'600 10px/1 var(--ff-body)', textTransform:'uppercase', letterSpacing:'.07em', color:'var(--grn)', marginBottom:12 }}>Enviar pedido ao cliente</div>
        <div style={{ display:'grid', gridTemplateColumns:'repeat(4,1fr)', gap:8 }}>
          <button className="btn btn-secondary" style={{ flexDirection:'column', padding:'14px 8px', height:'auto', gap:6, fontSize:12, display:'flex', alignItems:'center', justifyContent:'center', lineHeight:1.3 }}
            onClick={function(){
            // Link encurtado pelo useEffect [showWpp] ao abrir o modal.
            setWppPedidoMsg('');
            setWppLink('');
            setShowWpp(true);
          }}>
            <i data-lucide="message-circle" style={{ width:22, height:22, color:'#25d366' }}></i>
            <strong>WhatsApp</strong>
            <span style={{ font:'400 10px/1.2 var(--ff-body)', color:'var(--tx-3)', textAlign:'center' }}>Link + mensagem</span>
          </button>
          <button className="btn btn-secondary" style={{ flexDirection:'column', padding:'14px 8px', height:'auto', gap:6, fontSize:12, display:'flex', alignItems:'center', justifyContent:'center', lineHeight:1.3 }}
            onClick={function() {
              var clienteContato = (cli&&cli.contato)||'Cliente';
              var modeloStr = (op&&op.modelo)||'equipamento';
              var vendNome = (vend&&vend.nome)||'Consultor Bauko';
              var linkPedido = gerarLinkPedido();
              var corpoInicial = 'Prezado(a) '+clienteContato+',\n\nSegue o pedido de compra Bauko para '+modeloStr+'.\n\nPara confirmar, acesse o link abaixo e assine digitalmente:\n'+linkPedido+'\n\nAtenciosamente,\n'+vendNome+'\nBauko Soluções em Equipamentos';
              setEmailDest((cli&&cli.email)||'');
              setEmailCorpoPed(corpoInicial);
              setShowEmail(true);
            }}>
            <i data-lucide="mail" style={{ width:22, height:22, color:'var(--info)' }}></i>
            <strong>E-mail</strong>
            <span style={{ font:'400 10px/1.2 var(--ff-body)', color:'var(--tx-3)', textAlign:'center' }}>Enviar pelo serviço de e-mail</span>
          </button>
          <button className="btn btn-secondary" style={{ flexDirection:'column', padding:'14px 8px', height:'auto', gap:6, fontSize:12, display:'flex', alignItems:'center', justifyContent:'center', lineHeight:1.3, background:linkCopiado?'var(--ok-050)':'' }}
            onClick={copiarLink}>
            <i data-lucide={linkCopiado?"check":"link"} style={{ width:22, height:22, color:linkCopiado?'var(--ok)':'var(--tx-2)' }}></i>
            <strong>{linkCopiado?'Copiado!':'Copiar link'}</strong>
            <span style={{ font:'400 10px/1.2 var(--ff-body)', color:'var(--tx-3)', textAlign:'center' }}>Pedido público</span>
          </button>
          <button className="btn btn-secondary" style={{ flexDirection:'column', padding:'14px 8px', height:'auto', gap:6, fontSize:12, display:'flex', alignItems:'center', justifyContent:'center', lineHeight:1.3 }}
            onClick={function(){
              addTimelineEvent('pedido_enviado_cliente','Pedido impresso para assinatura manual');
              window.open(gerarLinkPedido()+'&print=1','_blank');
            }}>
            <i data-lucide="printer" style={{ width:22, height:22, color:'var(--tx-2)' }}></i>
            <strong>Imprimir</strong>
            <span style={{ font:'400 10px/1.2 var(--ff-body)', color:'var(--tx-3)', textAlign:'center' }}>Ass. manual</span>
          </button>
        </div>
        {!assinatura && (
          <div style={{ marginTop:10 }}>
            <button className="btn btn-secondary" style={{ width:'100%', gap:8, color:'var(--ok)', borderColor:'var(--ok)', display:'flex', alignItems:'center', justifyContent:'center' }}
              onClick={function(){ setShowManualSign(true); }}>
              <i data-lucide="pen-line" style={{ width:15, height:15 }}></i>
              Confirmar assinatura manual
            </button>
          </div>
        )}
      </div>
      )}

      {/* Corrigir pedido — vendedor dono ou gerente, pedido ainda não cancelado */}
      {!pedidoCancelado && podeCancelar && (
        <div style={{ marginBottom:18, display:'flex', justifyContent:'flex-end' }}>
          <button className="btn btn-ghost" onClick={onCorrigirPedido}
            style={{ color:'var(--warn)', borderColor:'var(--warn)', border:'1px solid var(--warn)', gap:6, fontSize:12 }}
            title="Cancela o pedido atual e volta a proposta para Em Negociação">
            <i data-lucide="rotate-ccw" style={{ width:13, height:13 }}></i>
            Corrigir pedido
          </button>
        </div>
      )}

      {/* ── Documento formal ── */}
      <div style={{ background:'#dce0dc', padding:'20px 12px 32px', borderRadius:'var(--r-md)', overflowY:'auto', maxHeight:660 }}>
        <div style={PS}>
          {/* Cabeçalho */}
          <div style={{ display:'flex', justifyContent:'space-between', alignItems:'flex-start', paddingBottom:12, borderBottom:'2px solid '+INK, marginBottom:22 }}>
            <div>
              <div style={{ font:'400 9px/1.5 '+MN, letterSpacing:'.03em', textTransform:'uppercase', color:INK3, marginBottom:4 }}>Bauko Soluções em Equipamentos Ltda</div>
              <div style={{ font:'400 28px/1 '+DP, letterSpacing:'.04em', color:GRN, textTransform:'uppercase' }}>Confirmação de Pedido</div>
            </div>
            <div style={{ textAlign:'right' }}>
              <div style={{ font:'600 9px/1 '+BD, letterSpacing:'.1em', textTransform:'uppercase', color:INK3, marginBottom:4 }}>Pedido N°</div>
              <div style={{ font:'400 30px/1 '+DP, letterSpacing:'.02em', color:INK }}>{numFormatado}</div>
              <div style={{ font:'400 10px/1.5 '+MN, color:INK3, marginTop:4 }}>
                {fDp(pedido.data)}<br/>
                <span style={{ fontWeight:600, color:INK2 }}>Vendedor: </span>{(vend&&vend.nome)||'—'}
              </div>
            </div>
          </div>

          {/* Destinatário */}
          <div style={{ marginBottom:18 }}>
            <div style={{ font:'600 9px/1 '+BD, letterSpacing:'.08em', textTransform:'uppercase', color:INK3, marginBottom:6 }}>À</div>
            <div style={{ font:'600 13px/1.4 '+BD, color:INK }}>{pedido.unidade_bauko||'Bauko Máquinas'}</div>
            <div style={{ font:'400 11px/1.7 '+MN, color:INK2, whiteSpace:'pre-line' }}>{endBauko}</div>
          </div>

          {/* Abertura */}
          <div style={{ font:'400 12px/1.65 '+BD, color:INK2, marginBottom:22, paddingBottom:16, borderBottom:'1px solid '+HAIR }}>
            Confirmo a aquisição nesta data do(s) equipamento(s) conforme abaixo descrito, nas condições comerciais acordadas com o consultor de vendas Bauko.
          </div>

          {/* Seção 1: Produtos */}
          <div style={{ marginBottom:22 }}>
            <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:14 }}>
              <span style={{ font:'400 24px/1 '+DP, color:GRN, lineHeight:1 }}>1</span>
              <span style={{ font:'600 11px/1 '+BD, letterSpacing:'.06em', textTransform:'uppercase', color:INK }}>Produto(s)</span>
            </div>
            {itensDoc.length > 0 ? itensDoc.map(function(it,i){
              var totalFinal = Math.round(it.total*(1-(it.desconto||0)/100));
              var unitario = (it.qtd||1) > 0 ? Math.round(totalFinal/(it.qtd||1)) : totalFinal;
              return (
                <div key={i} style={{ border:'1px solid '+HAIR, borderRadius:4, padding:'14px 16px', marginBottom:10 }}>
                  <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr', gap:'6px 20px', marginBottom:10 }}>
                    {[
                      ['Equipamento', it.sku||(op&&op.modelo)||'—'],
                      ['Fabricante', it.familia||(op&&op.familia)||'—'],
                      ['Quantidade', String(it.qtd||1)],
                    ].map(function(r,j){ return (
                      <div key={j}>
                        <div style={{ font:'600 9px/1 '+BD, letterSpacing:'.1em', textTransform:'uppercase', color:INK3, marginBottom:3 }}>{r[0]}</div>
                        <div style={{ font:'500 12px/1.3 '+BD, color:INK }}>{r[1]}</div>
                      </div>
                    ); })}
                  </div>
                  {(it.desc||(op&&op.descricao)) && (
                    <div style={{ font:'400 11px/1.65 '+BD, color:INK2, marginBottom:10, paddingTop:8, borderTop:'1px solid '+HAIR }}>
                      <span style={{ fontWeight:600, color:INK }}>Especificação: </span>
                      {it.desc||(op&&op.descricao?(op.descricao.slice(0,220)+(op.descricao.length>220?'…':'')):'')}                    </div>
                  )}
                  {(it.prazo||it.garantia||it.local_entrega) && (
                    <div style={{ display:'flex', gap:20, flexWrap:'wrap', marginBottom:10, paddingTop:8, borderTop:'1px solid '+HAIR }}>
                      {it.prazo && <div><div style={{ font:'600 9px/1 '+BD, letterSpacing:'.1em', textTransform:'uppercase', color:INK3, marginBottom:3 }}>Prazo de Entrega</div><div style={{ font:'500 11px/1.3 '+BD, color:INK }}>{it.prazo}</div></div>}
                      {it.garantia && <div><div style={{ font:'600 9px/1 '+BD, letterSpacing:'.1em', textTransform:'uppercase', color:INK3, marginBottom:3 }}>Garantia</div><div style={{ font:'500 11px/1.3 '+BD, color:INK }}>{it.garantia}</div></div>}
                      {it.local_entrega && <div><div style={{ font:'600 9px/1 '+BD, letterSpacing:'.1em', textTransform:'uppercase', color:INK3, marginBottom:3 }}>Frete / Entrega</div><div style={{ font:'500 11px/1.3 '+BD, color:INK }}>{it.local_entrega}</div></div>}
                    </div>
                  )}
                  <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:'6px 20px', paddingTop:8, borderTop:'1px solid '+HAIR }}>
                    <div>
                      <div style={{ font:'600 9px/1 '+BD, letterSpacing:'.1em', textTransform:'uppercase', color:INK3, marginBottom:3 }}>Preço Unitário</div>
                      <div style={{ font:'600 13px/1 '+MN, color:INK }}>{fRp(unitario)}</div>
                    </div>
                    <div>
                      <div style={{ font:'600 9px/1 '+BD, letterSpacing:'.1em', textTransform:'uppercase', color:INK3, marginBottom:3 }}>Preço Total</div>
                      <div style={{ font:'600 13px/1 '+MN, color:INK }}>{fRp(totalFinal)}</div>
                    </div>
                  </div>
                </div>
              );
            }) : (
              <div style={{ font:'400 11px/1.4 '+BD, color:INK3, padding:'12px 0' }}>Nenhum item registrado.</div>
            )}
          </div>

          {/* {/* Seção 2: Condições */}
          <div style={{ marginBottom:22 }}>
            <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:12 }}>
              <span style={{ font:'400 24px/1 '+DP, color:GRN }}>2</span>
              <span style={{ font:'600 11px/1 '+BD, letterSpacing:'.06em', textTransform:'uppercase', color:INK }}>Condições Comerciais</span>
            </div>
            <table style={{ width:'100%', borderCollapse:'collapse' }}>
              <tbody>
                {[
                  ['Condição de Pagamento', pedido.pgto_condicao||'—'],
                  ['Valor Total do Pedido', fRp(valorNum)],
                  ['Prazo de Entrega', (itensDoc[0]&&itensDoc[0].prazo)||(prop&&prop.prazo_entrega)||'A confirmar'],
                  ['Local de Entrega', 'A definir com o cliente'],
                  ['Validade', (prop&&prop.validade)?fDp(prop.validade):(((window.CRM_CONFIG && CRM_CONFIG.get('proposta_validade_default_dias')) || 10) + ' dias')],
                ].map(function(row,i){ return (
                  <tr key={i} style={{ borderBottom:'1px solid '+HAIR }}>
                    <td style={{ padding:'8px 0', font:'600 11px/1.4 '+BD, color:INK, width:'40%' }}>{row[0]}</td>
                    <td style={{ padding:'8px 0', paddingLeft:12, font:'400 11.5px/1.4 '+MN, color:INK2 }}>{row[1]}</td>
                  </tr>
                ); })}
              </tbody>
            </table>
          </div>

          {/* Seção 3: Observações */}
          {pedido.notas && (
            <div style={{ marginBottom:22 }}>
              <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:10 }}>
                <span style={{ font:'400 24px/1 '+DP, color:GRN }}>3</span>
                <span style={{ font:'600 11px/1 '+BD, letterSpacing:'.06em', textTransform:'uppercase', color:INK }}>Observações</span>
              </div>
              <div style={{ font:'400 11.5px/1.65 '+BD, color:INK2, background:'#f8faf9', padding:'10px 14px', borderLeft:'3px solid '+GRN, borderRadius:2 }}>{pedido.notas}</div>
            </div>
          )}

          {/* Encerramento */}
          <div style={{ font:'400 11.5px/1.65 '+BD, color:INK2, marginBottom:24, paddingTop:16, borderTop:'1px solid '+HAIR }}>
            Nada mais havendo, confirmo o presente e subscrevo-me,
          </div>

          {/* Assinaturas */}
          <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:28, marginBottom:28 }}>
            {[
              { lbl: cli?(cli.razao||'Cliente'):'Cliente', sub:(op&&op.contato_nome)||(cli&&cli.contato)||'', isCliente:true },
              { lbl: pedido.unidade_bauko||'Bauko Máquinas', sub:(vend&&vend.nome)||'', isCliente:false },
            ].map(function(s,i){ return (
              <div key={i}>
                <div style={{ font:'600 9px/1 '+BD, letterSpacing:'.1em', textTransform:'uppercase', color:INK3, marginBottom:20 }}>{s.lbl}</div>
                {s.isCliente && assinatura ? (
                  <div>
                    <div style={{ fontFamily:'var(--ff-assinatura,"Dancing Script",cursive)', fontSize:22, color:INK, marginBottom:6, lineHeight:1.3 }}>{assinatura.texto}</div>
                    <div style={{ borderTop:'1px solid '+GRN, paddingTop:5 }}>
                      <div style={{ font:'500 11px/1 '+BD, color:INK }}>{assinatura.nome}</div>
                      <div style={{ font:'400 9px/1 '+MN, color:GRN, marginTop:2 }}>✓ Assinado em {assinatura.data?new Date(assinatura.data).toLocaleString('pt-BR'):'—'}</div>
                    </div>
                  </div>
                ) : (
                  <div style={{ borderTop:'1px solid '+(i===0?HAIR:INK), paddingTop:6 }}>
                    <div style={{ font:'500 11px/1 '+BD, color:INK }}>{s.sub||'—'}</div>
                    {s.isCliente && <div style={{ font:'400 9px/1.4 '+MN, color:INK3, marginTop:3 }}>Aguardando assinatura</div>}
                  </div>
                )}
              </div>
            ); })}
          </div>

          {/* Dados do Comprador */}
          {cli && (
            <div style={{ borderTop:'2px solid '+INK, paddingTop:16 }}>
              <div style={{ font:'600 9px/1 '+BD, letterSpacing:'.1em', textTransform:'uppercase', color:'#fff', background:INK, padding:'5px 10px', marginBottom:14, display:'inline-block' }}>DADOS DO COMPRADOR</div>
              <div style={{ display:'grid', gridTemplateColumns:'repeat(3,1fr)', gap:'10px 20px' }}>
                {[
                  ['Empresa',cli.razao],['A/C',(op&&op.contato_nome)||null],['Responsável',cli.contato],['CNPJ',cli.cnpj],['I.E.',cli.ie||null],
                  ['Endereço',cli.endereco],['Cidade/UF',cli.cidade&&cli.uf?cli.cidade+' / '+cli.uf:(cli.cidade||cli.uf||null)],
                  ['Telefone',cli.telefone],['E-mail',cli.email],['Segmento',cli.segmento],
                ].filter(function(r){ return r[1]; }).map(function(r,i){ return (
                  <div key={i}>
                    <div style={{ font:'600 9px/1 '+BD, letterSpacing:'.1em', textTransform:'uppercase', color:INK3, marginBottom:2 }}>{r[0]}</div>
                    <div style={{ font:'400 11px/1.4 '+MN, color:INK2 }}>{r[1]}</div>
                  </div>
                ); })}
              </div>
            </div>
          )}

          {/* Rodapé */}
          <div style={{ marginTop:28, paddingTop:9, borderTop:'1px solid '+HAIR, display:'flex', justifyContent:'space-between' }}>
            <div style={{ font:'400 8.5px/1 '+MN, color:INK3, letterSpacing:'.05em', textTransform:'uppercase' }}>Bauko Soluções em Equipamentos Ltda · Confirmação de Pedido</div>
            <div style={{ font:'400 8.5px/1 '+MN, color:INK3 }}>Pedido {pedido.id} · {fDp(pedido.data)}</div>
          </div>
        </div>
      </div>

      {/* Modal WhatsApp */}
      {showWpp && (function(){
        var clienteNome = (cli&&cli.contato)?cli.contato.split(' ')[0]:'Cliente';
        var clienteNomeCompleto = (cli&&cli.contato)?cli.contato:'Cliente';
        var modeloStr = (op&&op.modelo)||'equipamento';
        var vendNomePed = (vend&&vend.nome)?vend.nome:'Consultor Bauko';
        var valorPedStr = fRp(valorNum);
        var equipListPed = itensDoc.length > 0
          ? itensDoc.map(function(it){ var nm=it.sku||it.modelo||it.familia||'equipamento'; return nm+((it.qtd||1)>1?' ×'+(it.qtd||1):''); }).join(', ')
          : modeloStr;
        var formatTelPed = function(d){ var s=(d||'').replace(/\D/g,''); if(s.length===11) return '('+s.slice(0,2)+') '+s.slice(2,7)+'-'+s.slice(7); if(s.length===10) return '('+s.slice(0,2)+') '+s.slice(2,6)+'-'+s.slice(6); return s; };
        var phoneDigitsPed = wppPhone.replace(/\D/g,'');
        var phoneValidoPed = phoneDigitsPed.length >= 10 && phoneDigitsPed.length <= 11;
        var pedWppTones = ['Formal', 'Amigável', 'Direto'];
        var pedWppMsgs = [
          'Prezado(a) ' + clienteNomeCompleto + ',\n\nEncaminhamos o pedido de compra Bauko referente ao(s) equipamento(s): ' + equipListPed + '.\n\nPedido: ' + pedido.id + ' • Valor: ' + valorPedStr + '\n\nPara confirmar a compra, acesse o link e assine digitalmente:\n' + (wppLink||gerarLinkPedido()) + '\n\nColoco-me à disposição para qualquer esclarecimento.\n\n' + vendNomePed + ' | Bauko Soluções em Equipamentos',
          'Olá ' + clienteNome + '! Segue o pedido Bauko para: ' + equipListPed + '.\n\n' + pedido.id + ' • ' + valorPedStr + '\n\nConfirme assinando pelo link:\n' + (wppLink||gerarLinkPedido()) + '\n\nQualquer dúvida, é só chamar!',
          pedido.id + ' | ' + equipListPed + ' | ' + valorPedStr + '\n' + (wppLink||gerarLinkPedido()) + ' – ' + vendNomePed + '/Bauko',
        ];
        var defaultMsg = pedWppMsgs[0];
        if (!wppPedidoMsg) { setWppPedidoMsg(pedWppMsgs[pedWppModeloSel] || defaultMsg); }
        var msgAtual = wppPedidoMsg || defaultMsg;
        return (
          <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.55)', zIndex:9999, display:'flex', alignItems:'center', justifyContent:'center', padding:16 }}
            onClick={function(e){ if(e.target===e.currentTarget){setShowWpp(false);setWppLink('');} }}>
            <div style={{ background:'var(--surface)', borderRadius:'var(--r-lg)', padding:'24px 28px', width:'100%', maxWidth:520, maxHeight:'90vh', overflowY:'auto', boxShadow:'var(--shadow-3)' }}>
              <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:18 }}>
                <div style={{ font:'600 14px/1 var(--ff-body)', display:'flex', alignItems:'center', gap:8 }}>
                  <i data-lucide="message-circle" style={{ width:18, height:18, color:'#25d366' }}></i> Enviar Pedido via WhatsApp
                </div>
                <button className="btn btn-ghost" style={{ padding:'4px 8px' }} onClick={function(){setShowWpp(false);setWppLink('');}}>
                  <i data-lucide="x" style={{ width:16, height:16 }}></i>
                </button>
              </div>
              <div style={{ marginBottom:14 }}>
                <label style={{ font:'600 10px/1 var(--ff-body)', textTransform:'uppercase', letterSpacing:'.07em', color:'var(--tx-3)', display:'block', marginBottom:5 }}>Telefone do cliente (com DDD)</label>
                <input type="tel" value={formatTelPed(wppPhone)} onChange={function(e){setWppPhone(e.target.value.replace(/\D/g,''));}}
                  placeholder="(11) 99999-9999"
                  style={{ width:'100%', padding:'8px 10px', border:'1px solid '+(wppPhone&&!phoneValidoPed?'var(--danger)':'var(--border-2)'), borderRadius:'var(--r-sm)', background:'var(--surface)', fontFamily:'var(--ff-mono)', fontSize:13, color:'var(--tx)', outline:'none', boxSizing:'border-box' }} />
              </div>
              <div style={{ marginBottom:14 }}>
                <label style={{ font:'600 10px/1 var(--ff-body)', textTransform:'uppercase', letterSpacing:'.07em', color:'var(--tx-3)', display:'block', marginBottom:6 }}>Link do pedido</label>
                <div style={{ display:'flex', gap:6, alignItems:'center' }}>
                  <input readOnly value={wppLink || 'gerando link curto…'} style={{ flex:1, padding:'7px 10px', border:'1px solid var(--grn)', borderRadius:'var(--r-sm)', background:'var(--surface)', fontFamily:'var(--ff-mono)', fontSize:11, color:'var(--tx)', outline:'none', boxSizing:'border-box' }} />
                  <button className="btn btn-secondary" style={{ fontSize:11, padding:'7px 10px' }} onClick={function(){try{navigator.clipboard.writeText(wppLink || gerarLinkPedido());}catch(e){}}}><i data-lucide="copy" style={{ width:12, height:12 }}></i> Copiar</button>
                </div>
              </div>
              <div style={{ marginBottom:14 }}>
                <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:6 }}>
                  <label style={{ font:'600 10px/1 var(--ff-body)', textTransform:'uppercase', letterSpacing:'.07em', color:'var(--tx-3)' }}>Mensagem</label>
                  <button className="btn btn-ghost" style={{ fontSize:11, padding:'3px 8px', border:'1px solid var(--border-2)' }}
                    onClick={function(){ setWppPedidoMsg(defaultMsg); }}>Restaurar padrão</button>
                </div>
                <textarea rows={7} value={msgAtual} onChange={function(e){ setWppPedidoMsg(e.target.value); }}
                  style={{ width:'100%', padding:'8px 10px', border:'1px solid var(--border-2)', borderRadius:'var(--r-sm)', background:'var(--surface)', fontFamily:'var(--ff-body)', fontSize:13, color:'var(--tx)', outline:'none', boxSizing:'border-box', resize:'vertical', lineHeight:1.6 }} />
              </div>
              <div style={{ display:'flex', gap:8, justifyContent:'flex-end', borderTop:'1px solid var(--border)', paddingTop:14 }}>
                <button className="btn btn-secondary" onClick={function(){setShowWpp(false);setWppLink('');}}>Cancelar</button>
                <button disabled={!wppPhone || !wppLink} style={{ background:'#25d366', color:'#fff', border:'none', borderRadius:'var(--r-sm)', padding:'8px 16px', fontSize:13, fontWeight:600, cursor:(wppPhone && wppLink)?'pointer':'not-allowed', opacity:(wppPhone && wppLink)?1:0.5, display:'flex', alignItems:'center', gap:6 }}
                  onClick={function(){
                    var phone = wppPhone.replace(/\D/g,'');
                    if (!msgAtual.trim()) { window.CRM_TOAST('Escreva uma mensagem antes de continuar.', 'warn'); return; }
                    window.open('https://wa.me/'+(phone?'55'+phone:'')+'?text='+encodeURIComponent(msgAtual),'_blank');
                    addTimelineEvent('pedido_enviado_cliente','Pedido enviado via WhatsApp'+(phone?' para +55'+phone:''));
                    setShowWpp(false); setWppLink('');
                  }}>
                  <i data-lucide="send" style={{ width:14, height:14 }}></i> Abrir WhatsApp
                </button>
              </div>
            </div>
          </div>
        );
      })()}

      {/* Modal E-mail */}
      {showEmail && (function(){
        var clienteContato = (cli&&cli.contato)||'Cliente';
        var modeloStr = (op&&op.modelo)||'equipamento';
        var vendNomePedEmail = (vend&&vend.nome)||'Consultor Bauko';
        var linkPedido = gerarLinkPedido();
        var valorPedEmailStr = fRp(valorNum);
        var equipListPedEmail = itensDoc.length > 0
          ? itensDoc.map(function(it){ return it.sku||it.modelo||it.familia||'equipamento'; }).join(', ')
          : modeloStr;
        var assunto = 'Pedido '+pedido.id+' — '+equipListPedEmail+' · Bauko';
        var pedEmailMsgs = [
          'Prezado(a) '+clienteContato+',\n\nEncaminhamos o pedido de compra Bauko referente ao(s) equipamento(s):\n'+equipListPedEmail+'\n\nPedido: '+pedido.id+' • Valor: '+valorPedEmailStr+'\n\nPara confirmar a compra, acesse o link abaixo e assine digitalmente:\n\n[Confirmar Pedido]\n\nColocamo-nos à disposição para qualquer esclarecimento.\n\nAtenciosamente,\n'+vendNomePedEmail+'\nBauko Soluções em Equipamentos',
          'Olá '+clienteContato+',\n\nSegue o pedido Bauko para: '+equipListPedEmail+'.\n\n'+pedido.id+' • '+valorPedEmailStr+'\n\nConfirme a compra assinando pelo link:\n\n[Confirmar Pedido]\n\nQualquer dúvida, é só falar!\n\nAbraços,\n'+vendNomePedEmail+' – Bauko',
          'Caro(a) '+clienteContato+',\n\n'+pedido.id+' | '+equipListPedEmail+' | '+valorPedEmailStr+'\n\nConfirme pelo link:\n\n[Confirmar Pedido]\n\n'+vendNomePedEmail+' – Bauko',
        ];
        if (!emailCorpoPed) { setEmailCorpoPed(pedEmailMsgs[0]); }
        var corpo = emailCorpoPed || pedEmailMsgs[0];
        // Helper: perguntar se salva o e-mail digitado no cadastro do cliente
        function verificarSalvarEmailPed(emailUsado) {
          if (!emailUsado || !cli || !cli._spId) return;
          if (emailUsado === (cli.email || '')) return;
          if (!window.CRM_CONFIRM) return;
          window.CRM_CONFIRM(
            'Adicionar "' + emailUsado + '" ao cadastro de ' + (cli.razao || 'este cliente') + '?',
            { confirmLabel: 'Salvar no cadastro' }
          ).then(function(ok) {
            if (!ok) return;
            cli.email = emailUsado;
            if (window.CRM_DATA && CRM_DATA.clientes) {
              var idx = CRM_DATA.clientes.findIndex(function(c){ return c.id === cli.id; });
              if (idx >= 0) CRM_DATA.clientes[idx] = Object.assign({}, CRM_DATA.clientes[idx], { email: emailUsado });
            }
            if (window.CRM_API) CRM_API.updateItem('Clientes', cli._spId, { email: emailUsado })
              .catch(function(e){ console.warn('[CRM] salvar email cliente (pedido):', e.message); });
          });
        }
        return (
          <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.55)', zIndex:9999, display:'flex', alignItems:'center', justifyContent:'center', padding:16 }}
            onClick={function(e){ if(e.target===e.currentTarget) setShowEmail(false); }}>
            <div style={{ background:'var(--surface)', borderRadius:'var(--r-lg)', padding:'24px 28px', width:'100%', maxWidth:520, boxShadow:'var(--shadow-3)' }}>
              <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:18 }}>
                <div style={{ font:'600 14px/1 var(--ff-body)', display:'flex', alignItems:'center', gap:8 }}>
                  <i data-lucide="mail" style={{ width:18, height:18, color:'var(--info)' }}></i> Enviar Pedido por E-mail
                </div>
                <button className="btn btn-ghost" style={{ padding:'4px 8px' }} onClick={function(){ setShowEmail(false); }}>
                  <i data-lucide="x" style={{ width:16, height:16 }}></i>
                </button>
              </div>
              <div style={{ marginBottom:14 }}>
                <label style={{ font:'600 10px/1 var(--ff-body)', textTransform:'uppercase', letterSpacing:'.07em', color:'var(--tx-3)', display:'block', marginBottom:5 }}>E-mail do cliente</label>
                <input type="email" value={emailDest} onChange={function(e){setEmailDest(e.target.value);}}
                  placeholder="cliente@empresa.com.br"
                  style={{ width:'100%', padding:'8px 10px', border:'1px solid var(--border-2)', borderRadius:'var(--r-sm)', background:'var(--surface)', fontSize:13, color:'var(--tx)', outline:'none', boxSizing:'border-box' }} />
              </div>
              <div style={{ marginBottom:14 }}>
                <label style={{ font:'600 10px/1 var(--ff-body)', textTransform:'uppercase', letterSpacing:'.07em', color:'var(--tx-3)', display:'block', marginBottom:5 }}>Assunto</label>
                <input readOnly value={assunto} style={{ width:'100%', padding:'8px 10px', border:'1px solid var(--border-2)', borderRadius:'var(--r-sm)', background:'var(--surface-2)', fontSize:12, color:'var(--tx-3)', fontFamily:'var(--ff-mono)', boxSizing:'border-box' }} />
              </div>
              <div style={{ marginBottom:16 }}>
                <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:5 }}>
                  <label style={{ font:'600 10px/1 var(--ff-body)', textTransform:'uppercase', letterSpacing:'.07em', color:'var(--tx-3)' }}>Mensagem</label>
                  <button className="btn btn-ghost" style={{ fontSize:11, padding:'3px 8px', border:'1px solid var(--border-2)' }}
                    onClick={function(){
                      var clienteContato = (cli&&cli.contato)||'Cliente';
                      var modeloStr = (op&&op.modelo)||'equipamento';
                      var vendNome = (vend&&vend.nome)||'Consultor Bauko';
                      var linkPedido = gerarLinkPedido();
                      setEmailCorpoPed('Prezado(a) '+clienteContato+',\n\nSegue o pedido de compra Bauko para '+modeloStr+'.\n\nPara confirmar, acesse o link abaixo e assine digitalmente:\n'+linkPedido+'\n\nAtenciosamente,\n'+vendNome+'\nBauko Soluções em Equipamentos');
                    }}>Restaurar padrão</button>
                </div>
                <textarea rows={7} value={emailCorpoPed} onChange={function(e){ setEmailCorpoPed(e.target.value); }}
                  style={{ width:'100%', padding:'8px 10px', border:'1px solid var(--border-2)', borderRadius:'var(--r-sm)', background:'var(--surface)', fontFamily:'var(--ff-body)', fontSize:12, color:'var(--tx)', outline:'none', boxSizing:'border-box', resize:'vertical', lineHeight:1.7 }} />
              </div>
              <div style={{ display:'flex', gap:8, justifyContent:'flex-end', borderTop:'1px solid var(--border)', paddingTop:14 }}>
                <button className="btn btn-secondary" onClick={function(){ setShowEmail(false); }}>Cancelar</button>
                <button className="btn btn-primary" disabled={!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailDest.trim())} style={{ opacity: !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailDest.trim()) ? 0.42 : 1, cursor: !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailDest.trim()) ? 'not-allowed' : 'pointer' }}
                  onClick={function(){
                    var longUrl = gerarLinkPedido();
                    var emailUsado = emailDest.trim();
                    var abrirMailto = function(finalUrl) {
                      var corpoFinal = (emailCorpoPed || corpo).replace(longUrl, finalUrl).replace(/\[Confirmar Pedido\]/g, finalUrl);
                      var mailtoUrl = 'mailto:'+emailUsado+'?subject='+encodeURIComponent(assunto)+'&body='+encodeURIComponent(corpoFinal);
                      window.open(mailtoUrl,'_blank');
                      addTimelineEvent('pedido_enviado_cliente','Pedido enviado por e-mail para '+emailUsado);
                      setShowEmail(false);
                      verificarSalvarEmailPed(emailUsado);
                    };
                    if (window.CRM_API && window.CRM_API.encurtarLink) {
                      window.CRM_API.encurtarLink(longUrl).then(abrirMailto);
                    } else { abrirMailto(longUrl); }
                  }}>
                  <i data-lucide="send" style={{ width:14, height:14 }}></i> Abrir e-mail
                </button>
              </div>
            </div>
          </div>
        );
      })()}

      {/* Modal Assinatura Manual */}
      {showManualSign && (
        <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.55)', zIndex:10001, display:'flex', alignItems:'center', justifyContent:'center', padding:16 }}
          onClick={function(e){ if(e.target===e.currentTarget) setShowManualSign(false); }}>
          <div style={{ background:'var(--surface)', borderRadius:'var(--r-lg)', padding:'24px 28px', width:'100%', maxWidth:420, boxShadow:'var(--shadow-3)' }}>
            <div style={{ font:'600 15px/1 var(--ff-body)', marginBottom:16, display:'flex', alignItems:'center', gap:8 }}>
              <i data-lucide="pen-line" style={{ width:18, height:18, color:'var(--ok)' }}></i> Confirmar assinatura manual
            </div>
            <div style={{ marginBottom:14 }}>
              <label style={{ font:'600 10px/1 var(--ff-body)', textTransform:'uppercase', letterSpacing:'.07em', color:'var(--tx-3)', display:'block', marginBottom:5 }}>Nome do signatário</label>
              <input type="text" value={manualSignName} onChange={function(e){ setManualSignName(e.target.value); }}
                placeholder="Nome completo do cliente"
                style={{ width:'100%', padding:'8px 10px', border:'1px solid var(--border-2)', borderRadius:'var(--r-sm)', background:'var(--surface)', fontSize:13, color:'var(--tx)', outline:'none', boxSizing:'border-box' }} />
            </div>
            <div style={{ display:'flex', gap:8, justifyContent:'flex-end', borderTop:'1px solid var(--border)', paddingTop:14 }}>
              <button className="btn btn-ghost" onClick={function(){ setShowManualSign(false); setManualSignName(''); }}>Cancelar</button>
              <button className="btn btn-primary" disabled={!manualSignName.trim()}
                onClick={function(){
                  var sig = { nome: manualSignName.trim(), texto: 'Assinatura manual', fonte: '', ts: new Date().toISOString(), data: new Date().toISOString() };
                  pedido.assinatura = sig;
                  setAssinaturaLocal(sig);
                  if (window.CRM_DATA && CRM_DATA.pedidos) {
                    var p = CRM_DATA.pedidos.find(function(x){ return x.id === pedido.id; });
                    if (p) p.assinatura = sig;
                  }
                  if (pedido._spId && window.CRM_API) {
                    // Grava assinatura manual nas mesmas colunas SP usadas pelo webhook n8n
                    // (assinatura_nome/texto/fonte + cliente_aprovado_em).
                    // dados_json nao existe no FIELD_MAP de CRMPedidos.
                    CRM_API.updateItem('CRMPedidos', pedido._spId, {
                      assinatura_nome:     sig.nome,
                      assinatura_texto:    sig.texto || 'Assinatura manual',
                      assinatura_fonte:    sig.fonte || '',
                      cliente_aprovado_em: sig.ts
                    }).catch(function(){});
                  }
                  if (persistStatusComEvento) {
                    persistStatusComEvento('pedido_assinado', 'pedido_assinado_cliente', 'Assinatura manual confirmada — ' + manualSignName.trim());
                  } else {
                    addTimelineEvent('pedido_assinado_cliente', 'Assinatura manual confirmada — ' + manualSignName.trim());
                  }
                  setShowManualSign(false);
                  setManualSignName('');
                }}>
                <i data-lucide="check" style={{ width:14, height:14 }}></i> Confirmar assinatura
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
window.PedidoDocTab = PedidoDocTab;
