');win.document.close();win.print()} W.idv92Snapshot=function(){snapshot92('Snapshot manual V10.9.92');audit92('Criou snapshot manual V10.9.92','Entrega');toast92('Snapshot criado.')} function qualidadeTab92(){const issues=scanIntegrity92();const bad=issues.filter(function(i){return i.level==='bad'}).length;const warn=issues.filter(function(i){return i.level==='warn'}).length;const rows=issues.length?issues.map(function(i){return ''+pill92(i.level==='bad'?'Crítico':'Aviso',i.level==='bad'?'bad':'warn')+''+E(i.area)+''+E(i.msg)+''+E(i.fix?'Reparo seguro':'Manual')+''}).join(''):'Nenhum problema encontrado na varredura atual.';return '

Auditoria de integridade

'+kpi92('Críticos',bad,bad?'corrigir':'OK',bad?'bad':'ok')+kpi92('Avisos',warn,warn?'revisar':'OK',warn?'warn':'ok')+kpi92('O.S. atrasadas',overdueOrders92().length,'SLA','warn')+kpi92('Estoque crítico',criticalStock92().length,'itens','warn')+'
Importante: o reparo seguro preenche campos ausentes e remove duplicidades óbvias. Ele não inventa dados de cliente, não apaga O.S. e não corrige saldo negativo por conta própria.

Histórico de varreduras

'+history92()+'

Problemas encontrados

'+rows+'
NívelÁreaMensagemAção
'} function history92(){return A(S().integrityHistoryV92).slice(0,12).map(function(h){return '
'+E(h.action||'scan')+''+E(h.date)+' • '+E(h.user)+' • '+E(h.changes||0)+' ajuste(s)
'}).join('')||'
Sem histórico de varredura.
'} W.idv92RunScan=function(){ensure92();const issues=scanIntegrity92();S().integrityHistoryV92.unshift({id:uid92('SCAN'),date:now92(),user:user92()?.name||'Sistema',action:'scan',changes:issues.length,bad:issues.filter(function(i){return i.level==='bad'}).length,warn:issues.filter(function(i){return i.level==='warn'}).length});saveRaw92();toast92('Varredura concluída: '+issues.length+' item(ns).');renderDelivery92()} W.idv92ExportScanCsv=function(){const rows=[['nivel','area','mensagem','acao'],...scanIntegrity92().map(function(i){return [i.level,i.area,i.msg,i.fix?'reparo seguro':'manual']})];csv92('varredura_integridade_idriver_v10_9_92.csv',rows);audit92('Exportou varredura V10.9.92','CSV')} function overdueOrders92(){const t=Number(T(today92()).replace(/-/g,''));return A(S().orders).filter(function(o){const d=Number(T(o.date).replace(/-/g,''));return d&&d

Rotina operacional diária

'+rotinaItems92().map(function(i){const key=today92()+'_'+i[0];return ''}).join('')+'

Resumo de hoje

'+kpi92('Hoje',A(S().orders).filter(function(o){return o.date===today92()}).length,'O.S.','info')+kpi92('Atrasadas',overdueOrders92().length,'pendentes',overdueOrders92().length?'warn':'ok')+kpi92('Críticos',criticalStock92().length,'estoque',criticalStock92().length?'warn':'ok')+kpi92('Fila notif.',A(S().notificationQueueV87).filter(function(n){return n.status==='Pendente'}).length,'pendentes','warn')+'
'+dailyList92()+'
'} W.idv92ToggleRoutine=function(key,on){ensure92();S().dailyRoutineV92[key]=!!on;audit92('Atualizou rotina diária V10.9.92',key+' = '+(on?'OK':'pendente'));saveRaw92();renderDelivery92()} function dailyList92(){const arr=overdueOrders92().slice(0,6);return '
O.S. atrasadas: '+(arr.length?arr.map(function(o){return E(o.code||o.id)+' '+E(o.plate||'')}).join(', '):'nenhuma pendente atrasada')+'
'} W.idv92CreateDailySnapshot=function(){snapshot92('Fechamento diário V10.9.92 '+today92());audit92('Snapshot diário V10.9.92',today92());toast92('Snapshot diário criado.')} W.idv92ExportDailyReport=function(){const rows=[['tipo','codigo','cliente','placa','status','data','hora','tecnico'],...A(S().orders).filter(function(o){return o.date===today92()||overdueOrders92().some(function(x){return x.id===o.id})}).map(function(o){return [o.date===today92()?'hoje':'atrasada',o.code,o.clientName,o.plate,o.status,o.date,o.time,techName92(o.techId)]})];csv92('relatorio_diario_idriver_'+today92()+'.csv',rows);audit92('Exportou relatório diário V10.9.92',today92())} function techName92(id){try{return techName(id)}catch(e){return A(S().technicians).find(function(t){return t.id===id})?.name||''}} function lgpdTab92(){return '

LGPD / dados do cliente

Ferramentas para exportar dossiê, registrar solicitação e anonimizar cliente com snapshot obrigatório.

Atenção: anonimização é destrutiva. O sistema cria snapshot antes, mas em produção real isto deve seguir política jurídica/contratual.

Solicitações registradas

'+privacyHistory92()+'
'} function privacyHistory92(){return A(S().privacyRequestsV92).slice(0,20).map(function(r){return '
🔐
'+E(r.type)+' • '+E(r.clientName)+''+E(r.date)+' • '+E(r.user)+' • '+E(r.note||'')+'
'}).join('')||'
Nenhuma solicitação registrada.
'} W.idv92FindClients=function(){const term=N(document.getElementById('idv92ClientSearch')?.value||'');const list=A(S().clients).filter(function(c){const txt=N(JSON.stringify(c)+' '+A(c.vehicles).map(function(v){return v.plate}).join(' '));return !term||txt.includes(term)}).slice(0,20);const el=document.getElementById('idv92ClientResults');if(!el)return;el.innerHTML=list.length?list.map(function(c){return '
👤
'+E(c.name||c.id)+''+E(c.doc||'')+' • '+E(c.phone||'')+' • '+A(c.vehicles).map(function(v){return E(v.plate)}).join(', ')+'
'}).join(''):'
Nenhum cliente encontrado.
'} W.idv92RegisterPrivacy=function(clientId,type,note){const c=A(S().clients).find(function(x){return x.id===clientId});if(!c)return;S().privacyRequestsV92.unshift({id:uid92('LGPD'),clientId:clientId,clientName:c.name,type:type||'Solicitação',note:note||'',date:now92(),user:user92()?.name||'Sistema'});audit92('Registrou solicitação LGPD V10.9.92',(type||'Solicitação')+' • '+c.name);saveRaw92();toast92('Solicitação registrada.');renderDelivery92()} W.idv92ExportClientDossier=function(clientId){const s=S();const c=A(s.clients).find(function(x){return x.id===clientId});if(!c)return;const plates=A(c.vehicles).map(function(v){return v.plate});const orders=A(s.orders).filter(function(o){return o.clientId===clientId||plates.includes(o.plate)||o.clientName===c.name});const data={version:VERSION92,createdAt:new Date().toISOString(),client:c,orders:orders,tasks:A(s.tasks).filter(function(t){return orders.some(function(o){return o.id===t.osId})}),notifications:A(s.notificationQueueV87).filter(function(n){return orders.some(function(o){return n.relatedId===o.id||T(n.message).includes(o.code)||T(n.message).includes(o.plate)})})};downloadJson92('dossie_cliente_'+safeName92(c.name||clientId)+'_v10_9_92.json',data);W.idv92RegisterPrivacy(clientId,'Exportação de dossiê','Arquivo JSON gerado')} W.idv92AnonymizeClient=function(clientId){const s=S();const c=A(s.clients).find(function(x){return x.id===clientId});if(!c)return;if(!allowed92()){toast92('Sem permissão.');return}const ok=prompt('Digite ANONIMIZAR para confirmar a anonimização de '+(c.name||clientId));if(ok!=='ANONIMIZAR')return;snapshot92('Antes de anonimizar cliente V10.9.92 '+(c.name||clientId));const oldName=c.name;const anon='Cliente anonimizado '+T(clientId).slice(-5);c.name=anon;c.doc='ANONIMIZADO';c.phone='ANONIMIZADO';c.email='ANONIMIZADO';c.address='ANONIMIZADO';c.obs='Dados pessoais anonimizados em '+now92();A(c.vehicles).forEach(function(v,i){v.plate='XXX'+String(i+1).padStart(3,'0');v.chassis='ANONIMIZADO';v.renavam='ANONIMIZADO'});A(s.orders).forEach(function(o){if(o.clientId===clientId||o.clientName===oldName){o.clientName=anon;o.address='ANONIMIZADO'}});S().privacyRequestsV92.unshift({id:uid92('LGPD'),clientId:clientId,clientName:oldName,type:'Anonimização',note:'Snapshot criado antes da alteração',date:now92(),user:user92()?.name||'Sistema'});audit92('Anonimizou cliente V10.9.92',oldName+' → '+anon);saveRaw92();toast92('Cliente anonimizado com snapshot.');renderDelivery92()} function dossieTab92(){return '

Dossiê de entrega

Exporta um pacote com resumo técnico, indicadores, checklist, riscos, limitações e estado completo para auditoria.

'+E(summaryText92())+'

Próximo passo recomendado

'+[['Backend seguro','Substituir login/localStorage por API com sessão, hash de senha e permissões no servidor.'],['Fotos e anexos','Salvar imagens em storage/servidor e manter apenas URLs/metadados no estado.'],['Banco multiusuário','Migrar estado JSON para tabelas: users, orders, clients, devices, movements, notifications.'],['Mensageria real','Conectar fila de notificações a worker/cron com logs de tentativa e webhook.'],['Auditoria imutável','Registrar ações críticas no backend, sem depender do navegador.']].map(function(x,i){return '
'+(i+1)+'
'+E(x[0])+''+E(x[1])+'
'}).join('')+'
'} function summaryText92(){const p=checklistProgress92();const issues=scanIntegrity92();return 'iDriver Mobile Command '+VERSION92+'\nData: '+now92()+'\nUsuário: '+(user92()?.name||'Sistema')+'\n\nResumo:\n- O.S.: '+A(S().orders).length+'\n- Clientes: '+A(S().clients).length+'\n- Técnicos: '+A(S().technicians).length+'\n- Produtos: '+A(S().products).length+'\n- Ativos: '+A(S().devices).length+'\n- Movimentações: '+A(S().movements).length+'\n- Regras de notificação: '+A(S().notificationRulesV87).length+'\n- Fila de notificações: '+A(S().notificationQueueV87).length+'\n- Checklist de entrega: '+p.done+'/'+p.total+' ('+p.pct+'%)\n- Críticos: '+issues.filter(function(i){return i.level==='bad'}).length+'\n- Avisos: '+issues.filter(function(i){return i.level==='warn'}).length+'\n- Tamanho do estado: '+bytes92(stateBytes92())+'\n- LocalStorage total: '+bytes92(storageBytes92())+'\n\nLimitação: versão HTML/localStorage pronta para operação assistida e demonstração avançada; SaaS comercial requer backend seguro.'} W.idv92ExportDossier=function(){const data={version:VERSION92,createdAt:new Date().toISOString(),user:user92()?.name||'Sistema',summary:summaryText92(),checklist:S().handoverChecklistV92,delivery:S().deliveryV92,integrity:scanIntegrity92(),state:S()};downloadJson92('dossie_entrega_idriver_v10_9_92.json',data);audit92('Exportou dossiê de entrega V10.9.92','JSON')} W.idv92ExportSummaryCsv=function(){const issues=scanIntegrity92();const p=checklistProgress92();const rows=[['item','valor'],['versao',VERSION92],['data',now92()],['checklist',p.done+'/'+p.total+' '+p.pct+'%'],['criticos',issues.filter(function(i){return i.level==='bad'}).length],['avisos',issues.filter(function(i){return i.level==='warn'}).length],['os',A(S().orders).length],['clientes',A(S().clients).length],['tecnicos',A(S().technicians).length],['produtos',A(S().products).length],['ativos',A(S().devices).length],['estado',bytes92(stateBytes92())],['localStorage',bytes92(storageBytes92())]];csv92('resumo_entrega_idriver_v10_9_92.csv',rows)} W.idv92CopySummary=function(){const txt=summaryText92();if(navigator.clipboard)navigator.clipboard.writeText(txt).then(function(){toast92('Resumo copiado.')}).catch(function(){prompt('Copie o resumo:',txt)});else prompt('Copie o resumo:',txt)} function downloadJson92(name,data){const blob=new Blob([JSON.stringify(data,null,2)],{type:'application/json'});try{download(blob,name)}catch(e){const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download=name;a.click();setTimeout(function(){URL.revokeObjectURL(a.href)},1000)}} function safeName92(s){return N(s).replace(/[^a-z0-9]+/g,'_').replace(/^_+|_+$/g,'')||'arquivo'} function csv92(name,rows){const csv=rows.map(function(r){return r.map(function(v){return '"'+T(v).replace(/"/g,'""')+'"'}).join(';')}).join('\n');const blob=new Blob([csv],{type:'text/csv;charset=utf-8'});try{download(blob,name)}catch(e){const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download=name;a.click();setTimeout(function(){URL.revokeObjectURL(a.href)},1000)}} function renderDelivery92(){ensure92();if(!allowed92()){const c=document.getElementById('content');if(c)c.innerHTML='
Sem permissão para Entrega.
';return}const tab=S().deliveryV92.tab||'entrega';let html=hero92()+tabs92();html+=tab==='qualidade'?qualidadeTab92():tab==='rotina'?rotinaTab92():tab==='lgpd'?lgpdTab92():tab==='dossie'?dossieTab92():entregaTab92();const c=document.getElementById('content');if(c)c.innerHTML=html} W.entrega=renderDelivery92;W.idv92RenderDelivery=renderDelivery92; function injectNav92(){try{const nav=document.getElementById('nav');if(!nav||nav.querySelector('[data-v="entrega"]')||!allowed92())return;const btn=document.createElement('button');btn.type='button';btn.setAttribute('data-v','entrega');btn.onclick=function(){if(typeof navigate==='function')navigate('entrega')};btn.innerHTML='🏁Entrega';const logout=[].slice.call(nav.querySelectorAll('button')).find(function(b){return /Sair/i.test(b.textContent||'')});if(logout)nav.insertBefore(btn,logout);else nav.appendChild(btn)}catch(e){}} function wrapRender92(){const old=W.render||(typeof render==='function'?render:null);if(old&&!old.__v92){const wrapped=function(){let v='';try{v=N(view||W.view||'')}catch(e){}if(v==='entrega'||v.includes('entrega')){renderDelivery92();setTimeout(injectNav92,40);return}try{return old.apply(this,arguments)}finally{setTimeout(injectNav92,40)}};wrapped.__v92=true;W.render=wrapped;try{render=wrapped}catch(e){}}} function wrapBuildNav92(){const old=W.buildNav||(typeof buildNav==='function'?buildNav:null);if(old&&!old.__v92){const wrapped=function(){ensure92();const r=old.apply(this,arguments);setTimeout(injectNav92,40);return r};wrapped.__v92=true;W.buildNav=wrapped;try{buildNav=wrapped}catch(e){}}} function boot92(){try{ensure92();wrapBuildNav92();wrapRender92();saveRaw92();if(user92()&&typeof buildNav==='function')buildNav();if(user92()&&typeof render==='function')render();setTimeout(injectNav92,120)}catch(e){console.warn('boot V10.9.92',e)}} document.addEventListener('DOMContentLoaded',function(){setTimeout(boot92,3900)});setTimeout(boot92,4300); })(); '); win.document.close(); win.print()} W.idv93ToggleMaintenance=function(){if(!can93('support')){toast93('Sem permissão.');return} const s=ensure93().supportV93; if(!s.maintenance){const msg=prompt('Mensagem do modo manutenção:',s.maintenanceMsg||'Sistema em manutenção operacional.'); if(msg===null)return; s.maintenance=true; s.maintenanceMsg=msg}else{s.maintenance=false} audit93('Alterou modo manutenção V10.9.93',s.maintenance?'Ativo':'Inativo'); save93(); renderSupport93()} function supportTab(){const arr=A(S().supportTicketsV93); return '

Central de chamados

Registre melhorias, dúvidas, bugs e solicitações pós-entrega.

Resumo

'+kpi('Total',arr.length,'chamados')+kpi('Abertos',ticketCounts().open,'pendentes')+kpi('Alta/Crítica',ticketCounts().high,'prioridade')+kpi('Resolvidos',arr.filter(t=>t.status==='Resolvido'||t.status==='Fechado').length,'finalizados')+'

Lista de chamados

'+(arr.length?arr.map(ticketRow).join(''):'
Nenhum chamado registrado.
')+'
'} function ticketRow(t){const cls=t.priority==='Crítica'||t.priority==='Alta'?'high':t.priority==='Média'?'medium':'low'; return '
🎧
'+E(t.title)+''+E(t.id)+' • '+E(t.type)+' • '+E(t.priority)+' • '+E(t.status)+' • '+E(t.createdAt)+' • '+E(t.owner||'')+''+E(t.description||'')+'
'} W.idv93CreateTicket=function(){if(!can93('view')){toast93('Sem permissão.');return} const title=prompt('Título do chamado:'); if(!title)return; const type=prompt('Tipo: Bug, Melhoria, Dúvida, Treinamento, Implantação','Melhoria')||'Melhoria'; const priority=prompt('Prioridade: Baixa, Média, Alta, Crítica','Média')||'Média'; const desc=prompt('Descrição curta do chamado:','')||''; S().supportTicketsV93.unshift({id:uid93('SUP'),title,type,priority,status:'Aberto',description:desc,owner:user()?.name||'Sistema',createdAt:now(),updatedAt:now()}); audit93('Criou chamado V10.9.93',title); save93(); renderSupport93()} W.idv93UpdateTicket=function(id,status){const t=A(S().supportTicketsV93).find(x=>x.id===id); if(!t)return; t.status=status; t.updatedAt=now(); t.updatedBy=user()?.name||'Sistema'; audit93('Atualizou chamado V10.9.93',id+' • '+status); save93(); renderSupport93()} W.idv93DeleteTicket=function(id){if(!can93('critical')){toast93('Somente administrador exclui chamado.');return} if(!confirm('Excluir chamado?'))return; snapshot93('Antes de excluir chamado V10.9.93'); S().supportTicketsV93=A(S().supportTicketsV93).filter(x=>x.id!==id); audit93('Excluiu chamado V10.9.93',id); save93(); renderSupport93()} W.idv93ExportTicketsCsv=function(){csv93('chamados_suporte_v10_9_93.csv',[['id','titulo','tipo','prioridade','status','responsavel','criado','atualizado','descricao'],...A(S().supportTicketsV93).map(t=>[t.id,t.title,t.type,t.priority,t.status,t.owner,t.createdAt,t.updatedAt,t.description])])} function incidentsTab(){const arr=A(S().incidentLogV93); return '

Registro de incidentes

Use para queda de sistema, erro de dados, falha de sincronização, perda de fotos, problema de permissão ou falha operacional.

Playbook rápido

1
Criar snapshotAntes de qualquer reparo.
2
Exportar dossiêGuardar estado atual para análise.
3
Aplicar reparo seguroSomente se o diagnóstico indicar.

Incidentes

'+(arr.length?arr.map(incidentRow).join(''):'
Nenhum incidente registrado.
')+'
'} function incidentRow(i){const cls=i.severity==='Crítico'||i.severity==='Alto'?'bad':i.severity==='Médio'?'warn':'info'; return '
🚨
'+E(i.title)+''+E(i.id)+' • '+E(i.severity)+' • '+E(i.status)+' • '+E(i.createdAt)+' • '+E(i.owner||'')+''+E(i.description||'')+'
'+pill(i.severity,cls)+'
'} W.idv93CreateIncident=function(){if(!can93('support')){toast93('Sem permissão.');return} const title=prompt('Título do incidente:'); if(!title)return; const severity=prompt('Severidade: Baixo, Médio, Alto, Crítico','Médio')||'Médio'; const desc=prompt('Descrição do incidente:','')||''; snapshot93('Incidente registrado V10.9.93'); S().incidentLogV93.unshift({id:uid93('INC'),title,severity,status:'Aberto',description:desc,owner:user()?.name||'Sistema',createdAt:now(),updatedAt:now(),stateBytes:stateBytes(),storageBytes:storageBytes()}); audit93('Registrou incidente V10.9.93',title); save93(); renderSupport93()} W.idv93UpdateIncident=function(id,status){const i=A(S().incidentLogV93).find(x=>x.id===id); if(!i)return; i.status=status; i.updatedAt=now(); i.updatedBy=user()?.name||'Sistema'; audit93('Atualizou incidente V10.9.93',id+' • '+status); save93(); renderSupport93()} W.idv93ExportIncidentsCsv=function(){csv93('incidentes_idriver_v10_9_93.csv',[['id','titulo','severidade','status','responsavel','criado','atualizado','descricao','estado_bytes','storage_bytes'],...A(S().incidentLogV93).map(i=>[i.id,i.title,i.severity,i.status,i.owner,i.createdAt,i.updatedAt,i.description,i.stateBytes,i.storageBytes])])} function backupTab(){return '

Pacote de implantação/backup

Gera um pacote JSON com estado completo, resumo, checklist, chamados, incidentes e histórico de versões.

Nota: pacote completo pode ficar pesado se houver muitas fotos em base64 nas O.S.

Armazenamento

'+kpi('Estado',bytes(stateBytes()),'JSON')+kpi('LocalStorage',bytes(storageBytes()),'total')+kpi('Snapshots',A(S().snapshotsV89).length,'locais')+kpi('Fotos',countPhotos(),'em O.S.')+'

Resumo técnico

'+E(summaryText())+'
'} function countPhotos(){return A(S().orders).reduce((n,o)=>n+A(o.photos).length,0)} function packageData(full){return {version:VERSION93,createdAt:new Date().toISOString(),user:user()?.name||'Sistema',summary:summaryText(),postDeliveryChecklist:S().postDeliveryChecklistV93,support:S().supportV93,tickets:S().supportTicketsV93,incidents:S().incidentLogV93,releases:S().releaseHistoryV93,storage:{stateBytes:stateBytes(),localStorageBytes:storageBytes(),photos:countPhotos()},state:full?S():undefined,counts:{orders:A(S().orders).length,clients:A(S().clients).length,technicians:A(S().technicians).length,products:A(S().products).length,devices:A(S().devices).length,movements:A(S().movements).length,notifications:A(S().notificationQueueV87).length}}} W.idv93ExportPackage=function(){snapshot93('Antes de exportar pacote V10.9.93'); const data=packageData(true); S().backupPackagesV93.unshift({id:uid93('PKG'),date:now(),user:user()?.name||'Sistema',type:'completo',bytes:stateBytes()}); save93(); downloadJson93('pacote_completo_idriver_v10_9_93.json',data); audit93('Exportou pacote completo V10.9.93','JSON')} W.idv93ExportLightPackage=function(){downloadJson93('pacote_leve_idriver_v10_9_93.json',packageData(false)); audit93('Exportou pacote leve V10.9.93','JSON')} W.idv93CreateSnapshot=function(){snapshot93('Snapshot manual V10.9.93'); audit93('Criou snapshot V10.9.93','Suporte'); toast93('Snapshot criado.')} function versionsTab(){return '

Histórico de versões

'+A(S().releaseHistoryV93).map(r=>'
🧬
'+E(r.version)+' — '+E(r.title||'')+''+E(r.date)+' • '+E(r.notes||'')+'
').join('')+'

Notas da V10.9.93

'+E('Incluído:\n- Central Pós-entrega/Suporte\n- Chamados e incidentes\n- Aceite pós-entrega\n- Modo manutenção\n- Pacote completo/leves de backup\n- Versionamento interno\n- Snapshots antes de ações sensíveis\n\nRecomendação final:\nusar esta versão como entrega HTML avançada e evoluir para backend real antes de SaaS multiusuário em produção.')+'
'} function summaryText(){const p=progress(), tc=ticketCounts(), ic=incidentCounts(); return 'iDriver Mobile Command '+VERSION93+'\nData: '+now()+'\nUsuário: '+(user()?.name||'Sistema')+'\n\nIndicadores:\n- O.S.: '+A(S().orders).length+'\n- Clientes: '+A(S().clients).length+'\n- Técnicos: '+A(S().technicians).length+'\n- Produtos: '+A(S().products).length+'\n- Ativos: '+A(S().devices).length+'\n- Movimentações: '+A(S().movements).length+'\n- Fila de notificações: '+A(S().notificationQueueV87).length+'\n- Chamados: '+tc.total+' total / '+tc.open+' abertos\n- Incidentes: '+ic.total+' total / '+ic.open+' abertos\n- Checklist pós-entrega: '+p.done+'/'+p.total+' ('+p.pct+'%)\n- Estado: '+bytes(stateBytes())+'\n- LocalStorage: '+bytes(storageBytes())+'\n- Fotos em O.S.: '+countPhotos()+'\n\nLimitação honesta: HTML/localStorage é entrega avançada para operação assistida, demonstração e implantação controlada. Produção SaaS real exige backend, autenticação segura, hash de senha, banco relacional, storage para imagens e auditoria no servidor.'} function renderSupport93(){ensure93(); if(!can93('view')){const c=document.getElementById('content'); if(c)c.innerHTML='
Sem permissão para Suporte.
'; return} const tab=S().supportV93.tab||'pos'; let html=hero()+tabs(); html+=tab==='suporte'?supportTab():tab==='incidentes'?incidentsTab():tab==='backup'?backupTab():tab==='versoes'?versionsTab():posTab(); const c=document.getElementById('content'); if(c)c.innerHTML=html} W.suporte=renderSupport93; W.idv93RenderSupport=renderSupport93; function injectNav(){try{const nav=document.getElementById('nav'); if(!nav||nav.querySelector('[data-v="suporte"]')||!can93('view'))return; const btn=document.createElement('button'); btn.type='button'; btn.setAttribute('data-v','suporte'); btn.onclick=function(){if(typeof navigate==='function')navigate('suporte')}; btn.innerHTML='🎧Suporte'; const logout=[].slice.call(nav.querySelectorAll('button')).find(b=>/Sair/i.test(b.textContent||'')); if(logout)nav.insertBefore(btn,logout);else nav.appendChild(btn)}catch(e){}} function wrapRender(){const old=W.render||(typeof render==='function'?render:null); if(old&&!old.__v93){const wrapped=function(){let v='';try{v=N(view||W.view||'')}catch(e){} if(v==='suporte'||v.includes('suporte')){renderSupport93(); setTimeout(injectNav,40); return} try{return old.apply(this,arguments)}finally{setTimeout(injectNav,40)}}; wrapped.__v93=true; W.render=wrapped; try{render=wrapped}catch(_){}}} function wrapBuildNav(){const old=W.buildNav||(typeof buildNav==='function'?buildNav:null); if(old&&!old.__v93){const wrapped=function(){ensure93(); const r=old.apply(this,arguments); setTimeout(injectNav,40); return r}; wrapped.__v93=true; W.buildNav=wrapped; try{buildNav=wrapped}catch(_){}}} function boot(){try{ensure93(); wrapBuildNav(); wrapRender(); save93(); if(user()&&typeof buildNav==='function')buildNav(); if(user()&&typeof render==='function')render(); setTimeout(injectNav,120)}catch(e){console.warn('boot V10.9.93',e)}} document.addEventListener('DOMContentLoaded',()=>setTimeout(boot,4700)); setTimeout(boot,5200); })();