diff --git a/src/main/webapp/cliente/condominio-detalhe.js b/src/main/webapp/cliente/condominio-detalhe.js
index aa43bf4..f35510f 100644
--- a/src/main/webapp/cliente/condominio-detalhe.js
+++ b/src/main/webapp/cliente/condominio-detalhe.js
@@ -1,4 +1,13 @@
-const id=new URLSearchParams(location.search).get('id');const sections=['contatos','espacos','assembleias','documentos','avisos'];document.querySelectorAll('.nav-tabs button').forEach(b=>b.onclick=()=>{document.querySelectorAll('.nav-tabs button').forEach(x=>x.classList.remove('active'));b.classList.add('active');sections.forEach(s=>document.querySelector('#'+s).classList.toggle('hidden',s!==b.dataset.tab))});let contatos=[],docs=[],avisos=[],funcionariosVinculados=[],extras=[],assembleiasCalendario=[],calMonth=new Date();function recLabel(v){return {1:'Mensal',3:'Trimestral',12:'Anual'}[Number(v)]||'Sem recorrencia'}
+const id=new URLSearchParams(location.search).get('id');const sections=['contatos','espacos','assembleias','documentos','avisos'];document.querySelectorAll('.nav-tabs button').forEach(b=>b.onclick=()=>{document.querySelectorAll('.nav-tabs button').forEach(x=>x.classList.remove('active'));b.classList.add('active');sections.forEach(s=>document.querySelector('#'+s).classList.toggle('hidden',s!==b.dataset.tab))});let contatos=[],docs=[],avisos=[],funcionariosVinculados=[],extras=[],assembleiasCalendario=[],calMonth=new Date(),espacos=[],assembleias=[];function recLabel(v){return {1:'Mensal',3:'Trimestral',12:'Anual'}[Number(v)]||'Sem recorrencia'}
+function esc(v){return String(v??'').replace(/[&<>'"]/g,c=>({'&':'&','<':'<','>':'>',"'":''','"':'"'}[c]))}
+function lupaBtn(fn,label){return ``}
+function headerCadastro(titulo,tipo,novoFn,extra=''){const q=esc(termoDetalhe(tipo)),open=document.querySelector(`#${tipo}-search`)&&!document.querySelector(`#${tipo}-search`)?.classList.contains('hidden');return `
${titulo}
${extra}${lupaBtn(`alternarBuscaDetalhe('${tipo}')`,'Buscar '+titulo)}
`}
+function termoDetalhe(tipo){return document.querySelector(`#${tipo}-search-input`)?.value.trim().toLowerCase()||''}
+function contemDetalhe(q,...vals){return !q||vals.some(v=>String(v??'').toLowerCase().includes(q))}
+window.alternarBuscaDetalhe=tipo=>{const strip=document.querySelector(`#${tipo}-search`),input=document.querySelector(`#${tipo}-search-input`);if(!strip||!input)return;strip.classList.toggle('hidden');if(!strip.classList.contains('hidden'))input.focus()};
+function ensureDetailModal(){let m=document.querySelector('#detail-form-modal');if(m)return m;document.body.insertAdjacentHTML('beforeend','');return document.querySelector('#detail-form-modal')}
+function abrirDetailModal(titulo,html){const m=ensureDetailModal();document.querySelector('#detail-form-title').textContent=titulo;document.querySelector('#detail-form-body').innerHTML=html;m.classList.remove('hidden')}
+window.fecharDetailModal=()=>{const m=document.querySelector('#detail-form-modal');if(m)m.classList.add('hidden');const body=document.querySelector('#detail-form-body');if(body)body.innerHTML=''};
function dateKey(v){const d=new Date(v);if(Number.isNaN(d.getTime()))return'';const pad=n=>String(n).padStart(2,'0');return d.getFullYear()+'-'+pad(d.getMonth()+1)+'-'+pad(d.getDate())}
function monthLabel(d){return d.toLocaleDateString('pt-BR',{month:'long',year:'numeric'})}
@@ -18,13 +27,27 @@ window.fecharAvisoNotificacao=()=>document.querySelector('#aviso-notif-modal')?.
window.salvarAvisoNotificacao=()=>{const ids=new Set([...document.querySelectorAll('#aviso-notif-body input:checked')].map(x=>x.value));avisoDestInputs().forEach(x=>x.checked=ids.has(x.value));updateAvisoNotifSummary();fecharAvisoNotificacao()};
async function safeLoad(section,fn){try{await fn()}catch(e){document.querySelector('#'+section).innerHTML=`${e.message}
`;Util.toast(e.message,true)}}
async function load(){try{const d=await Api.get(`/api/condominios/${id}`);document.querySelector('#header').innerHTML=`${d.condominio.nome}
${d.condominio.endereco||''}
Sindico${d.sindico_atual?.contato_nome||'-'}
Assembleias futuras${d.assembleias_futuras||0}
Avisos ativos${d.avisos_ativos||0}
`;await safeLoad('contatos',loadContatos);await safeLoad('avisos',loadFuncionariosVinculados);await safeLoad('avisos',loadExtras);await safeLoad('espacos',loadEspacos);await safeLoad('assembleias',loadAssembleias);await safeLoad('documentos',loadDocs);await safeLoad('avisos',loadAvisos)}catch(e){Util.toast(e.message,true)}}
-async function loadContatos(){const d=await Api.get(`/api/condominios/${id}/contatos`);contatos=d.contatos||[];document.querySelector('#contatos').innerHTML=`Contatos
| Nome | Tipo | Telefone | Email |
${contatos.map(c=>`| ${c.contato_nome} | ${c.tipo} | ${c.contato_telefone||''} | ${c.contato_email||''} |
`).join('')}
`;document.querySelector('#contato-form').onsubmit=async e=>{e.preventDefault();try{await Api.post(`/api/condominios/${id}/contatos/vincular`,Util.formData(e.target));Util.toast('Contato salvo');loadContatos()}catch(err){Util.toast(err.message,true)}}}
-async function loadEspacos(){const d=await Api.get(`/api/condominios/${id}/espacos-comuns`);document.querySelector('#espacos').innerHTML=`Espacos comuns
| Nome | Valor | Indice | Descricao |
${(d.espacos||[]).map(x=>`| ${x.nome} | ${Util.money(x.valor_utilizacao_centavos)} | ${x.indice_correcao||''} | ${x.descricao||''} |
`).join('')}
`;document.querySelector('#espaco-form').onsubmit=async e=>{e.preventDefault();try{await Api.post(`/api/condominios/${id}/espacos-comuns`,Util.formData(e.target));Util.toast('Espaco salvo');loadEspacos()}catch(err){Util.toast(err.message,true)}}}
-async function loadAssembleias(){const d=await Api.get(`/api/condominios/${id}/assembleias`);document.querySelector('#assembleias').innerHTML=`Assembleias
| Tipo | Data | Local | Status |
${(d.assembleias||[]).map(a=>`| ${a.tipo} | ${Util.date(a.data_hora)} | ${a.local||''} | ${Util.badge(a.status)} |
`).join('')}
`;document.querySelector('#ass-form').onsubmit=async e=>{e.preventDefault();try{await Api.post(`/api/condominios/${id}/assembleias`,Util.formData(e.target));Util.toast('Assembleia salva');loadAssembleias();load()}catch(err){Util.toast(err.message,true)}}}
+async function loadContatos(){const d=await Api.get(`/api/condominios/${id}/contatos`);contatos=d.contatos||[];renderContatos()}
+function renderContatos(){const q=termoDetalhe('contatos');const lista=contatos.filter(c=>contemDetalhe(q,c.contato_nome,c.tipo,c.contato_telefone,c.contato_email));document.querySelector('#contatos').innerHTML=headerCadastro('Contatos','contatos','abrirNovoContato()')+`| Nome | Tipo | Telefone | Email |
${lista.map(c=>`| ${esc(c.contato_nome)} | ${esc(c.tipo)} | ${esc(c.contato_telefone||'')} | ${esc(c.contato_email||'')} |
`).join('')||'| Nenhum contato encontrado. |
'}
`;document.querySelector('#contatos-search-input')?.addEventListener('input',renderContatos)}
+window.abrirNovoContato=()=>{abrirDetailModal('Novo contato','');document.querySelector('#contato-form').onsubmit=async e=>{e.preventDefault();try{await Api.post(`/api/condominios/${id}/contatos/vincular`,Util.formData(e.target));Util.toast('Contato salvo');fecharDetailModal();loadContatos();load()}catch(err){Util.toast(err.message,true)}}};
+
+async function loadEspacos(){const d=await Api.get(`/api/condominios/${id}/espacos-comuns`);espacos=d.espacos||[];renderEspacos()}
+function renderEspacos(){const q=termoDetalhe('espacos');const lista=espacos.filter(x=>contemDetalhe(q,x.nome,x.valor_utilizacao_centavos,x.indice_correcao,x.descricao));document.querySelector('#espacos').innerHTML=headerCadastro('Espacos comuns','espacos','abrirNovoEspaco()')+`| Nome | Valor | Indice | Descricao |
${lista.map(x=>`| ${esc(x.nome)} | ${Util.money(x.valor_utilizacao_centavos)} | ${esc(x.indice_correcao||'')} | ${esc(x.descricao||'')} |
`).join('')||'| Nenhum espaco encontrado. |
'}
`;document.querySelector('#espacos-search-input')?.addEventListener('input',renderEspacos)}
+window.abrirNovoEspaco=()=>{abrirDetailModal('Novo espaco comum','');document.querySelector('#espaco-form').onsubmit=async e=>{e.preventDefault();try{await Api.post(`/api/condominios/${id}/espacos-comuns`,Util.formData(e.target));Util.toast('Espaco salvo');fecharDetailModal();loadEspacos()}catch(err){Util.toast(err.message,true)}}};
+
+async function loadAssembleias(){const d=await Api.get(`/api/condominios/${id}/assembleias`);assembleias=d.assembleias||[];renderAssembleias()}
+function renderAssembleias(){const q=termoDetalhe('assembleias');const lista=assembleias.filter(a=>contemDetalhe(q,a.tipo,a.data_hora,a.local,a.status));const calendar='';document.querySelector('#assembleias').innerHTML=headerCadastro('Assembleias','assembleias','abrirNovaAssembleia()',calendar)+`| Tipo | Data | Local | Status |
${lista.map(a=>`| ${esc(a.tipo)} | ${Util.date(a.data_hora)} | ${esc(a.local||'')} | ${Util.badge(a.status)} |
`).join('')||'| Nenhuma assembleia encontrada. |
'}
`;document.querySelector('#assembleias-search-input')?.addEventListener('input',renderAssembleias)}
+window.abrirNovaAssembleia=()=>{abrirDetailModal('Nova assembleia','');document.querySelector('#ass-form').onsubmit=async e=>{e.preventDefault();try{await Api.post(`/api/condominios/${id}/assembleias`,Util.formData(e.target));Util.toast('Assembleia salva');fecharDetailModal();loadAssembleias();load()}catch(err){Util.toast(err.message,true)}}};
async function loadFuncionariosVinculados(){const d=await Api.get(`/api/condominios/${id}/funcionarios-vinculados`);funcionariosVinculados=d.funcionarios||[]}
async function loadExtras(){const d=await Api.get(`/api/extras`);extras=(d.extras||[]).filter(x=>x.status==='ativo')}
-async function loadDocs(){const d=await Api.get(`/api/condominios/${id}/documentos`);docs=d.documentos||[];document.querySelector('#documentos').innerHTML=`Documentos
| ID | Arquivo | Tipo | Download |
${docs.map(d=>`| ${d.id} | ${d.nome_arquivo} | ${d.tipo||''} | Baixar |
`).join('')}
`;document.querySelector('#doc-form').onsubmit=async e=>{e.preventDefault();const fd=new FormData(e.target);try{await Api.post(`/api/condominios/${id}/documentos`,fd);Util.toast('Documento enviado');loadDocs()}catch(err){Util.toast(err.message,true)}}}
-async function loadAvisos(){const d=await Api.get(`/api/condominios/${id}/avisos`);avisos=d.avisos||[];const destContatos=contatos.map(c=>``).join('');const destFuncionarios=funcionariosVinculados.map(f=>``).join('');const destExtras=extras.map(x=>``).join('');const dest=[destContatos,destFuncionarios,destExtras].filter(Boolean).join('');const docChecks=docs.map(d=>``).join('');document.querySelector('#avisos').innerHTML=`Avisos
| Titulo | Status | Envio | Publicado em | Recorrencia | Acoes |
${avisos.map(a=>`| ${a.titulo} | ${Util.badge(a.status_envio)} | ${Util.date(a.data_evento)} | ${Util.date(a.data_publicacao)} | ${recLabel(a.recorrencia_meses)} | |
`).join('')}
`;updateAvisoNotifSummary();document.querySelector('#aviso-form').onsubmit=async e=>{e.preventDefault();const f=e.target,b=Util.formData(f);b.enviar_whatsapp=!!f.enviar_whatsapp.checked;b.enviar_email=!!f.enviar_email.checked;b.destinatarios=[...f.querySelectorAll('input[name=dest]:checked')].map(x=>{const [tipo,did]=x.value.split(':');return{tipo_destinatario:tipo,id:Number(did)}});b.documentos=[...f.querySelectorAll('input[name=doc]:checked')].map(x=>Number(x.value));try{await Api.post(`/api/condominios/${id}/avisos`,b);Util.toast('Aviso criado');loadAvisos();load()}catch(err){Util.toast(err.message,true)}}}
+async function loadDocs(){const d=await Api.get(`/api/condominios/${id}/documentos`);docs=d.documentos||[];renderDocs()}
+function renderDocs(){const q=termoDetalhe('documentos');const lista=docs.filter(d=>contemDetalhe(q,d.id,d.nome_arquivo,d.tipo));document.querySelector('#documentos').innerHTML=headerCadastro('Documentos','documentos','abrirNovoDocumento()')+`| ID | Arquivo | Tipo | Download |
${lista.map(d=>`| ${d.id} | ${esc(d.nome_arquivo)} | ${esc(d.tipo||'')} | Baixar |
`).join('')||'| Nenhum documento encontrado. |
'}
`;document.querySelector('#documentos-search-input')?.addEventListener('input',renderDocs)}
+window.abrirNovoDocumento=()=>{abrirDetailModal('Novo documento','');document.querySelector('#doc-form').onsubmit=async e=>{e.preventDefault();const fd=new FormData(e.target);try{await Api.post(`/api/condominios/${id}/documentos`,fd);Util.toast('Documento enviado');fecharDetailModal();loadDocs();loadAvisos()}catch(err){Util.toast(err.message,true)}}};
+
+function avisoFormHtml(){const destContatos=contatos.map(c=>``).join('');const destFuncionarios=funcionariosVinculados.map(f=>``).join('');const destExtras=extras.map(x=>``).join('');const dest=[destContatos,destFuncionarios,destExtras].filter(Boolean).join('');const docChecks=docs.map(d=>``).join('');return ``}
+async function loadAvisos(){const d=await Api.get(`/api/condominios/${id}/avisos`);avisos=d.avisos||[];renderAvisos()}
+function renderAvisos(){const q=termoDetalhe('avisos');const lista=avisos.filter(a=>contemDetalhe(q,a.titulo,a.status_envio,a.data_evento,a.data_publicacao,recLabel(a.recorrencia_meses)));document.querySelector('#avisos').innerHTML=headerCadastro('Avisos','avisos','abrirNovoAviso()')+`| Titulo | Status | Envio | Publicado em | Recorrencia | Acoes |
${lista.map(a=>`| ${esc(a.titulo)} | ${Util.badge(a.status_envio)} | ${Util.date(a.data_evento)} | ${Util.date(a.data_publicacao)} | ${recLabel(a.recorrencia_meses)} | |
`).join('')||'| Nenhum aviso encontrado. |
'}
`;document.querySelector('#avisos-search-input')?.addEventListener('input',renderAvisos)}
+window.abrirNovoAviso=()=>{abrirDetailModal('Novo aviso',avisoFormHtml());updateAvisoNotifSummary();document.querySelector('#aviso-form').onsubmit=async e=>{e.preventDefault();const f=e.target,b=Util.formData(f);b.enviar_whatsapp=!!f.enviar_whatsapp.checked;b.enviar_email=!!f.enviar_email.checked;b.destinatarios=[...f.querySelectorAll('input[name=dest]:checked')].map(x=>{const [tipo,did]=x.value.split(':');return{tipo_destinatario:tipo,id:Number(did)}});b.documentos=[...f.querySelectorAll('input[name=doc]:checked')].map(x=>Number(x.value));try{await Api.post(`/api/condominios/${id}/avisos`,b);Util.toast('Aviso criado');fecharDetailModal();loadAvisos();load()}catch(err){Util.toast(err.message,true)}}};
window.reenviarAviso=async avisoId=>{try{await Api.post(`/api/condominios/${id}/avisos/${avisoId}/reenviar`,{});Util.toast('Aviso reenviado');loadAvisos()}catch(err){Util.toast(err.message,true)}};
window.excluirAviso=async avisoId=>{try{await Api.request(`/api/condominios/${id}/avisos/${avisoId}`,{method:'DELETE'});Util.toast('Aviso excluido');loadAvisos();load()}catch(err){Util.toast(err.message,true)}};
load();