☰
PERSONAL OS
BLACKPITS
v2.0 — 2026
SENHA DE ACESSO
ENTRAR →
CHECKLIST DO DIA
Vá para CHECKLIST DIÁRIO para adicionar tarefas.
CLIMA — ITABAIANA, PB
Carregando...
NOVA TAREFA
TAREFA
ÁREA
GERAL RESTAURANTE CYBERSECURITY
ENGENHARIA OFICINA FINANÇAS
TRADE TECH ESTUDOS
PRIORIDADE
NORMAL ALTA BAIXA
ADICIONAR
PROGRESSO DO DIA
0 / 0 concluídas
FOCO
25:00
SESSÃO 1 / 4 — 0 CICLOS COMPLETOS
▶ INICIAR
↺ RESET
» PULAR
NOVA NOTA
TÍTULO
ÁREA
GERAL CYBERSECURITY OSINT PENTEST ENGENHARIA OFICINA RESTAURANTE FINANÇAS TRADE TECH ESTUDOS
CONTEÚDO
SALVAR
LIMPAR
NOTAS — 0
TODAS GERAL CYBERSECURITY OSINT PENTEST ENGENHARIA OFICINA RESTAURANTE FINANÇAS TRADE TECH ESTUDOS
FILTRAR
ÁREA TODAS CYBERSECURITY OSINT PENTEST ENGENHARIA OFICINA RESTAURANTE FINANÇAS TECH ESTUDOS GERAL
TIPO TODOS PDF HTML SCRIPT RELATÓRIO DOCUMENTO
NOVO PROJETO
NOME
ÁREA
CYBERSECURITY ENGENHARIA OFICINA RESTAURANTE FINANÇAS TECH ESTUDOS GERAL
PRIORIDADE
ALTA MÉDIA BAIXA
DESCRIÇÃO
CRIAR
REGISTRAR OPERAÇÃO
DIREÇÃO LONG SHORT
STATUS ABERTA FECHADA
NOTAS / SETUP
REGISTRAR
CALCULADORA CMV DE PRATO
SALVAR PRATO
REFERÊNCIA CMV
● ABAIXO 30% — EXCELENTE
● 30–35% — BOM
● 35–40% — ATENÇÃO
● ACIMA 40% — CRÍTICO
PREÇO SUGERIDO
Para CMV de 30%:
CUSTO DO PRATO R$
LANÇAR DRE MENSAL
MÊS/ANO
SALVAR DRE
LANÇAR TRANSAÇÃO
DESCRIÇÃO
CATEGORIA RESTAURANTE PESSOAL TECH OFICINA EDUCAÇÃO OUTROS
LANÇAR
REGISTRAR TÉCNICA / WRITEUP
NOME
CATEGORIA OSINT WEB APP NETWORK RF/SDR HARDWARE WIRELESS FORENSE SOCIAL ENG CRIPTO
TIPO TÉCNICA VULNERABILIDADE FERRAMENTA WRITEUP CTF ESTUDO
DOMÍNIO DESCONHEÇO VI MAS NÃO PRATIQUEI PRATICANDO DOMINADO
FERRAMENTAS
NOTAS / CVE
REGISTRAR
BASE DE CONHECIMENTO
TODAS OSINT WEB APP NETWORK RF/SDR HARDWARE WIRELESS
ADICIONAR AO ARSENAL
NOME
CATEGORIA
OSINT PENTEST RF/SDR HARDWARE HACKING MARCENARIA SERRALHARIA ELÉTRICA SOFTWARE REDE OUTRO
TIPO
DISPOSITIVO SOFTWARE FERRAMENTA FÍSICA SCRIPT/TOOL EQUIPAMENTO
STATUS
OPERACIONAL EM MANUTENÇÃO QUEBRADO EMPRESTADO INATIVO
LOCALIZAÇÃO
BLACKARCH BANCADA OFICINA MOCHILA/CAMPO RASPBERRY PI ESCRITÓRIO NUVEM/GIT
MODELO/VERSÃO
OBSERVAÇÕES
ADICIONAR
FILTRAR ARSENAL
CATEGORIA
TODAS OSINT PENTEST RF/SDR HARDWARE HACKING MARCENARIA SERRALHARIA SOFTWARE
STATUS
TODOS OPERACIONAL EM MANUTENÇÃO QUEBRADO
NOVO PROJETO
NOME
TIPO CIVIL QUÍMICA MISTO
STATUS PLANEJANDO EM EXECUÇÃO PAUSADO CONCLUÍDO
DESCRIÇÃO / MEMORIAL
REGISTRAR
NOVO PROJETO
NOME
TIPO MARCENARIA SERRALHARIA MISTO ELÉTRICO
STATUS IDEIA PLANEJANDO COMPRANDO MATERIAL EM EXECUÇÃO CONCLUÍDO
MATERIAIS
REGISTRAR
FERRAMENTAS AI LOCAIS
GPT-SoVITS
ATIVO localhost:9874
Ollama — qwen2.5-coder:7b
ATIVO localhost:11434
Aider
ATIVO ~/.local/bin/aider
Claude Code
ATIVO ~/.local/bin/claude
DaVinci Resolve
SETUP Em instalação
PIPELINE YOUTUBE
1. Roteiro
Claude / Ollama
4. Vídeo
Veo 2 / Gemini Pro
NOTAS TÉCNICAS RÁPIDAS
SALVAR NOTA
VOCABULÁRIO — 0
TODOS NÃO DOMINADOS PARCIAIS DOMINADOS
RESULTADO
Envie uma imagem ou PDF para extrair o conteúdo...
COMO USAR
1. Crie um repositório PRIVADO no GitHub
2. Gere um PAT com permissão de repo
3. Preencha os campos ao lado
4. Clique PUSH para salvar seus dados
5. Em outro dispositivo: configure igual e clique PULL
STATUS DO SYNC
Nenhum sync realizado.
SEGURANÇA
● Token salvo apenas no localStorage local
● Repositório privado = só você acessa
● Não use para dados ultra-sensíveis (senhas, credenciais ativas)
● GitHub tem acesso técnico ao conteúdo
CONFIGURAÇÃO
CONTEXTO / ESPECIALIDADE
ASSISTENTE GERAL
CYBERSECURITY / OSINT / PENTEST
TRADER — FOREX / AÇÕES
GESTÃO DE RESTAURANTE
ENGENHARIA CIVIL / QUÍMICA
MARCENARIA / SERRALHARIA
PROFESSOR DE INGLÊS
CONSULTOR FINANCEIRO
CONTEXTO ATIVO
LIMPAR CHAT
DADOS DO SEU OS
O Gemini recebe contexto dos seus dados para respostas personalizadas.
CHAT
Configure sua chave API e selecione uma especialidade para começar.
→
CONFIGURAÇÃO
CHAVE API GEMINI
TIPO DE RELATÓRIO
RELATÓRIO FINANCEIRO — DRE RESTAURANTE
RELATÓRIO DE TRADES — ANÁLISE DE PERFORMANCE
RELATÓRIO DE PROJETOS — STATUS GERAL
RELATÓRIO DE CONHECIMENTO — CYBERSECURITY
RELATÓRIO DE PROJETOS — OFICINA
RESUMO SEMANAL — TODAS AS ÁREAS
INSTRUÇÕES EXTRAS (OPCIONAL)
⚡ GERAR RELATÓRIO
⎘ COPIAR
💾 SALVAR COMO NOTA
TIPOS DISPONÍVEIS
DRE — Analisa receita, CMV, lucro, tendências
TRADES — Win rate, pares mais lucrativos, erros
PROJETOS — Status, atrasados, concluídos
CYBER — Técnicas dominadas, gaps, sugestões
OFICINA — Projetos, custos, materiais pendentes
SEMANAL — Visão geral de todas as áreas
RELATÓRIO GERADO
Selecione um tipo de relatório e clique em GERAR...
ADICIONAR BLOCO
DIA
SEG TER QUA QUI SEX SAB DOM
HORA INÍCIO
05:00 06:00 07:00 08:00 09:00 10:00 11:00 12:00 13:00 14:00 15:00 16:00 17:00 18:00 19:00 20:00 21:00 22:00 23:00
HORA FIM
06:00 07:00 08:00 09:00 10:00 11:00 12:00 13:00 14:00 15:00 16:00 17:00 18:00 19:00 20:00 21:00 22:00 23:00 00:00
ÁREA/COR
RESTAURANTE
CYBERSECURITY
TRADE
ENGENHARIA
OFICINA
ESTUDOS
TECH & AI
PESSOAL
EXERCÍCIO
DESCANSO
DESCRIÇÃO
ADICIONAR BLOCO
FILTRAR
STATUS
TODOS QUERO LER LENDO LIDO PAUSADO ABANDONADO
CATEGORIA
TODAS CYBERSECURITY ENGENHARIA FINANÇAS NEGÓCIOS GESTÃO TECNOLOGIA PROGRAMAÇÃO FILOSOFIA FICÇÃO
LENDO AGORA
PLAYER
SELECIONE UMA ESTAÇÃO
—
ADICIONAR ESTAÇÃO PERSONALIZADA
URL DO STREAM
ADICIONAR
NOVA ENTRADA
O QUE FIZ HOJE
O QUE APRENDI
O QUE TRAVOU / BLOQUEIOS
FOCO DE AMANHÃ
HUMOR (1-5)
😊 5 — Ótimo 🙂 4 — Bom 😐 3 — Normal 😔 2 — Ruim 😞 1 — Péssimo
ENERGIA (1-5)
⚡ 5 — Alta 🔋 4 — Boa 🔆 3 — Normal 🔅 2 — Baixa 💤 1 — Esgotado
SALVAR ENTRADA
NOVO HÁBITO
NOME DO HÁBITO
CRIAR HÁBITO
INVESTIMENTOS
ENGENHARIA
CONVERSÃO
DCA — PREÇO MÉDIO
Adicione compras para calcular preço médio
+ ADICIONAR LIMPAR
PREÇO MÉDIO
TOTAL INVESTIDO:
RESISTÊNCIA DE VIGAS — MOMENTO FLETOR
CARGA DISTRIBUÍDA q (kN/m)
COMPRIMENTO L (m)
TIPO DE VIGA
SIMPLESMENTE APOIADA (M=qL²/8) ENGASTADA (M=qL²/12) CONSOLE (M=qL²/2)
MOMENTO MÁXIMO
REAÇÃO DE APOIO:
CONVERSOR DE UNIDADES
CATEGORIA
PRESSÃO (MPa, kPa, kgf/cm², psi)
FORÇA (N, kN, kgf, tf)
COMPRIMENTO (mm, cm, m, km, pol, ft)
ÁREA (mm², cm², m², ha)
VOLUME (mL, L, m³, gal)
MASSA (g, kg, t, lb)
TEMPERATURA (°C, °F, K)
VALOR
REFERÊNCIAS RÁPIDAS
PRESSÃO
1 MPa = 10,197 kgf/cm² = 145,04 psi
1 kgf/cm² = 0,0981 MPa = 14,22 psi
CONCRETO (fck)
C20: 20 MPa | C25: 25 MPa | C30: 30 MPa
AÇO
CA-50: fyk=500 MPa | CA-60: fyk=600 MPa
QUÍMICA
M = n/V | C = m/V | n = m/M molar
GRAVAÇÃO
CHAVE API GEMINI
🎤
CLIQUE PARA GRAVAR
0:00
● GRAVAR
⚡ TRANSCREVER
💾 SALVAR NOTA
TRANSCRIÇÃO
Grave um áudio e clique em TRANSCREVER...
COMO USAR
1. Selecione as seções desejadas
2. Defina título e subtítulo
3. Clique em GERAR
4. Uma nova aba abre com os slides
5. Use as setas para navegar
6. Ctrl+P para imprimir / salvar PDF
ATALHOS NA APRESENTAÇÃO
→ / ESPAÇO — próximo slide
← — slide anterior
F — tela cheia
ESC — sair
EXPORTAR PARA O VAULT
📔 Diário Pessoal → /BLACKPITS/Diário/
📝 Notas → /BLACKPITS/Notas/
📈 Relatório de Trades → /BLACKPITS/Trade/
🍽️ DRE Restaurante → /BLACKPITS/Restaurante/
🔐 Base Cybersecurity → /BLACKPITS/Cyber/
📋 Projetos → /BLACKPITS/Projetos/
✅ Hábitos → /BLACKPITS/Hábitos/
⚡ EXPORTAR TUDO
CONFIGURAR GRÁFICO
SÍMBOLO
INTERVALO
1 min 5 min 15 min
30 min 1 hora
4 horas Diário Semanal
TEMA
Claro Escuro
CARREGAR
EUR/USD
USD/BRL
EUR/BRL
GBP/USD
PETR4
VALE3
IBOVESPA
BTC/USDT
OURO
TRADINGVIEW
Configure o símbolo e clique em CARREGAR
▶ CARREGAR EUR/USD
CONFIGURAÇÃO DO BOT
⚡ TESTAR BOT
MENSAGEM RÁPIDA
ENVIAR
EXPORTAR PARA TELEGRAM
🍽️ DRE Restaurante — último mês
📈 Performance de Trades
📋 Projetos Ativos
✅ Checklist do Dia
🔥 Status dos Hábitos
💰 Resumo Financeiro
💾 Backup JSON dos Dados
⚡ RESUMO DIÁRIO COMPLETO
COMO CONFIGURAR (PASSO A PASSO)
1. Abra o Telegram → busque @BotFather → envie /newbot
2. Escolha um nome e username para o bot
3. BotFather te dá o TOKEN — cole no campo acima
4. Abra seu novo bot → envie qualquer mensagem (ex: /start)
5. Acesse: https://api.telegram.org/bot{SEU_TOKEN}/getUpdates
6. Copie o "id" dentro de "chat" → cole no campo Chat ID
7. Clique TESTAR BOT — deve chegar uma mensagem no seu Telegram
FILTRAR
TODAS AS ÁREAS
CYBERSECURITY OSINT PENTEST
ENGENHARIA RESTAURANTE FINANÇAS
TECH & AI OFICINA ESTUDOS GERAL
ESTATÍSTICAS
DICA
● Suba o HTML no Google Drive
● Compartilhe como "Qualquer pessoa com o link"
● Cole o link aqui → botão ABRIR abre em qualquer dispositivo
FERRAMENTAS CADASTRADAS
☁ CLOUDFLARE KV SYNC
Configure após hospedar no Cloudflare Pages.
WORKER URL
API KEY DO WORKER
⬆ PUSH CLOUDFLARE
⬇ PULL CLOUDFLARE
NOTIFICAÇÕES
Alertas de checklist, CMV e pomodoro.
🔔 ATIVAR NOTIFICAÇÕES
DADOS
⬇ EXPORTAR JSON
⬆ IMPORTAR JSON
⚠ RESETAR TODOS OS DADOS
📋 CLOUDFLARE WORKER — CÓDIGO PARA DEPLOY
Cole este código em workers.cloudflare.com após criar um KV namespace chamado BP_DATA.
⎘ COPIAR CÓDIGO
Compartilhar Seção
Gera um link temporário somente leitura
SEÇÃO
DRE Restaurante
Performance de Trades
Projetos Ativos
Financeiro Pessoal
Hábitos
Base Cybersecurity
VALIDADE
1 hora
24 horas
7 dias
⤴ GERAR LINK
CANCELAR
const DK='blackpits_data';
let data=JSON.parse(localStorage.getItem(DK)||'{"notes":[],"files":[],"projects":[],"trades":[],"dre":[],"financas":[],"cyber":[],"engenharia":[],"oficina":[],"tech_notes":[],"words":[],"arsenal":[],"checklist":[],"pomo_cycles":0}');
if(!data.arsenal)data.arsenal=[];
if(!data.checklist)data.checklist=[];
if(!data.pomo_cycles)data.pomo_cycles=0;
function save(){localStorage.setItem(DK,JSON.stringify(data));updateKPIs()}
function uid(){return Date.now().toString(36)+Math.random().toString(36).slice(2,6)}
function fmt(n){return 'R$'+parseFloat(n||0).toLocaleString('pt-BR',{minimumFractionDigits:2,maximumFractionDigits:2})}
function dateStr(ts){return new Date(ts).toLocaleDateString('pt-BR')}
// CLOCK
function updateClock(){
const now=new Date();
document.getElementById('clock').textContent=now.toTimeString().slice(0,8);
const days=['DOM','SEG','TER','QUA','QUI','SEX','SAB'];
const months=['JAN','FEV','MAR','ABR','MAI','JUN','JUL','AGO','SET','OUT','NOV','DEZ'];
document.getElementById('datestr').textContent=days[now.getDay()]+' '+now.getDate()+' '+months[now.getMonth()]+' '+now.getFullYear();
document.getElementById('topbar-date').textContent=now.toLocaleDateString('pt-BR');
}
setInterval(updateClock,1000);updateClock();
// Midnight checklist reset
function checkMidnightReset(){
const today=new Date().toDateString();
const lastDay=localStorage.getItem('blackpits_lastday');
if(lastDay&&lastDay!==today){data.checklist=data.checklist.filter(c=>!c.daily);save();}
localStorage.setItem('blackpits_lastday',today);
}
checkMidnightReset();
// NAV
// sections defined below
function go(id){
sections.forEach(s=>document.getElementById('sec-'+s)?.classList.remove('active'));
document.querySelectorAll('.nav-item').forEach(el=>el.classList.remove('active'));
document.getElementById('sec-'+id)?.classList.add('active');
document.querySelectorAll('.nav-item').forEach(el=>{if(el.getAttribute('onclick')?.includes("'"+id+"'"))el.classList.add('active')});
document.getElementById('topbar-title').textContent=id.toUpperCase().replace('-',' ');
const renders={notes:renderNotes,files:renderFiles,projects:renderProjects,trade:renderTrades,restaurante:()=>{renderDRE();renderCMVPratos();},financas:renderFinancas,cyber:renderCyber,engenharia:renderEngenharia,oficina:renderOficina,estudos:renderWords,arsenal:renderArsenal,checklist:renderChecklist,github:loadGHConfig,cronograma:renderCronograma,livros:renderLivros,radio:renderRadioStations,diario:renderDiario,habitos:renderHabitos,calculadora:()=>switchCalc('inv'),voztext:()=>{const k=localStorage.getItem('blackpits_gem_key');if(k){const el=document.getElementById('voz-gem-key');if(el)el.value=k;}},telegram:()=>setTimeout(loadTGConfig,100),ferramentas:renderFerramentas};
renders[id]?.();
if(window.innerWidth<=768)document.getElementById('sidebar').classList.remove('open');
}
function toggleSidebar(){document.getElementById('sidebar').classList.toggle('open')}
// KPIs
function updateKPIs(){
document.getElementById('kpi-projects').textContent=data.projects.filter(p=>p.status!=='CONCLUÍDO').length;
document.getElementById('kpi-notes').textContent=data.notes.length;
document.getElementById('kpi-files').textContent=data.files.length;
document.getElementById('kpi-trades').textContent=data.trades.filter(t=>t.status==='ABERTA').length;
const pl=document.getElementById('home-projects-list');
const active=data.projects.filter(p=>p.status==='EM ANDAMENTO').slice(0,5);
pl.innerHTML=active.length?active.map(p=>`${p.priority} ${p.name} ${p.area}
`).join(''):'Nenhum projeto ativo.
';
const nl=document.getElementById('home-notes-list');
const recent=[...data.notes].reverse().slice(0,5);
nl.innerHTML=recent.length?recent.map(n=>`${n.area} ${n.title}
`).join(''):'Nenhuma nota.
';
const hc=document.getElementById('home-checklist');
const today=data.checklist.filter(c=>c.daily).slice(0,6);
hc.innerHTML=today.length?today.map(c=>`${c.done?'✓':''}
${c.text} `).join(''):'Nenhuma tarefa hoje.
';
}
// GLOBAL SEARCH
function globalSearch(q){
const el=document.getElementById('search-results');
if(!q||q.length<2){el.style.display='none';return}
const ql=q.toLowerCase();
const results=[];
data.notes.forEach(n=>{if(n.title?.toLowerCase().includes(ql)||n.content?.toLowerCase().includes(ql))results.push({title:n.title,meta:'NOTA — '+n.area,action:()=>go('notes')})});
data.files.forEach(f=>{if(f.name?.toLowerCase().includes(ql)||f.desc?.toLowerCase().includes(ql))results.push({title:f.name,meta:'ARQUIVO — '+f.area,url:f.url,action:()=>go('files')})});
data.projects.forEach(p=>{if(p.name?.toLowerCase().includes(ql)||p.desc?.toLowerCase().includes(ql))results.push({title:p.name,meta:'PROJETO — '+p.area+' / '+p.status,action:()=>go('projects')})});
data.cyber.forEach(c=>{if(c.name?.toLowerCase().includes(ql)||c.notes?.toLowerCase().includes(ql))results.push({title:c.name,meta:'CYBER — '+c.cat,action:()=>go('cyber')})});
data.arsenal.forEach(a=>{if(a.name?.toLowerCase().includes(ql))results.push({title:a.name,meta:'ARSENAL — '+a.cat,action:()=>go('arsenal')})});
data.trades.forEach(t=>{if(t.asset?.toLowerCase().includes(ql))results.push({title:t.asset,meta:'TRADE — '+t.market,action:()=>go('trade')})});
data.words.forEach(w=>{if(w.word?.toLowerCase().includes(ql)||w.trans?.toLowerCase().includes(ql))results.push({title:w.word,meta:'INGLÊS — '+w.trans,action:()=>go('estudos')})});
if(!results.length){el.innerHTML='Nenhum resultado para "'+q+'"
';el.style.display='block';return}
el.innerHTML=results.slice(0,8).map((r,i)=>``).join('');
el._results=results;
el.style.display='block';
}
function searchGo(i){
const r=document.getElementById('search-results')._results[i];
r.action();
document.getElementById('search-results').style.display='none';
document.getElementById('global-search').value='';
}
// PRINT
function printSection(){window.print()}
// EXPORT / IMPORT
function exportData(){
const blob=new Blob([JSON.stringify(data,null,2)],{type:'application/json'});
const a=document.createElement('a');a.href=URL.createObjectURL(blob);
a.download='blackpits_'+new Date().toISOString().slice(0,10)+'.json';a.click();
}
function importData(e){
const file=e.target.files[0];if(!file)return;
const reader=new FileReader();
reader.onload=function(ev){
try{
const imp=JSON.parse(ev.target.result);
['notes','files','projects','trades','dre','financas','cyber','engenharia','oficina','tech_notes','words','arsenal','checklist'].forEach(k=>{if(imp[k])data[k]=imp[k]});
save();alert('✓ Dados importados!');location.reload();
}catch{alert('Erro ao importar.');}
};reader.readAsText(file);
}
// POMODORO
let pomoTimer=null,pomoSeconds=0,pomoTotal=0,pomoMode='focus',pomoSession=1,pomoCycles=data.pomo_cycles||0,pomoRunning=false;
function getPomoTimes(){return{focus:parseInt(document.getElementById('pomo-focus-time')?.value||25)*60,short:parseInt(document.getElementById('pomo-short-time')?.value||5)*60,long:parseInt(document.getElementById('pomo-long-time')?.value||15)*60,sessions:parseInt(document.getElementById('pomo-sessions')?.value||4)}}
function resetPomo(){
clearInterval(pomoTimer);pomoRunning=false;pomoMode='focus';pomoSession=1;
const t=getPomoTimes();pomoSeconds=t.focus;pomoTotal=t.focus;
document.getElementById('pomo-btn').textContent='▶ INICIAR';
document.getElementById('pomo-mode-label').textContent='FOCO';
updatePomoDisplay();
}
function updatePomoDisplay(){
const m=Math.floor(pomoSeconds/60).toString().padStart(2,'0');
const s=(pomoSeconds%60).toString().padStart(2,'0');
document.getElementById('pomo-display').textContent=m+':'+s;
const pct=pomoTotal>0?(pomoSeconds/pomoTotal*100):100;
document.getElementById('pomo-fill').style.width=pct+'%';
document.getElementById('pomo-session').textContent=pomoSession;
document.getElementById('pomo-cycles').textContent=pomoCycles;
}
function togglePomo(){
if(pomoRunning){clearInterval(pomoTimer);pomoRunning=false;document.getElementById('pomo-btn').textContent='▶ INICIAR';}
else{
pomoRunning=true;document.getElementById('pomo-btn').textContent='⏸ PAUSAR';
if(pomoSeconds===0)skipPomo();
pomoTimer=setInterval(()=>{
pomoSeconds--;updatePomoDisplay();
if(pomoSeconds<=0){clearInterval(pomoTimer);pomoRunning=false;completePomo();}
},1000);
}
}
function completePomo(){
const t=getPomoTimes();
const task=document.getElementById('pomo-task')?.value||'—';
const hist=document.getElementById('pomo-history');
const line=document.createElement('div');
if(pomoMode==='focus'){
line.textContent='✓ FOCO '+pomoSession+' — '+task+' ['+new Date().toLocaleTimeString('pt-BR').slice(0,5)+']';
line.style.color='var(--green)';
if(pomoSession>=t.sessions){pomoMode='long';pomoSeconds=t.long;pomoTotal=t.long;pomoCycles++;data.pomo_cycles=pomoCycles;save();}
else{pomoMode='short';pomoSeconds=t.short;pomoTotal=t.short;}
}else{
line.textContent='— PAUSA — ['+new Date().toLocaleTimeString('pt-BR').slice(0,5)+']';
line.style.color='var(--text3)';
if(pomoMode==='long')pomoSession=1;else pomoSession++;
pomoMode='focus';pomoSeconds=t.focus;pomoTotal=t.focus;
}
hist.prepend(line);
document.getElementById('pomo-mode-label').textContent=pomoMode==='focus'?'FOCO':pomoMode==='short'?'PAUSA CURTA':'PAUSA LONGA';
document.getElementById('pomo-btn').textContent='▶ INICIAR';
updatePomoDisplay();
if('Notification' in window&&Notification.permission==='granted')new Notification('BLACKPITS OS',{body:pomoMode==='focus'?'Hora de focar!':'Hora de descansar!'});
}
function skipPomo(){completePomo()}
// CHECKLIST
function saveCheck(){
const text=document.getElementById('chk-text').value.trim();if(!text)return;
data.checklist.push({id:uid(),text,area:document.getElementById('chk-area').value,priority:document.getElementById('chk-priority').value,done:false,daily:true,ts:Date.now()});
save();renderChecklist();document.getElementById('chk-text').value='';
}
function toggleCheck(id){const c=data.checklist.find(c=>c.id===id);if(c){c.done=!c.done;save();renderChecklist();updateKPIs();}}
function deleteCheck(id){data.checklist=data.checklist.filter(c=>c.id!==id);save();renderChecklist();}
function clearChecklist(){data.checklist=[];save();renderChecklist();}
function renderChecklist(){
const items=data.checklist;
const done=items.filter(c=>c.done).length;
const total=items.length;
document.getElementById('chk-count').textContent=total;
document.getElementById('chk-progress-text').textContent=done+' / '+total+' concluídas';
document.getElementById('chk-progress-bar').style.width=(total?Math.round(done/total*100):0)+'%';
const el=document.getElementById('checklist-items');
const pc={ALTA:'red',NORMAL:'',BAIXA:''};
const sorted=[...items].sort((a,b)=>a.done-b.done);
el.innerHTML=sorted.length?sorted.map(c=>`
${c.done?'✓':''}
${c.text}
${c.area}
×
`).join(''):'Nenhuma tarefa. Adicione acima.
';
updateKPIs();
}
// ARSENAL
function saveArsenal(){
const name=document.getElementById('ar-name').value.trim();if(!name)return;
data.arsenal.push({id:uid(),name,cat:document.getElementById('ar-cat').value,type:document.getElementById('ar-type').value,status:document.getElementById('ar-status').value,loc:document.getElementById('ar-loc').value,model:document.getElementById('ar-model').value,obs:document.getElementById('ar-obs').value,ts:Date.now()});
save();renderArsenal();
['ar-name','ar-model','ar-obs'].forEach(id=>document.getElementById(id).value='');
}
function deleteArsenal(id){data.arsenal=data.arsenal.filter(a=>a.id!==id);save();renderArsenal()}
function renderArsenal(){
const fc=document.getElementById('ar-filter-cat').value;
const fs=document.getElementById('ar-filter-status').value;
let list=data.arsenal;
if(fc)list=list.filter(a=>a.cat===fc);
if(fs)list=list.filter(a=>a.status===fs);
document.getElementById('ar-total').textContent=data.arsenal.length;
document.getElementById('ar-ok').textContent=data.arsenal.filter(a=>a.status==='OPERACIONAL').length;
const sc={OPERACIONAL:'green','EM MANUTENÇÃO':'amber',QUEBRADO:'red',EMPRESTADO:'blue',INATIVO:''};
const el=document.getElementById('arsenal-list');
el.innerHTML=list.length?list.map(a=>`
${a.name}${a.model?' — '+a.model+' ':''}
${a.cat} ${a.type} ${a.loc}
${a.obs?`
${a.obs}
`:''}
${a.status}
DEL
`).join(''):'Nenhuma ferramenta registrada.
';
}
// NOTES
function saveNote(){
const title=document.getElementById('note-title').value.trim();if(!title)return;
data.notes.push({id:uid(),title,area:document.getElementById('note-area').value,content:document.getElementById('note-content').value,ts:Date.now()});
save();renderNotes();document.getElementById('note-title').value='';document.getElementById('note-content').value='';
}
function deleteNote(id){data.notes=data.notes.filter(n=>n.id!==id);save();renderNotes()}
function renderNotes(){
const filter=document.getElementById('note-filter').value;
let notes=filter?data.notes.filter(n=>n.area===filter):data.notes;
notes=[...notes].reverse();
document.getElementById('note-count').textContent=notes.length;
document.getElementById('notes-list').innerHTML=notes.length?notes.map(n=>`
${(n.content||'').slice(0,140)}${(n.content?.length>140)?'...':''}
${dateStr(n.ts)}
`).join(''):'Nenhuma nota.
';
}
// FILES
function saveFile(){
const name=document.getElementById('file-name').value.trim();if(!name)return;
data.files.push({id:uid(),name,type:document.getElementById('file-type').value,area:document.getElementById('file-area').value,url:document.getElementById('file-url').value,desc:document.getElementById('file-desc').value,ts:Date.now()});
save();renderFiles();['file-name','file-url','file-desc'].forEach(id=>document.getElementById(id).value='');
}
function deleteFile(id){data.files=data.files.filter(f=>f.id!==id);save();renderFiles()}
function renderFiles(){
const fa=document.getElementById('file-filter-area').value;
const ft=document.getElementById('file-filter-type').value;
let files=data.files;
if(fa)files=files.filter(f=>f.area===fa);
if(ft)files=files.filter(f=>f.type===ft);
files=[...files].reverse();
document.getElementById('file-total').textContent=data.files.length;
document.getElementById('file-html-count').textContent=data.files.filter(f=>f.type==='HTML').length;
const tc={PDF:'red',HTML:'blue',SCRIPT:'green',RELATÓRIO:'amber'};
document.getElementById('files-list').innerHTML=files.length?files.map(f=>`
${f.type}
${f.name}
${f.area}${f.desc?' — '+f.desc:''}
${f.url?`
ABRIR `:''}
DEL
`).join(''):'Nenhum arquivo.
';
}
// PROJECTS
function saveProject(){
const name=document.getElementById('proj-name').value.trim();if(!name)return;
data.projects.push({id:uid(),name,area:document.getElementById('proj-area').value,priority:document.getElementById('proj-priority').value,desc:document.getElementById('proj-desc').value,status:'BACKLOG',ts:Date.now()});
save();renderProjects();document.getElementById('proj-name').value='';document.getElementById('proj-desc').value='';
}
function moveProject(id,status){const p=data.projects.find(p=>p.id===id);if(p){p.status=status;save();renderProjects()}}
function deleteProject(id){data.projects=data.projects.filter(p=>p.id!==id);save();renderProjects()}
function renderProjects(){
const statuses=['BACKLOG','EM ANDAMENTO','CONCLUÍDO'];
const ids=['kanban-backlog','kanban-active','kanban-done'];
const pc={ALTA:'red',MÉDIA:'amber',BAIXA:''};
statuses.forEach((s,i)=>{
const ps=data.projects.filter(p=>p.status===s);
document.getElementById(ids[i]).innerHTML=ps.length?ps.map(p=>`
${p.priority} ${p.area}
${p.name}
${p.desc?`
${p.desc}
`:''}
${s!=='BACKLOG'?`← `:''}
${s!=='EM ANDAMENTO'?`▶ `:''}
${s!=='CONCLUÍDO'?`✓ `:''}
×
`).join(''):'Vazio
';
});
updateKPIs();
}
// TRADES
function saveTrade(){
const asset=document.getElementById('t-asset').value.trim();if(!asset)return;
const res=parseFloat(document.getElementById('t-res').value)||0;
data.trades.push({id:uid(),asset,market:document.getElementById('t-market').value,dir:document.getElementById('t-dir').value,status:document.getElementById('t-status').value,entry:document.getElementById('t-entry').value,sl:document.getElementById('t-sl').value,tp:document.getElementById('t-tp').value,result:res,emotion:document.getElementById('t-emotion').value,notes:document.getElementById('t-notes').value,ts:Date.now()});
save();renderTrades();document.getElementById('t-asset').value='';document.getElementById('t-res').value='';document.getElementById('t-notes').value='';
}
function deleteTrade(id){data.trades=data.trades.filter(t=>t.id!==id);save();renderTrades()}
function renderTrades(){
const closed=data.trades.filter(t=>t.status==='FECHADA');
const wins=closed.filter(t=>t.result>0).length;
const totalRes=closed.reduce((a,t)=>a+t.result,0);
const wr=closed.length?Math.round(wins/closed.length*100):0;
document.getElementById('t-total').textContent=data.trades.length;
document.getElementById('t-wr').textContent=wr+'%';
const rv=document.getElementById('t-result');rv.textContent=fmt(totalRes);rv.className='card-val '+(totalRes>=0?'trade-positive':'trade-negative');
document.getElementById('t-open').textContent=data.trades.filter(t=>t.status==='ABERTA').length;
const trades=[...data.trades].reverse();
document.getElementById('trade-list').innerHTML=trades.length?trades.map(t=>`
${t.dir} ${t.asset} ${t.market}
×
E:${t.entry||'—'} SL:${t.sl||'—'} TP:${t.tp||'—'}
${t.status}
${t.result?fmt(t.result):''}
${t.emotion}
`).join(''):'Nenhuma operação.
';
}
// DRE
function saveDRE(){
const mes=document.getElementById('r-mes').value.trim();if(!mes)return;
const rec=parseFloat(document.getElementById('r-rec-bruta').value)||0;
const imp=parseFloat(document.getElementById('r-impostos').value)||0;
const cmv=parseFloat(document.getElementById('r-cmv-val').value)||0;
const folha=parseFloat(document.getElementById('r-folha').value)||0;
const alug=parseFloat(document.getElementById('r-aluguel').value)||0;
const en=parseFloat(document.getElementById('r-energia').value)||0;
const recLiq=rec-imp;
const lucro=recLiq-(cmv+folha+alug+en);
const cmvPct=rec?Math.round(cmv/rec*100):0;
const margem=recLiq?Math.round(lucro/recLiq*100):0;
data.dre.push({id:uid(),mes,rec,imp,recLiq,cmv,folha,alug,en,lucro,cmvPct,margem,ts:Date.now()});
save();renderDRE();document.getElementById('r-mes').value='';
['r-rec-bruta','r-impostos','r-cmv-val','r-folha','r-aluguel','r-energia'].forEach(id=>document.getElementById(id).value='');
}
function deleteDRE(id){data.dre=data.dre.filter(d=>d.id!==id);save();renderDRE()}
function renderDRE(){
const last=data.dre.length?data.dre[data.dre.length-1]:null;
document.getElementById('r-receita').textContent=last?fmt(last.rec):'R$0';
document.getElementById('r-cmv').textContent=last?(last.cmvPct+(last.cmvPct>35?'% ⚠':'%')):'0%';
document.getElementById('r-lucro').textContent=last?fmt(last.lucro):'R$0';
document.getElementById('r-margem').textContent=last?last.margem+'%':'0%';
const list=[...data.dre].reverse();
document.getElementById('dre-list').innerHTML=list.length?list.map(d=>`
${d.mes}
×
CMV
${d.cmvPct}%${d.cmvPct>35?' ⚠':''}
`).join(''):'Nenhum DRE.
';
}
// FINANCAS
function saveFinanca(){
const desc=document.getElementById('f-desc').value.trim();if(!desc)return;
data.financas.push({id:uid(),desc,tipo:document.getElementById('f-tipo').value,valor:parseFloat(document.getElementById('f-valor').value)||0,cat:document.getElementById('f-cat').value,ts:Date.now()});
save();renderFinancas();document.getElementById('f-desc').value='';document.getElementById('f-valor').value='';
}
function deleteFinanca(id){data.financas=data.financas.filter(f=>f.id!==id);save();renderFinancas()}
function renderFinancas(){
const rec=data.financas.filter(f=>f.tipo==='RECEITA').reduce((a,f)=>a+f.valor,0);
const desp=data.financas.filter(f=>f.tipo==='DESPESA').reduce((a,f)=>a+f.valor,0);
const inv=data.financas.filter(f=>f.tipo==='INVESTIMENTO').reduce((a,f)=>a+f.valor,0);
document.getElementById('f-rec').textContent=fmt(rec);
document.getElementById('f-desp').textContent=fmt(desp);
document.getElementById('f-saldo').textContent=fmt(rec-desp);
document.getElementById('f-inv').textContent=fmt(inv);
const tc={RECEITA:'green',DESPESA:'red',INVESTIMENTO:'blue'};
const list=[...data.financas].reverse();
document.getElementById('financas-list').innerHTML=list.length?list.map(f=>`
${f.tipo}
${f.desc}${f.cat}
${fmt(f.valor)}
×
`).join(''):'Nenhum lançamento.
';
}
// CYBER
function saveCyber(){
const name=document.getElementById('cy-name').value.trim();if(!name)return;
data.cyber.push({id:uid(),name,cat:document.getElementById('cy-cat').value,type:document.getElementById('cy-type').value,level:document.getElementById('cy-level').value,tools:document.getElementById('cy-tools').value,notes:document.getElementById('cy-notes').value,ts:Date.now()});
save();renderCyber();document.getElementById('cy-name').value='';document.getElementById('cy-tools').value='';document.getElementById('cy-notes').value='';
}
function deleteCyber(id){data.cyber=data.cyber.filter(c=>c.id!==id);save();renderCyber()}
function renderCyber(){
const filter=document.getElementById('cy-filter').value;
let list=filter?data.cyber.filter(c=>c.cat===filter):data.cyber;
list=[...list].reverse();
const lc={'DESCONHEÇO':'','VI MAS NÃO PRATIQUEI':'red',PRATICANDO:'amber',DOMINADO:'green'};
document.getElementById('cyber-list').innerHTML=list.length?list.map(c=>`
${c.cat} ${c.type} ${c.level}
DEL
${c.name}
${c.tools?`
TOOLS: ${c.tools}
`:''}
${c.notes?`
${c.notes.slice(0,120)}
`:''}
`).join(''):'Nenhuma entrada.
';
}
// ENGENHARIA
function saveEngenharia(){
const name=document.getElementById('eng-name').value.trim();if(!name)return;
data.engenharia.push({id:uid(),name,type:document.getElementById('eng-type').value,status:document.getElementById('eng-status').value,desc:document.getElementById('eng-desc').value,ts:Date.now()});
save();renderEngenharia();document.getElementById('eng-name').value='';document.getElementById('eng-desc').value='';
}
function deleteEngenharia(id){data.engenharia=data.engenharia.filter(e=>e.id!==id);save();renderEngenharia()}
function renderEngenharia(){
const list=[...data.engenharia].reverse();
const sc={PLANEJANDO:'blue','EM EXECUÇÃO':'amber',PAUSADO:'red',CONCLUÍDO:'green'};
document.getElementById('eng-list').innerHTML=list.length?list.map(e=>`
${e.name}
${e.desc?`
${e.desc.slice(0,120)}
`:''}
`).join(''):'Nenhum projeto.
';
}
// OFICINA
function saveOficina(){
const name=document.getElementById('of-name').value.trim();if(!name)return;
data.oficina.push({id:uid(),name,type:document.getElementById('of-type').value,status:document.getElementById('of-status').value,cost:parseFloat(document.getElementById('of-cost').value)||0,priority:document.getElementById('of-priority').value,materials:document.getElementById('of-materials').value,ts:Date.now()});
save();renderOficina();document.getElementById('of-name').value='';document.getElementById('of-materials').value='';document.getElementById('of-cost').value='';
}
function deleteOficina(id){data.oficina=data.oficina.filter(o=>o.id!==id);save();renderOficina()}
function renderOficina(){
const list=[...data.oficina].reverse();
const sc={IDEIA:'',PLANEJANDO:'blue','COMPRANDO MATERIAL':'amber','EM EXECUÇÃO':'green',CONCLUÍDO:'green'};
const pc={ALTA:'red',MÉDIA:'amber',BAIXA:''};
document.getElementById('of-list').innerHTML=list.length?list.map(o=>`
${o.type} ${o.status} ${o.priority}
DEL
${o.name}
${o.cost?`
CUSTO EST.: ${fmt(o.cost)}
`:''}
${o.materials?`
${o.materials.slice(0,100)}
`:''}
`).join(''):'Nenhum projeto.
';
}
// TECH NOTES
function saveTechNote(){
const content=document.getElementById('tech-notes-input').value.trim();if(!content)return;
data.tech_notes.push({id:uid(),content,ts:Date.now()});
save();renderTechNotes();document.getElementById('tech-notes-input').value='';
}
function deleteTechNote(id){data.tech_notes=data.tech_notes.filter(n=>n.id!==id);save();renderTechNotes()}
function renderTechNotes(){
const list=[...data.tech_notes].reverse();
document.getElementById('tech-notes-list').innerHTML=list.length?list.map(n=>`
${dateStr(n.ts)} DEL
${n.content}
`).join(''):'';
}
// WORDS
function saveWord(){
const word=document.getElementById('en-word').value.trim();if(!word)return;
data.words.push({id:uid(),word,trans:document.getElementById('en-trans').value,type:document.getElementById('en-type').value,example:document.getElementById('en-example').value,mastered:document.getElementById('en-mastered').value,ts:Date.now()});
save();renderWords();document.getElementById('en-word').value='';document.getElementById('en-trans').value='';document.getElementById('en-example').value='';
}
function deleteWord(id){data.words=data.words.filter(w=>w.id!==id);save();renderWords()}
function renderWords(){
const filter=document.getElementById('en-filter').value;
let list=filter?data.words.filter(w=>w.mastered===filter):data.words;
list=[...list].reverse();
document.getElementById('word-count').textContent=data.words.length;
const mc={SIM:'green',PARCIAL:'amber','NÃO':'red'};
document.getElementById('words-list').innerHTML=list.length?list.map(w=>`
${w.word} ${w.type} ${w.mastered}
DEL
${w.trans}
${w.example?`
"${w.example}"
`:''}
`).join(''):'Nenhuma palavra.
';
}
// CMV CALCULATOR
if(!data.cmv_pratos)data.cmv_pratos=[];
function calcCMV(){
const custo=parseFloat(document.getElementById('cmv-custo').value)||0;
const preco=parseFloat(document.getElementById('cmv-preco').value)||0;
if(!custo||!preco){document.getElementById('cmv-result').style.display='none';return}
const pct=Math.round(custo/preco*100);
const lucro=preco-custo;
const margem=Math.round(lucro/preco*100);
const el=document.getElementById('cmv-result');
el.style.display='block';
const color=pct<=30?'var(--green)':pct<=35?'var(--amber)':'var(--red)';
document.getElementById('cmv-pct').textContent=pct+'%';
document.getElementById('cmv-pct').style.color=color;
document.getElementById('cmv-lucro').textContent='R$'+lucro.toFixed(2);
document.getElementById('cmv-margem').textContent=margem+'%';
const status=pct<=30?'✓ EXCELENTE':pct<=35?'✓ BOM':pct<=40?'⚠ ATENÇÃO':'✗ CRÍTICO';
document.getElementById('cmv-status').textContent=status;
document.getElementById('cmv-status').style.color=color;
document.getElementById('cmv-bar').style.background=`linear-gradient(to right,${color} ${Math.min(pct,100)}%,var(--bg4) ${Math.min(pct,100)}%)`;
}
function calcSugest(){
const c=parseFloat(document.getElementById('sugest-custo').value)||0;
if(!c){document.getElementById('sugest-result').textContent='';return}
const p30=(c/0.30).toFixed(2);
const p35=(c/0.35).toFixed(2);
document.getElementById('sugest-result').innerHTML=`CMV 30%: R$${p30} CMV 35%: R$${p35}`;
}
function saveCMVPrato(){
const nome=document.getElementById('cmv-prato').value.trim();
const custo=parseFloat(document.getElementById('cmv-custo').value)||0;
const preco=parseFloat(document.getElementById('cmv-preco').value)||0;
if(!nome||!custo||!preco)return;
if(!data.cmv_pratos)data.cmv_pratos=[];
data.cmv_pratos.push({id:uid(),nome,custo,preco,pct:Math.round(custo/preco*100),ts:Date.now()});
save();renderCMVPratos();
}
function deleteCMVPrato(id){data.cmv_pratos=data.cmv_pratos.filter(p=>p.id!==id);save();renderCMVPratos()}
function renderCMVPratos(){
if(!data.cmv_pratos)return;
const el=document.getElementById('cmv-pratos-list');
if(!el)return;
const list=[...data.cmv_pratos].reverse();
el.innerHTML=list.length?list.map(p=>{
const c=p.pct<=30?'var(--green)':p.pct<=35?'var(--amber)':'var(--red)';
return `${p.nome}
${p.pct}% CMV R$${p.preco.toFixed(2)} × `;
}).join(''):'Nenhum prato salvo.
';
}
// OCR
let ocrBase64=null,ocrMime=null;
function previewOCR(e){
const file=e.target.files[0];if(!file)return;
if(file.type==='application/pdf'){
document.getElementById('ocr-preview').style.display='none';
document.getElementById('ocr-status').textContent='PDF selecionado: '+file.name;
ocrMime='application/pdf';
}else{
const reader=new FileReader();
reader.onload=ev=>{
ocrBase64=ev.target.result.split(',')[1];
ocrMime=file.type;
const img=document.getElementById('ocr-img-preview');
img.src=ev.target.result;
document.getElementById('ocr-preview').style.display='block';
document.getElementById('ocr-status').textContent='Imagem pronta.';
};reader.readAsDataURL(file);
}
if(file.type==='application/pdf'){
const reader=new FileReader();
reader.onload=ev=>{ocrBase64=ev.target.result.split(',')[1];};
reader.readAsDataURL(file);
}
}
async function runOCR(){
const key=document.getElementById('ocr-apikey').value.trim();
if(!key){alert('Insira sua chave API Anthropic.');return}
if(!ocrBase64){alert('Selecione uma imagem ou PDF.');return}
const prompt=document.getElementById('ocr-prompt').value||'Extraia todo o texto e conteúdo importante deste documento de forma organizada.';
const status=document.getElementById('ocr-status');
const result=document.getElementById('ocr-result');
status.textContent='⟳ Processando com IA...';
result.textContent='Aguarde...';
localStorage.setItem('blackpits_ocr_key',key);
try{
const resp=await fetch('https://api.anthropic.com/v1/messages',{
method:'POST',
headers:{'Content-Type':'application/json','x-api-key':key,'anthropic-version':'2023-06-01'},
body:JSON.stringify({
model:'claude-opus-4-5',max_tokens:2000,
messages:[{role:'user',content:[
{type:ocrMime==='application/pdf'?'document':'image',source:{type:'base64',media_type:ocrMime,data:ocrBase64}},
{type:'text',text:prompt}
]}]
})
});
const d=await resp.json();
if(d.error){status.textContent='Erro: '+d.error.message;result.textContent='';return}
const text=d.content?.map(c=>c.text||'').join('\n')||'Sem resultado.';
result.textContent=text;
status.textContent='✓ Concluído — '+text.length+' caracteres extraídos.';
result._lastText=text;
}catch(err){status.textContent='Erro: '+err.message;result.textContent='';}
}
function saveOCRNote(){
const text=document.getElementById('ocr-result')._lastText||document.getElementById('ocr-result').textContent;
if(!text||text.includes('Envie uma'))return;
data.notes.push({id:uid(),title:'OCR — '+new Date().toLocaleDateString('pt-BR'),area:'GERAL',content:text,ts:Date.now()});
save();alert('✓ Salvo como nota!');
}
// Restore OCR key
const savedOCRKey=localStorage.getItem('blackpits_ocr_key');
if(savedOCRKey){document.addEventListener('DOMContentLoaded',()=>{const el=document.getElementById('ocr-apikey');if(el)el.value=savedOCRKey;});}
// GITHUB SYNC
function saveGHConfig(){
localStorage.setItem('blackpits_gh',JSON.stringify({
token:document.getElementById('gh-token').value,
user:document.getElementById('gh-user').value,
repo:document.getElementById('gh-repo').value,
filename:document.getElementById('gh-filename').value||'data.json'
}));
}
function loadGHConfig(){
const cfg=JSON.parse(localStorage.getItem('blackpits_gh')||'{}');
if(cfg.token)document.getElementById('gh-token').value=cfg.token;
if(cfg.user)document.getElementById('gh-user').value=cfg.user;
if(cfg.repo)document.getElementById('gh-repo').value=cfg.repo;
if(cfg.filename)document.getElementById('gh-filename').value=cfg.filename;
return cfg;
}
async function ghPush(){
const cfg=loadGHConfig();
if(!cfg.token||!cfg.user||!cfg.repo){alert('Configure token, usuário e repositório.');return}
const status=document.getElementById('gh-status');
status.style.color='var(--text3)';status.textContent='⟳ Enviando para GitHub...';
const content=btoa(unescape(encodeURIComponent(JSON.stringify(data,null,2))));
const filename=cfg.filename||'data.json';
const url=`https://api.github.com/repos/${cfg.user}/${cfg.repo}/contents/${filename}`;
try{
// Get current SHA if exists
let sha='';
const get=await fetch(url,{headers:{'Authorization':'token '+cfg.token,'Accept':'application/vnd.github.v3+json'}});
if(get.ok){const gd=await get.json();sha=gd.sha;}
const body={message:'BLACKPITS OS backup — '+new Date().toISOString(),content};
if(sha)body.sha=sha;
const resp=await fetch(url,{method:'PUT',headers:{'Authorization':'token '+cfg.token,'Accept':'application/vnd.github.v3+json','Content-Type':'application/json'},body:JSON.stringify(body)});
if(resp.ok){
const now=new Date().toLocaleString('pt-BR');
status.style.color='var(--green)';status.textContent='✓ Push realizado com sucesso em '+now;
document.getElementById('gh-last-sync').textContent='Último push: '+now;
localStorage.setItem('blackpits_gh_last',now);
}else{const e=await resp.json();status.style.color='var(--red)';status.textContent='Erro: '+e.message;}
}catch(err){status.style.color='var(--red)';status.textContent='Erro: '+err.message;}
}
async function ghPull(){
const cfg=loadGHConfig();
if(!cfg.token||!cfg.user||!cfg.repo){alert('Configure token, usuário e repositório.');return}
const status=document.getElementById('gh-status');
status.style.color='var(--text3)';status.textContent='⟳ Carregando do GitHub...';
const filename=cfg.filename||'data.json';
const url=`https://api.github.com/repos/${cfg.user}/${cfg.repo}/contents/${filename}`;
try{
const resp=await fetch(url,{headers:{'Authorization':'token '+cfg.token,'Accept':'application/vnd.github.v3+json'}});
if(!resp.ok){const e=await resp.json();status.style.color='var(--red)';status.textContent='Erro: '+e.message;return}
const d=await resp.json();
const text=decodeURIComponent(escape(atob(d.content.replace(/\n/g,''))));
const imported=JSON.parse(text);
['notes','files','projects','trades','dre','financas','cyber','engenharia','oficina','tech_notes','words','arsenal','checklist','cmv_pratos'].forEach(k=>{if(imported[k])data[k]=imported[k]});
save();
const now=new Date().toLocaleString('pt-BR');
status.style.color='var(--green)';status.textContent='✓ Pull realizado com sucesso em '+now;
document.getElementById('gh-last-sync').textContent='Último pull: '+now;
alert('✓ Dados carregados do GitHub!');location.reload();
}catch(err){status.style.color='var(--red)';status.textContent='Erro: '+err.message;}
}
// GEMINI CHAT
const GEM_CONTEXTS={
geral:`Você é um assistente pessoal de Vinícius, um engenheiro civil e químico, dono de restaurante, praticante de OSINT e pentest, trader e marceneiro/serralheiro. Responda de forma direta e técnica.`,
cyber:`Você é um especialista em cybersecurity. Vinícius pratica OSINT e pentest, usa BlackArch, tem RTL-SDR, Digispark, Raspberry Pi e está construindo um dispositivo equivalente ao Flipper Zero. Ajude com técnicas, ferramentas, CVEs, OSINT e red team. Seja técnico e direto.`,
trade:`Você é um analista financeiro e trader especialista em forex, ações e renda fixa. Vinícius está aprendendo a operar no mercado financeiro. Ajude com análise técnica, gestão de risco, setups, psicologia do trading e estratégias. Seja objetivo.`,
restaurante:`Você é um consultor especialista em gestão de restaurantes. Vinícius é dono de restaurante e precisa de ajuda com CMV, fluxo de caixa, cardápio, gestão de equipe e operação. Foque em KPIs práticos e lucratividade.`,
engenharia:`Você é um engenheiro sênior em civil e química. Vinícius tem formação em engenharia civil e é acadêmico em química. Ajude com cálculos, normas ABNT, projetos estruturais, processos químicos e dimensionamentos técnicos.`,
oficina:`Você é um especialista em marcenaria e serralheria. Vinícius tem uma oficina com compressor, ferramentas de metalworking e faz projetos customizados. Ajude com técnicas, materiais, cortes, solda e projetos.`,
ingles:`Você é um professor de inglês nativo. Vinícius está estudando inglês para fluência. Corrija erros, explique gramática, ensine vocabulário e expressões idiomáticas. Sempre responda em inglês e depois traduza se necessário.`,
financas:`Você é um consultor financeiro pessoal. Ajude Vinícius com controle de gastos, investimentos em renda fixa, ações e forex, planejamento financeiro e análise de patrimônio. Seja prático e objetivo.`
};
let gemHistory=[];
let gemCtx='geral';
function setGemContext(){
gemCtx=document.getElementById('gem-ctx').value;
document.getElementById('gem-ctx-display').textContent=GEM_CONTEXTS[gemCtx];
gemHistory=[];
document.getElementById('gem-messages').innerHTML='Contexto: '+document.getElementById('gem-ctx').options[document.getElementById('gem-ctx').selectedIndex].text+'
';
}
function getGemKey(){
const k=document.getElementById('gem-key')?.value||localStorage.getItem('blackpits_gem_key')||'';
return k.trim();
}
function buildDataContext(){
const parts=[];
if(data.dre?.length){const last=data.dre[data.dre.length-1];parts.push(`DRE mais recente (${last.mes}): Receita R$${last.rec?.toFixed(2)}, CMV ${last.cmvPct}%, Lucro R$${last.lucro?.toFixed(2)}, Margem ${last.margem}%`);}
if(data.trades?.length){const closed=data.trades.filter(t=>t.status==='FECHADA');const wins=closed.filter(t=>t.result>0).length;parts.push(`Trades: ${data.trades.length} total, ${closed.length} fechados, win rate ${closed.length?Math.round(wins/closed.length*100):0}%`);}
if(data.projects?.length){const active=data.projects.filter(p=>p.status==='EM ANDAMENTO');parts.push(`Projetos: ${active.length} ativos de ${data.projects.length} total`);}
if(data.arsenal?.length)parts.push(`Arsenal: ${data.arsenal.length} ferramentas registradas`);
if(data.cyber?.length)parts.push(`Base cyber: ${data.cyber.length} técnicas/ferramentas registradas`);
return parts.length?'\n\nCONTEXTO DOS DADOS DO USUÁRIO:\n'+parts.join('\n'):'';
}
function addMessage(role,text,loading=false){
const el=document.getElementById('gem-messages');
const div=document.createElement('div');
const isUser=role==='user';
div.style.cssText=`display:flex;flex-direction:column;align-items:${isUser?'flex-end':'flex-start'};gap:4px`;
div.innerHTML=`
${isUser?'VOCÊ':'GEMINI'}
${text}
`;
el.appendChild(div);
el.scrollTop=el.scrollHeight;
return div;
}
async function sendGemini(){
const key=getGemKey();
if(!key){alert('Configure sua chave API Gemini.');return;}
const input=document.getElementById('gem-input');
const msg=input.value.trim();
if(!msg)return;
input.value='';
addMessage('user',msg);
gemHistory.push({role:'user',parts:[{text:msg}]});
const status=document.getElementById('gem-status');
status.textContent='⟳ Gemini está pensando...';
const loadDiv=addMessage('assistant','⟳','loading');
const systemPrompt=GEM_CONTEXTS[gemCtx]+buildDataContext();
try{
const body={
system_instruction:{parts:[{text:systemPrompt}]},
contents:gemHistory
};
const resp=await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${key}`,{
method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)
});
const d=await resp.json();
if(d.error){loadDiv.querySelector('div:last-child').textContent='Erro: '+d.error.message;status.textContent='';return;}
const reply=d.candidates?.[0]?.content?.parts?.[0]?.text||'Sem resposta.';
loadDiv.querySelector('div:last-child').textContent=reply;
loadDiv.querySelector('div:last-child').id='';
gemHistory.push({role:'model',parts:[{text:reply}]});
status.textContent='';
}catch(err){loadDiv.querySelector('div:last-child').textContent='Erro: '+err.message;status.textContent='';}
}
function clearChat(){gemHistory=[];document.getElementById('gem-messages').innerHTML='Chat limpo.
';}
// RELATÓRIOS IA
const REL_PROMPTS={
dre:(d)=>{
const list=d.dre?.slice(-6)||[];
const txt=list.map(r=>`${r.mes}: Receita R$${r.rec?.toFixed(2)}, CMV ${r.cmvPct}%, Folha R$${r.folha?.toFixed(2)}, Lucro R$${r.lucro?.toFixed(2)}, Margem ${r.margem}%`).join('\n');
return `Analise os dados financeiros do restaurante abaixo e gere um relatório executivo completo em português. Identifique tendências, pontos críticos (CMV acima de 35% é alerta), compare períodos, sugira ações concretas de melhoria.\n\nDADOS DRE:\n${txt||'Sem dados ainda.'}`;
},
trade:(d)=>{
const trades=d.trades||[];
const closed=trades.filter(t=>t.status==='FECHADA');
const wins=closed.filter(t=>t.result>0);
const losses=closed.filter(t=>t.result<=0);
const totalRes=closed.reduce((a,t)=>a+(t.result||0),0);
const emotions=[...new Set(trades.map(t=>t.emotion))].join(', ');
return `Analise a performance de trading abaixo e gere um relatório completo em português com análise psicológica e técnica.\n\nDADOS:\nTotal de trades: ${trades.length}\nFechados: ${closed.length}\nVitórias: ${wins.length}\nDerrotas: ${losses.length}\nWin rate: ${closed.length?Math.round(wins.length/closed.length*100):0}%\nResultado total: R$${totalRes.toFixed(2)}\nEstados emocionais registrados: ${emotions||'N/A'}\nMercados operados: ${[...new Set(trades.map(t=>t.market))].join(', ')||'N/A'}`;
},
projetos:(d)=>{
const proj=d.projects||[];
const por_status={'BACKLOG':0,'EM ANDAMENTO':0,'CONCLUÍDO':0};
proj.forEach(p=>por_status[p.status]=(por_status[p.status]||0)+1);
const lista=proj.filter(p=>p.status==='EM ANDAMENTO').map(p=>`${p.name} [${p.area}] — Prioridade: ${p.priority}`).join('\n');
return `Gere um relatório de status de projetos em português.\n\nDADOS:\nTotal: ${proj.length}\nBacklog: ${por_status['BACKLOG']}\nEm andamento: ${por_status['EM ANDAMENTO']}\nConcluídos: ${por_status['CONCLUÍDO']}\n\nPROJETOS ATIVOS:\n${lista||'Nenhum'}`;
},
cyber:(d)=>{
const items=d.cyber||[];
const por_nivel={};
items.forEach(c=>{por_nivel[c.level]=(por_nivel[c.level]||0)+1;});
const por_cat={};
items.forEach(c=>{por_cat[c.cat]=(por_cat[c.cat]||0)+1;});
return `Analise a base de conhecimento em cybersecurity abaixo e gere um relatório com gaps de conhecimento e sugestões de estudo prioritário.\n\nDADOS:\nTotal de itens: ${items.length}\nPor nível: ${JSON.stringify(por_nivel)}\nPor categoria: ${JSON.stringify(por_cat)}`;
},
oficina:(d)=>{
const proj=d.oficina||[];
const lista=proj.map(p=>`${p.name} [${p.type}] — Status: ${p.status}, Custo est.: R$${(p.cost||0).toFixed(2)}`).join('\n');
const total=proj.reduce((a,p)=>a+(p.cost||0),0);
return `Gere um relatório dos projetos da oficina (marcenaria/serralheria) em português.\n\nDADOS:\nTotal projetos: ${proj.length}\nCusto total estimado: R$${total.toFixed(2)}\n\nLISTA:\n${lista||'Nenhum projeto.'}`;
},
semanal:(d)=>{
const parts=[];
if(d.projects)parts.push(`Projetos: ${d.projects.filter(p=>p.status==='EM ANDAMENTO').length} ativos, ${d.projects.filter(p=>p.status==='CONCLUÍDO').length} concluídos`);
if(d.trades){const closed=d.trades.filter(t=>t.status==='FECHADA');const wins=closed.filter(t=>t.result>0);parts.push(`Trades: ${d.trades.length} total, win rate ${closed.length?Math.round(wins.length/closed.length*100):0}%`);}
if(d.dre?.length){const l=d.dre[d.dre.length-1];parts.push(`Restaurante (último mês): Receita R$${l.rec?.toFixed(2)}, CMV ${l.cmvPct}%, Lucro R$${l.lucro?.toFixed(2)}`);}
if(d.notes)parts.push(`Notas registradas: ${d.notes.length}`);
if(d.cyber)parts.push(`Base cyber: ${d.cyber.length} técnicas`);
if(d.words)parts.push(`Inglês: ${d.words.length} palavras, ${d.words.filter(w=>w.mastered==='SIM').length} dominadas`);
return `Gere um resumo semanal executivo em português de todas as áreas de vida e trabalho de Vinícius. Destaque progresso, alertas e próximos passos recomendados.\n\nDADOS CONSOLIDADOS:\n${parts.join('\n')}`;
}
};
async function gerarRelatorio(){
const key=document.getElementById('rel-gem-key')?.value||localStorage.getItem('blackpits_gem_key')||'';
if(!key.trim()){alert('Configure sua chave API Gemini.');return;}
const tipo=document.getElementById('rel-tipo').value;
const extra=document.getElementById('rel-extra').value;
const status=document.getElementById('rel-status');
const output=document.getElementById('rel-output');
status.textContent='⟳ Gerando relatório com Gemini...';
output.textContent='Aguarde...';
let prompt=REL_PROMPTS[tipo]?.(data)||'Gere um relatório geral.';
if(extra)prompt+='\n\nINSTRUÇÕES EXTRAS: '+extra;
try{
const resp=await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${key.trim()}`,{
method:'POST',headers:{'Content-Type':'application/json'},
body:JSON.stringify({contents:[{role:'user',parts:[{text:prompt}]}]})
});
const d=await resp.json();
if(d.error){status.textContent='Erro: '+d.error.message;output.textContent='';return;}
const text=d.candidates?.[0]?.content?.parts?.[0]?.text||'Sem resultado.';
output.textContent=text;
output._lastText=text;
status.textContent='✓ Relatório gerado em '+new Date().toLocaleTimeString('pt-BR');
}catch(err){status.textContent='Erro: '+err.message;output.textContent='';}
}
function copiarRelatorio(){
const text=document.getElementById('rel-output')._lastText||document.getElementById('rel-output').textContent;
if(!text||text.includes('Selecione'))return;
navigator.clipboard.writeText(text).then(()=>alert('✓ Copiado!'));
}
function salvarRelatorioNota(){
const text=document.getElementById('rel-output')._lastText||document.getElementById('rel-output').textContent;
if(!text||text.includes('Selecione'))return;
const tipo=document.getElementById('rel-tipo').options[document.getElementById('rel-tipo').selectedIndex].text;
data.notes.push({id:uid(),title:'RELATÓRIO — '+tipo.split('—')[0].trim()+' — '+new Date().toLocaleDateString('pt-BR'),area:'GERAL',content:text,ts:Date.now()});
save();alert('✓ Salvo como nota!');
}
// Restore Gemini key
const savedGemKey=localStorage.getItem('blackpits_gem_key');
if(savedGemKey){setTimeout(()=>{const el=document.getElementById('gem-key');if(el)el.value=savedGemKey;const el2=document.getElementById('rel-gem-key');if(el2)el2.value=savedGemKey;},100);}
// CRONOGRAMA SEMANAL
if(!data.cronograma)data.cronograma=[];
const CR_COLORS={
RESTAURANTE:'#fff3e0',CYBERSECURITY:'#e8f5e9',TRADE:'#e3f2fd',
ENGENHARIA:'#fce4ec',OFICINA:'#efebe9',ESTUDOS:'#f3e5f5',
TECH:'#e0f7fa',PESSOAL:'#f5f5f5',EXERCÍCIO:'#f9fbe7',DESCANSO:'#fafafa'
};
const CR_BORDER={
RESTAURANTE:'#e65100',CYBERSECURITY:'#2e7d32',TRADE:'#1565c0',
ENGENHARIA:'#880e4f',OFICINA:'#4e342e',ESTUDOS:'#6a1b9a',
TECH:'#006064',PESSOAL:'#424242',EXERCÍCIO:'#558b2f',DESCANSO:'#bdbdbd'
};
const DIAS=['SEG','TER','QUA','QUI','SEX','SAB','DOM'];
const HORAS=['05:00','06:00','07:00','08:00','09:00','10:00','11:00','12:00','13:00','14:00','15:00','16:00','17:00','18:00','19:00','20:00','21:00','22:00','23:00'];
function saveCronograma(){
const dia=document.getElementById('cr-dia').value;
const inicio=document.getElementById('cr-inicio').value;
const fim=document.getElementById('cr-fim').value;
const area=document.getElementById('cr-area').value;
const desc=document.getElementById('cr-desc').value.trim();
if(!desc)return;
data.cronograma.push({id:uid(),dia,inicio,fim,area,desc});
save();renderCronograma();document.getElementById('cr-desc').value='';
}
function deleteCronogramaBloco(id){data.cronograma=data.cronograma.filter(c=>c.id!==id);save();renderCronograma();}
function limparCronograma(){if(confirm('Limpar todo o cronograma?')){data.cronograma=[];save();renderCronograma();}}
function renderCronograma(){
const el=document.getElementById('cronograma-grid');
if(!el)return;
const isDark=document.documentElement.classList.contains('dark');
const headerBg=isDark?'#1a1a1a':'#f4f4f4';
const borderC=isDark?'#2a2a2a':'#d0d0d0';
const textC=isDark?'#aaa':'#444';
let html=``;
html+=`HORA `;
DIAS.forEach(d=>html+=`${d} `);
html+=' ';
HORAS.forEach(hora=>{
html+=`${hora} `;
DIAS.forEach(dia=>{
const blocos=data.cronograma.filter(c=>c.dia===dia&&c.inicio===hora);
if(blocos.length){
html+=``;
blocos.forEach(b=>{
const bg=isDark?'#2a2a2a':(CR_COLORS[b.area]||'#f5f5f5');
const border=CR_BORDER[b.area]||'#999';
html+=`
${b.area}
${b.desc}
${b.inicio}–${b.fim}
`;
});
html+=' ';
}else{
html+=` `;
}
});
html+=' ';
});
html+='
';
html+=`* Clique em um bloco para removê-lo
`;
el.innerHTML=html;
}
// LIVROS
if(!data.livros)data.livros=[];
function saveLivro(){
const titulo=document.getElementById('liv-titulo').value.trim();
if(!titulo)return;
data.livros.push({
id:uid(),titulo,autor:document.getElementById('liv-autor').value,
cat:document.getElementById('liv-cat').value,status:document.getElementById('liv-status').value,
nota:document.getElementById('liv-nota').value,prog:parseInt(document.getElementById('liv-prog').value)||0,
notas:document.getElementById('liv-notas').value,link:document.getElementById('liv-link').value,ts:Date.now()
});
save();renderLivros();
['liv-titulo','liv-autor','liv-notas','liv-link','liv-prog'].forEach(id=>document.getElementById(id).value='');
}
function deleteLivro(id){data.livros=data.livros.filter(l=>l.id!==id);save();renderLivros();}
function updateLivroStatus(id,status){const l=data.livros.find(l=>l.id===id);if(l){l.status=status;save();renderLivros();}}
function renderLivros(){
if(!data.livros)data.livros=[];
const fs=document.getElementById('liv-filter-status')?.value||'';
const fc=document.getElementById('liv-filter-cat')?.value||'';
let list=data.livros;
if(fs)list=list.filter(l=>l.status===fs);
if(fc)list=list.filter(l=>l.cat===fc);
list=[...list].reverse();
document.getElementById('liv-total').textContent=data.livros.length;
document.getElementById('liv-lendo').textContent=data.livros.filter(l=>l.status==='LENDO').length;
document.getElementById('liv-lidos').textContent=data.livros.filter(l=>l.status==='LIDO').length;
document.getElementById('liv-quero').textContent=data.livros.filter(l=>l.status==='QUERO LER').length;
const lendoList=document.getElementById('liv-lendo-list');
const lendo=data.livros.filter(l=>l.status==='LENDO');
lendoList.innerHTML=lendo.length?lendo.map(l=>`
${l.titulo}
${l.autor||'—'}
${l.prog?`
${l.prog}%
`:''}
`).join(''):'Nenhum livro em leitura.
';
const sc={LENDO:'blue','QUERO LER':'','LIDO':'green',PAUSADO:'amber',ABANDONADO:'red'};
const stars=n=>n?'★'.repeat(n)+'☆'.repeat(5-n):'—';
document.getElementById('livros-list').innerHTML=list.length?list.map(l=>`
${l.titulo}
${l.autor||''}
${l.status}
${l.cat}
DEL
${l.nota?`
${stars(parseInt(l.nota))}
`:''}
${l.prog?`
`:''}
${l.notas?`
${l.notas.slice(0,160)}${l.notas.length>160?'...':''}
`:''}
${l.status!=='LENDO'?`▶ LENDO `:''}
${l.status!=='LIDO'?`✓ LIDO `:''}
${l.link?`ABRIR `:''}
`).join(''):'Nenhum livro.
';
}
// ===================== RÁDIO =====================
if(!data.radios)data.radios=[];
// Se nunca inicializou as rádios padrão, adiciona
if(!localStorage.getItem('blackpits_radios_init')){
data.radios=[
{id:'r1',name:'Rádio Nacional AM',genre:'MPB / Notícias',url:'https://radios.ebc.com.br/radio-nacional-am/icecast.audio/nacional-am.mp3'},
{id:'r2',name:'Jovem Pan FM',genre:'Notícias / Esportes',url:'https://jovempanfm.leanstream.co/JPFM-MP3'},
{id:'r3',name:'Antena 1',genre:'Pop / Rock',url:'https://antena1.leanstream.co/ANTENA1-MP3'},
{id:'r4',name:'Radio Rock 89 FM',genre:'Rock Nacional',url:'https://radiorock.leanstream.co/AABRFM-MP3'},
{id:'r5',name:'CBN',genre:'Jornalismo',url:'https://cbn.leanstream.co/CBNAM-MP3'},
{id:'r6',name:'Rádio Globo',genre:'Esportes / Variedades',url:'https://radioglobo.leanstream.co/RGLOBO-MP3'},
];
localStorage.setItem('blackpits_radios_init','1');
save();
}
let radioPlaying=false;
function getAllRadios(){return data.radios||[];}
function renderRadioStations(){
const el=document.getElementById('radio-stations-list');if(!el)return;
const all=getAllRadios();
el.innerHTML=all.length?all.map(r=>`
${r.name}
${r.genre}
${r.url||'sem URL'}
▶
✏️
DEL
`).join(''):'Nenhuma estação. Adicione abaixo.
';
}
function editRadio(id){
const r=data.radios.find(r=>r.id===id);if(!r)return;
const name=prompt('Nome da estação:',r.name);if(name===null)return;
const genre=prompt('Gênero:',r.genre);if(genre===null)return;
const url=prompt('URL do stream:',r.url);if(url===null)return;
r.name=name;r.genre=genre;r.url=url;
save();renderRadioStations();
}
function playRadio(id,name,genre,url){
if(!url||url==='sem URL'){alert('Esta estação não tem URL configurada. Clique em ✏️ para editar.');return;}
const audio=document.getElementById('radio-audio');
const wasPlaying=radioPlaying&&audio._currentId===id;
document.querySelectorAll('[id^=radio-ind-]').forEach(el=>{el.textContent='▶';el.className='tag';});
if(wasPlaying){audio.pause();radioPlaying=false;document.getElementById('radio-play-btn').textContent='▶';document.getElementById('radio-status').textContent='PARADO';audio._currentId=null;return;}
audio.src=url;audio._currentId=id;
audio.volume=parseFloat(document.getElementById('radio-vol').value)||0.7;
audio.play().then(()=>{
radioPlaying=true;
document.getElementById('radio-station-name').textContent=name;
document.getElementById('radio-station-genre').textContent=genre;
document.getElementById('radio-play-btn').textContent='⏸';
document.getElementById('radio-status').textContent='AO VIVO';
const ind=document.getElementById('radio-ind-'+id);
if(ind){ind.textContent='▶▶';ind.className='tag green';}
}).catch(e=>{document.getElementById('radio-status').textContent='ERRO — verifique a URL do stream';});
}
function toggleRadio(){
const audio=document.getElementById('radio-audio');
if(!audio.src)return;
if(radioPlaying){audio.pause();radioPlaying=false;document.getElementById('radio-play-btn').textContent='▶';document.getElementById('radio-status').textContent='PARADO';}
else{audio.play();radioPlaying=true;document.getElementById('radio-play-btn').textContent='⏸';document.getElementById('radio-status').textContent='AO VIVO';}
}
function addCustomRadio(){
const name=document.getElementById('radio-custom-name').value.trim();
const url=document.getElementById('radio-custom-url').value.trim();
if(!name||!url)return;
if(!data.radios)data.radios=[];
data.radios.push({id:'r_'+uid(),name,genre:document.getElementById('radio-custom-genre').value||'Custom',url});
save();renderRadioStations();
document.getElementById('radio-custom-name').value='';
document.getElementById('radio-custom-url').value='';
document.getElementById('radio-custom-genre').value='';
}
function deleteRadio(id){
if(!confirm('Remover esta estação?'))return;
data.radios=data.radios.filter(r=>r.id!==id);save();renderRadioStations();
}
// ===================== DIÁRIO =====================
if(!data.diario)data.diario=[];
function saveDiario(){
const fiz=document.getElementById('diario-fiz').value.trim();
if(!fiz)return;
data.diario.push({id:uid(),data:new Date().toLocaleDateString('pt-BR'),fiz,aprendi:document.getElementById('diario-aprendi').value,travou:document.getElementById('diario-travou').value,amanha:document.getElementById('diario-amanha').value,humor:document.getElementById('diario-humor').value,energia:document.getElementById('diario-energia').value,ts:Date.now()});
save();renderDiario();
['diario-fiz','diario-aprendi','diario-travou','diario-amanha'].forEach(id=>document.getElementById(id).value='');
}
function deleteDiario(id){data.diario=data.diario.filter(d=>d.id!==id);save();renderDiario();}
function renderDiario(){
const hj=document.getElementById('diario-hoje');
if(hj)hj.textContent=new Date().toLocaleDateString('pt-BR',{weekday:'long',year:'numeric',month:'long',day:'numeric'}).toUpperCase();
document.getElementById('diario-count').textContent=data.diario?.length||0;
const el=document.getElementById('diario-list');if(!el)return;
const list=[...(data.diario||[])].reverse();
const humorMap={'5':'😊 5','4':'🙂 4','3':'😐 3','2':'😔 2','1':'😞 1'};
const energiaMap={'5':'⚡ 5','4':'🔋 4','3':'🔆 3','2':'🔅 2','1':'💤 1'};
el.innerHTML=list.length?list.map(d=>`
${d.data}
HUMOR ${humorMap[d.humor]||d.humor}
ENERGIA ${energiaMap[d.energia]||d.energia}
DEL
${d.fiz?`
`:''}
${d.aprendi?`
APRENDI
${d.aprendi.slice(0,150)}
`:''}
${d.travou?`
TRAVOU
${d.travou.slice(0,150)}
`:''}
${d.amanha?`
AMANHÃ
${d.amanha.slice(0,150)}
`:''}
`).join(''):'Nenhuma entrada ainda.
';
}
// ===================== HÁBITOS =====================
if(!data.habitos)data.habitos=[];
if(!data.habito_logs)data.habito_logs=[];
function saveHabito(){
const nome=document.getElementById('hab-nome').value.trim();if(!nome)return;
data.habitos.push({id:uid(),nome,icon:document.getElementById('hab-icon').value||'✓',freq:document.getElementById('hab-freq').value});
save();renderHabitos();document.getElementById('hab-nome').value='';document.getElementById('hab-icon').value='';
}
function deleteHabito(id){
data.habitos=data.habitos.filter(h=>h.id!==id);
data.habito_logs=data.habito_logs.filter(l=>l.hid!==id);
save();renderHabitos();
}
function toggleHabito(hid){
const today=new Date().toDateString();
const existing=data.habito_logs.find(l=>l.hid===hid&&l.day===today);
if(existing){data.habito_logs=data.habito_logs.filter(l=>!(l.hid===hid&&l.day===today));}
else{data.habito_logs.push({hid,day:today,ts:Date.now()});}
save();renderHabitos();
}
function getStreak(hid){
const logs=data.habito_logs.filter(l=>l.hid===hid).map(l=>l.day);
let streak=0;const d=new Date();
while(true){if(logs.includes(d.toDateString()))streak++;else break;d.setDate(d.getDate()-1);}
return streak;
}
function renderHabitos(){
const today=new Date().toDateString();
const dateEl=document.getElementById('hab-date');
if(dateEl)dateEl.textContent=new Date().toLocaleDateString('pt-BR');
const hojeEl=document.getElementById('hab-hoje-list');
if(hojeEl){
hojeEl.innerHTML=data.habitos.length?data.habitos.map(h=>{
const done=data.habito_logs.some(l=>l.hid===h.id&&l.day===today);
return`
${done?'✓':''}
${h.icon}
${h.nome}
${done?'FEITO':'PENDENTE'}
`;
}).join(''):'Nenhum hábito. Adicione acima.
';
}
const streaksEl=document.getElementById('hab-streaks');
if(streaksEl){
streaksEl.innerHTML=data.habitos.length?`
HÁBITO STREAK TOTAL
${data.habitos.map(h=>{
const streak=getStreak(h.id);
const total=data.habito_logs.filter(l=>l.hid===h.id).length;
return`${h.icon} ${h.nome} ${streak}🔥 ${total}x DEL `;
}).join('')}
`:'Nenhum hábito registrado.
';
}
}
// ===================== CALCULADORA =====================
let dcaEntries=[];
function switchCalc(tab){
['inv','eng','conv'].forEach(t=>{
document.getElementById('calc-'+t).style.display=t===tab?'block':'none';
document.getElementById('calc-tab-'+t).className=t===tab?'btn primary':'btn';
});
if(tab==='conv')updateConvUnits();
}
function calcJC(){
const C=parseFloat(document.getElementById('jc-capital').value)||0;
const A=parseFloat(document.getElementById('jc-aporte').value)||0;
const taxa=parseFloat(document.getElementById('jc-taxa').value)||0;
const anos=parseFloat(document.getElementById('jc-anos').value)||0;
if(!taxa||!anos){document.getElementById('jc-result').style.display='none';return;}
const im=taxa/100/12;const n=anos*12;
const montante=C*Math.pow(1+im,n)+A*(Math.pow(1+im,n)-1)/im;
const investido=C+A*n;
const rendimento=montante-investido;
document.getElementById('jc-result').style.display='block';
document.getElementById('jc-montante').textContent=fmt(montante);
document.getElementById('jc-investido').textContent=fmt(investido);
document.getElementById('jc-rendimento').textContent=fmt(rendimento);
document.getElementById('jc-multi').textContent=(montante/Math.max(investido,1)).toFixed(2)+'x';
}
function addDCA(){
const p=parseFloat(document.getElementById('dca-price').value)||0;
const q=parseFloat(document.getElementById('dca-qty').value)||0;
if(!p||!q)return;
dcaEntries.push({p,q});
document.getElementById('dca-price').value='';document.getElementById('dca-qty').value='';
renderDCA();
}
function clearDCA(){dcaEntries=[];renderDCA();}
function renderDCA(){
const el=document.getElementById('dca-entries');
el.innerHTML=dcaEntries.map((e,i)=>`R$${e.p.toFixed(2)} × ${e.q} ×
`).join('');
if(!dcaEntries.length){document.getElementById('dca-result').style.display='none';return;}
const totalVal=dcaEntries.reduce((a,e)=>a+e.p*e.q,0);
const totalQty=dcaEntries.reduce((a,e)=>a+e.q,0);
const avg=totalVal/totalQty;
document.getElementById('dca-result').style.display='block';
document.getElementById('dca-avg').textContent='R$'+avg.toFixed(4);
document.getElementById('dca-total').textContent=fmt(totalVal)+' ('+totalQty+' unidades)';
}
function calcViga(){
const q=parseFloat(document.getElementById('viga-q').value)||0;
const L=parseFloat(document.getElementById('viga-l').value)||0;
const tipo=document.getElementById('viga-tipo').value;
if(!q||!L){document.getElementById('viga-result').style.display='none';return;}
const divisor={bi:8,eng:12,cons:2}[tipo];
const M=(q*L*L/divisor).toFixed(2);
const R=(q*L/2).toFixed(2);
document.getElementById('viga-result').style.display='block';
document.getElementById('viga-m').textContent=M+' kN·m';
document.getElementById('viga-r').textContent=R+' kN';
}
function calcDilui(){
const c1=parseFloat(document.getElementById('dil-c1').value)||0;
const v1=parseFloat(document.getElementById('dil-v1').value)||0;
const c2=parseFloat(document.getElementById('dil-c2').value)||0;
if(!c1||!v1||!c2){document.getElementById('dil-result').style.display='none';return;}
const v2=(c1*v1/c2).toFixed(2);
const agua=(v2-v1).toFixed(2);
document.getElementById('dil-result').style.display='block';
document.getElementById('dil-v2').textContent=v2+' mL';
document.getElementById('dil-agua').textContent=agua+' mL';
}
const CONV_UNITS={
pressao:{MPa:[1],kPa:[1000],'kgf/cm²':[10.1972],psi:[145.038],bar:[10],atm:[9.8692]},
forca:{N:[1],kN:[0.001],kgf:[0.10197],tf:[0.00010197],lbf:[0.22481]},
comprimento:{mm:[1],cm:[0.1],m:[0.001],km:[0.000001],'pol(in)':[0.039370],ft:[0.003281]},
area:{'mm²':[1],'cm²':[0.01],'m²':[0.000001],ha:[1e-10],'ft²':[0.0000107639]},
volume:{mL:[1],L:[0.001],'m³':[0.000001],gal:[0.000264172],'ft³':[0.0000353147]},
massa:{g:[1],kg:[0.001],t:[0.000001],lb:[0.00220462],oz:[0.035274]},
temperatura:{special:true}
};
function updateConvUnits(){
const cat=document.getElementById('conv-cat').value;
const units=CONV_UNITS[cat];
const keys=cat==='temperatura'?['°C','°F','K']:Object.keys(units);
['conv-from','conv-to'].forEach((id,i)=>{
const sel=document.getElementById(id);
sel.innerHTML=keys.map((k,j)=>`${k} `).join('');
});
doConvert();
}
function doConvert(){
const cat=document.getElementById('conv-cat')?.value;
const from=document.getElementById('conv-from')?.value;
const to=document.getElementById('conv-to')?.value;
const val=parseFloat(document.getElementById('conv-val')?.value)||0;
const el=document.getElementById('conv-result');const out=document.getElementById('conv-out');
if(!cat||!from||!to){if(el)el.style.display='none';return;}
let result;
if(cat==='temperatura'){
let celsius;
if(from==='°C')celsius=val;
else if(from==='°F')celsius=(val-32)/1.8;
else celsius=val-273.15;
if(to==='°C')result=celsius;
else if(to==='°F')result=celsius*1.8+32;
else result=celsius+273.15;
}else{
const units=CONV_UNITS[cat];
const toBase=val/units[from][0];
result=toBase*units[to][0];
}
if(el)el.style.display='block';
if(out)out.textContent=parseFloat(result.toPrecision(6))+' '+to;
}
// ===================== VOZ → TEXTO =====================
let mediaRecorder=null,audioChunks=[],recInterval=null,recSeconds=0,audioBlob=null;
function toggleRecording(){
if(mediaRecorder&&mediaRecorder.state==='recording'){stopRecording();}
else{startRecording();}
}
async function startRecording(){
try{
const stream=await navigator.mediaDevices.getUserMedia({audio:true});
mediaRecorder=new MediaRecorder(stream);audioChunks=[];recSeconds=0;
mediaRecorder.ondataavailable=e=>audioChunks.push(e.data);
mediaRecorder.onstop=()=>{
audioBlob=new Blob(audioChunks,{type:'audio/webm'});
document.getElementById('voz-transcribe-btn').disabled=false;
document.getElementById('voz-rec-status').textContent='✓ Áudio gravado. Clique em TRANSCREVER.';
};
mediaRecorder.start();
document.getElementById('voz-rec-btn').textContent='⏹ PARAR';
document.getElementById('voz-status').textContent='GRAVANDO...';
document.getElementById('voz-indicator').style.border='2px solid var(--red)';
document.getElementById('voz-indicator').style.background='rgba(204,0,0,0.1)';
recInterval=setInterval(()=>{recSeconds++;const m=Math.floor(recSeconds/60);const s=recSeconds%60;document.getElementById('voz-timer').textContent=m+':'+(s<10?'0':'')+s;},1000);
}catch(e){alert('Erro ao acessar microfone: '+e.message);}
}
function stopRecording(){
if(mediaRecorder){mediaRecorder.stop();mediaRecorder.stream.getTracks().forEach(t=>t.stop());}
clearInterval(recInterval);
document.getElementById('voz-rec-btn').textContent='● GRAVAR';
document.getElementById('voz-status').textContent='GRAVAÇÃO CONCLUÍDA';
document.getElementById('voz-indicator').style.border='2px solid var(--border)';
document.getElementById('voz-indicator').style.background='';
}
async function transcribeAudio(){
const key=document.getElementById('voz-gem-key')?.value||localStorage.getItem('blackpits_gem_key')||'';
if(!key.trim()){alert('Configure sua chave API Gemini.');return;}
if(!audioBlob){alert('Grave um áudio primeiro.');return;}
const status=document.getElementById('voz-rec-status');
const result=document.getElementById('voz-result');
status.textContent='⟳ Transcrevendo com Gemini...';
result.textContent='Aguarde...';
try{
const reader=new FileReader();
reader.onload=async ev=>{
const b64=ev.target.result.split(',')[1];
const resp=await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${key.trim()}`,{
method:'POST',headers:{'Content-Type':'application/json'},
body:JSON.stringify({contents:[{role:'user',parts:[
{inline_data:{mime_type:'audio/webm',data:b64}},
{text:'Transcreva este áudio em português. Retorne apenas o texto transcrito, sem comentários adicionais.'}
]}]})
});
const d=await resp.json();
if(d.error){status.textContent='Erro: '+d.error.message;result.textContent='';return;}
const text=d.candidates?.[0]?.content?.parts?.[0]?.text||'Sem resultado.';
result.textContent=text;result._lastText=text;
status.textContent='✓ Transcrição concluída.';
};
reader.readAsDataURL(audioBlob);
}catch(e){status.textContent='Erro: '+e.message;result.textContent='';}
}
function saveVozNota(){
const text=document.getElementById('voz-result')?._lastText||document.getElementById('voz-result')?.textContent;
if(!text||text.includes('Grave um'))return;
data.notes.push({id:uid(),title:'VOZ — '+new Date().toLocaleDateString('pt-BR')+' '+new Date().toLocaleTimeString('pt-BR').slice(0,5),area:'GERAL',content:text,ts:Date.now()});
save();alert('✓ Salvo como nota!');
}
// ===================== APRESENTAÇÃO =====================
function gerarApresentacao(){
const titulo=document.getElementById('apres-titulo').value||'BLACKPITS OS';
const sub=document.getElementById('apres-sub').value||new Date().toLocaleDateString('pt-BR');
const tema=document.getElementById('apres-tema').value;
const checks=document.querySelectorAll('#apres-checks input:checked');
const secoes=[...checks].map(c=>c.value);
const slides=[];
// Slide de capa
slides.push({tipo:'capa',titulo,sub});
secoes.forEach(s=>{
if(s==='dre'&&data.dre?.length){
const last=data.dre[data.dre.length-1];
slides.push({tipo:'dados',titulo:'FINANCEIRO — RESTAURANTE',items:[
{label:'Período',val:last.mes},
{label:'Receita Bruta',val:fmt(last.rec)},
{label:'CMV',val:last.cmvPct+'% '+(last.cmvPct>35?'⚠':'✓')},
{label:'Lucro Líquido',val:fmt(last.lucro)},
{label:'Margem',val:last.margem+'%'},
]});
}
if(s==='trade'&&data.trades?.length){
const closed=data.trades.filter(t=>t.status==='FECHADA');
const wins=closed.filter(t=>t.result>0);
const totalRes=closed.reduce((a,t)=>a+(t.result||0),0);
slides.push({tipo:'dados',titulo:'PERFORMANCE DE TRADES',items:[
{label:'Total de Operações',val:data.trades.length},
{label:'Fechadas',val:closed.length},
{label:'Win Rate',val:closed.length?Math.round(wins.length/closed.length*100)+'%':'—'},
{label:'Resultado Total',val:fmt(totalRes)},
{label:'Abertas',val:data.trades.filter(t=>t.status==='ABERTA').length},
]});
}
if(s==='projetos'&&data.projects?.length){
const ativos=data.projects.filter(p=>p.status==='EM ANDAMENTO');
slides.push({tipo:'lista',titulo:'PROJETOS ATIVOS',items:ativos.slice(0,8).map(p=>p.name+' ['+p.area+']')});
}
if(s==='financas'&&data.financas?.length){
const rec=data.financas.filter(f=>f.tipo==='RECEITA').reduce((a,f)=>a+f.valor,0);
const desp=data.financas.filter(f=>f.tipo==='DESPESA').reduce((a,f)=>a+f.valor,0);
slides.push({tipo:'dados',titulo:'FINANCEIRO PESSOAL',items:[
{label:'Receitas',val:fmt(rec)},
{label:'Despesas',val:fmt(desp)},
{label:'Saldo',val:fmt(rec-desp)},
]});
}
if(s==='oficina'&&data.oficina?.length){
slides.push({tipo:'lista',titulo:'PROJETOS — OFICINA',items:data.oficina.filter(o=>o.status!=='CONCLUÍDO').slice(0,8).map(o=>o.name+' ['+o.status+']')});
}
if(s==='habitos'&&data.habitos?.length){
const today=new Date().toDateString();
slides.push({tipo:'lista',titulo:'HÁBITOS — HOJE',items:data.habitos.map(h=>{
const done=data.habito_logs?.some(l=>l.hid===h.id&&l.day===today);
const streak=getStreak(h.id);
return h.icon+' '+h.nome+' — '+(done?'✓ FEITO':'PENDENTE')+' — Streak: '+streak;
})});
}
});
slides.push({tipo:'fim',titulo:'BLACKPITS OS',sub:'FIM DA APRESENTAÇÃO'});
const isDark=tema==='dark';
const bg=isDark?'#0a0a0a':'#ffffff';
const text=isDark?'#f0f0f0':'#0a0a0a';
const border=isDark?'#333':'#ddd';
const accent=isDark?'#fff':'#000';
const slideHTML=slides.map((s,i)=>{
let content='';
if(s.tipo==='capa'||s.tipo==='fim'){
content=``;
}else if(s.tipo==='dados'){
content=`
${s.titulo}
${s.items.map(item=>`
${item.label}
${item.val}
`).join('')}
`;
}else if(s.tipo==='lista'){
content=`
${s.titulo}
${s.items.map(item=>`
▸ ${item}
`).join('')}
`;
}
return`${content}
`;
}).join('');
const html=`${titulo}
${slideHTML}
1 / ${slides.length}
← ANTERIOR
PRÓXIMO →