ACCEPTANCE CRITERIA (26/26)
☑ AC1.1: Criar nova rota `GET /api/crm/cnpj/:cnpj` no backend Express. A rota é protegida pelo middleware `X-CRM-Token` (mesmo padrão de todas as rotas CRM existentes).
☑ AC1.2: O handler extrai o CNPJ do parâmetro de rota, remove qualquer caractere não numérico, e valida que tem exatamente 14 dígitos — retorna 400 com `{ error: 'CNPJ inválido' }` se não for válido.
☑ AC1.3: O backend faz chamada server-side para `https://publica.cnpj.ws/cnpj/{cnpj}` (evita CORS no navegador). Usa `fetch()` nativo do Node.js 18+ (sem dependência adicional).
☑ AC1.4: O backend implementa cache simples em memória (objeto `Map<string, { data: CnpjResponse; cachedAt: number }>`): se o mesmo CNPJ foi consultado há menos de 60 minutos, retorna o dado do cache sem nova chamada à API externa.
☑ AC1.5: Mapeamento da resposta da `publica.cnpj.ws` para o formato `CnpjResponse` (definido em TypeScript):
☑ AC1.6: Se a API da Receita Federal retornar 404 (CNPJ não encontrado): backend retorna 404 com `{ error: 'CNPJ não encontrado na Receita Federal' }`.
☑ AC1.7: Se a API da Receita Federal retornar 429 (rate limit): backend retorna 429 com `{ error: 'Limite de consultas atingido. Tente novamente em 1 minuto.' }`.
☑ AC1.8: Se a API da Receita Federal retornar qualquer outro erro (5xx, timeout): backend retorna 502 com `{ error: 'Serviço da Receita Federal indisponível. Tente novamente.' }`.
☑ AC1.9: Timeout da chamada à API externa: 10 segundos. Se exceder, retorna 504 com `{ error: 'Timeout na consulta à Receita Federal.' }`.
☑ AC2.1: Adicionar interface `CnpjData` em `api.ts` espelhando o `CnpjResponse` do backend (mesmos campos, mesmos tipos).
☑ AC2.2: Implementar helper `fetchCnpjData(cnpj: string): Promise<CnpjData>` que:
☑ AC3.1: O botão "Consultar CNPJ" aparece na Ficha 360 **somente quando** o campo `cnpj` do cliente está preenchido com pelo menos 14 dígitos numéricos (ignorar pontuação para verificação). Para clientes sem CNPJ ou com CNPJ inválido, o botão não é exibido.
☑ AC3.2: O botão fica posicionado próximo ao campo CNPJ na seção de dados do cliente (dentro da aba ativa da Ficha 360 onde o CNPJ é exibido), com label "Consultar CNPJ" e ícone de busca (lupa) ou refresh.
☑ AC3.3: Ao clicar no botão:
☑ AC3.4: O botão retorna ao estado normal (clicável) após o resultado — seja erro ou sucesso.
☑ AC4.1: Modal/drawer exibe os dados da Receita Federal formatados em seções:
☑ AC4.2: Se a situação cadastral NÃO for "Ativa": exibir alerta amarelo no topo do modal com texto "Atenção: CNPJ com situação '{situacao}'. Verifique antes de prosseguir."
☑ AC4.3: Botão "Preencher Dados na Ficha" no rodapé do modal. Ao clicar, o modal fecha e os seguintes campos da ficha são preenchidos automaticamente com os dados da Receita Federal (sem salvar ainda — apenas atualiza o estado de edição local):
☑ AC4.4: Após o preenchimento automático (AC4.3), a Ficha 360 entra em modo de edição ativa (campos visíveis para revisão). O atendente precisa clicar em "Salvar" para persistir — o preenchimento automático NÃO salva automaticamente.
☑ AC4.5: Botão "Fechar" no modal fecha sem preencher nada na ficha.
☑ AC4.6: O modal tem título "Dados da Receita Federal — CNPJ {cnpj_formatado}".
☑ AC5.1: Se CNPJ não encontrado (404): exibir mensagem inline próxima ao botão: "CNPJ não encontrado na Receita Federal." (sem abrir modal).
☑ AC5.2: Se rate limit atingido (429): exibir mensagem inline: "Limite de consultas atingido. Tente novamente em 1 minuto." (sem abrir modal).
☑ AC5.3: Se serviço indisponível (502/504): exibir mensagem inline: "Serviço da Receita Federal indisponível. Tente novamente em alguns instantes." (sem abrir modal).
☑ AC5.4: Mensagem de erro exibida por no mínimo 5 segundos e depois some automaticamente (ou o atendente fecha clicando em X).
☑ AC5.5: Durante o loading (AC3.3), não exibir mensagem de erro anterior.