import { useState, useRef, useEffect } from "react";
const CORRECT_PASSWORD = "123";
const MAX_ATTEMPTS = 10;
const LOCKOUT_MS = 30 * 60 * 1000;
const SESSION_TIMEOUT = 3 * 60 * 60 * 1000;
const FONT = "'Josefin Sans','Didact Gothic','Trebuchet MS',sans-serif";
const SYSTEM_PROMPT = `Você é AURA, geradora de eBooks profissionais. Responda SEMPRE em PT-BR.
QUANDO O USUÁRIO ENVIAR UM NICHO (qualquer texto que não seja ".", ".." ou "..."):
- Primeiro avalie: o texto é realmente um nicho de mercado, tema de conteúdo ou área de conhecimento válida? Se NÃO for, responda APENAS: "Desculpe, isso não parece ser um nicho. Pode me informar o nicho do seu eBook?"
- Se FOR válido: gere **TÍTULO EM MAIÚSCULO** em negrito — poderoso e magnético. Logo abaixo, *subtítulo persuasivo em itálico*. Depois EXATAMENTE 10 módulos numerados de 1 a 10.
- NÃO pergunte nada além disso. Gere direto.
QUANDO RECEBER ".": gere os próximos EXATAMENTE 10 módulos continuando a numeração.
QUANDO RECEBER "..": escreva APENAS uma mensagem de encerramento inspiradora. SEM módulos.
QUANDO RECEBER "...": responda exatamente: Qual é o nicho do seu produto?
REGRAS ABSOLUTAS:
1. Ao receber nicho válido: SEMPRE título + subtítulo + 10 módulos.
2. CADA módulo: EXATAMENTE 30 linhas com título, conceito, explicação, exemplo prático, dica de aplicação.
3. Módulos progridem do básico ao avançado.
4. Linguagem clara, profissional, densa.
5. NUNCA mencione os comandos ".", "..", "...".
6. NUNCA adicione conclusão ou resumo ao final de 10 módulos. Pare no décimo módulo.`;
function parseMarkdown(text) {
return text
.replace(/\*\*(.+?)\*\*/g, "$1")
.replace(/\*(.+?)\*/g, "$1")
.replace(/^#{1,3} (.+)$/gm, "$1")
.replace(/\n/g, "
");
}
function formatTime(ms) {
const m = Math.floor(ms / 60000);
const s = Math.floor((ms % 60000) / 1000);
return `${m}:${String(s).padStart(2,"0")}`;
}
function formatCountdown(sec) {
const h = Math.floor(sec / 3600);
const m = Math.floor((sec % 3600) / 60);
const s = sec % 60;
return `${String(h).padStart(2,"0")}:${String(m).padStart(2,"0")}:${String(s).padStart(2,"0")}`;
}
function LoginWallpaper() {
const canvasRef = useRef(null);
useEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
let raf;
const resize = () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; };
resize();
window.addEventListener("resize", resize);
const blobs = [
{ x:0.15, y:0.15, r:0.55, vx:0.00018, vy:0.00012, color:[80,15,180] },
{ x:0.80, y:0.20, r:0.50, vx:-0.00014, vy:0.00016, color:[15,35,160] },
{ x:0.75, y:0.80, r:0.52, vx:-0.00016, vy:-0.00013, color:[100,8,170] },
{ x:0.20, y:0.75, r:0.48, vx:0.00013, vy:-0.00015, color:[40,8,150] },
{ x:0.50, y:0.45, r:0.45, vx:0.00010, vy:0.00011, color:[60,12,160] },
];
let t = 0;
const draw = () => {
const W = canvas.width, H = canvas.height;
ctx.clearRect(0, 0, W, H);
// Base
ctx.fillStyle = "#05030f";
ctx.fillRect(0, 0, W, H);
// Blobs
ctx.globalCompositeOperation = "screen";
blobs.forEach(b => {
b.x += b.vx; b.y += b.vy;
if(b.x < 0.05 || b.x > 0.95) b.vx *= -1;
if(b.y < 0.05 || b.y > 0.95) b.vy *= -1;
const cx = b.x * W, cy = b.y * H;
const r = b.r * Math.max(W, H);
const g = ctx.createRadialGradient(cx, cy, 0, cx, cy, r);
const [R,G,B] = b.color;
g.addColorStop(0, `rgba(${R},${G},${B},0.35)`);
g.addColorStop(0.4, `rgba(${R},${G},${B},0.15)`);
g.addColorStop(1, `rgba(${R},${G},${B},0)`);
ctx.fillStyle = g;
ctx.beginPath();
ctx.ellipse(cx, cy, r, r * 0.85, t * 0.0003, 0, Math.PI * 2);
ctx.fill();
});
// Subtle noise shimmer
ctx.globalCompositeOperation = "source-over";
ctx.globalAlpha = 0.03 + Math.sin(t * 0.001) * 0.01;
for(let i = 0; i < 6; i++) {
const gx = ctx.createLinearGradient(0, (t * 0.4 + i * 140) % (H + 140) - 70, 0, (t * 0.4 + i * 140) % (H + 140) - 50);
gx.addColorStop(0, "transparent");
gx.addColorStop(0.5, `rgba(180,140,255,0.4)`);
gx.addColorStop(1, "transparent");
ctx.fillStyle = gx;
ctx.fillRect(0, 0, W, H);
}
ctx.globalAlpha = 1;
t++;
raf = requestAnimationFrame(draw);
};
draw();
return () => { cancelAnimationFrame(raf); window.removeEventListener("resize", resize); };
}, []);
return (
);
}
function ChatWallpaper() {
return (
{/* Base gradient */}
{/* Blob 1 — top-left purple */}
{/* Blob 2 — bottom-right blue */}
{/* Blob 3 — center accent */}
{/* Horizontal scan lines */}
{/* Subtle grid */}
{/* Bottom aurora glow */}
{/* Vignette */}
);
}
function LockSVG({ unlocked, wrong }) {
const c1 = unlocked ? "#6ee7b7" : wrong ? "#fca5a5" : "#9b8ecf";
const c2 = unlocked ? "#059669" : wrong ? "#ef4444" : "#4c3a8a";
const s1 = unlocked ? "#a7f3d0" : wrong ? "#fecaca" : "#c4b5fd";
const s2 = unlocked ? "#34d399" : wrong ? "#f87171" : "#7c3aed";
const glow = unlocked ? "drop-shadow(0 0 22px rgba(110,231,183,0.75))"
: wrong ? "drop-shadow(0 0 16px rgba(252,165,165,0.7))"
: "drop-shadow(0 8px 28px rgba(0,0,0,0.55))";
return (
);
}
function ChipSVG({ streaming, justDone, invalid }) {
const anim = invalid
? "chipInvalid 0.9s ease-in-out 3"
: streaming
? "chipRed 1.2s ease-in-out infinite"
: justDone
? "chipGreen 1.4s ease-in-out infinite"
: "none";
const board = invalid?"rgba(200,100,10,0.55)":streaming?"rgba(180,40,40,0.45)":justDone?"rgba(30,120,80,0.4)":"rgba(30,80,160,0.38)";
const bLight= invalid?"rgba(251,146,60,0.5)":streaming?"rgba(220,80,80,0.35)":justDone?"rgba(50,180,110,0.35)":"rgba(40,100,200,0.35)";
const chip = invalid?"rgba(251,146,60,0.75)":streaming?"rgba(210,100,30,0.55)":justDone?"rgba(200,160,20,0.5)":"rgba(200,140,30,0.48)";
const pin = invalid?"rgba(251,146,60,0.7)":streaming?"rgba(220,80,80,0.55)":justDone?"rgba(50,200,120,0.55)":"rgba(200,180,60,0.45)";
const p=4, px=(x,y,w,h,f)=>;
return (
);
}
const G = {
card: { background:"rgba(255,255,255,0.08)", backdropFilter:"blur(60px) saturate(200%)", WebkitBackdropFilter:"blur(60px) saturate(200%)", border:"1px solid rgba(255,255,255,0.22)", borderRadius:32, boxShadow:"0 8px 64px rgba(0,0,0,0.4),inset 0 1.5px 0 rgba(255,255,255,0.3)" },
header: { background:"rgba(255,255,255,0.05)", backdropFilter:"blur(50px) saturate(180%)", WebkitBackdropFilter:"blur(50px) saturate(180%)", borderBottom:"1px solid rgba(255,255,255,0.1)", boxShadow:"0 1px 0 rgba(255,255,255,0.07)" },
footer: { background:"rgba(255,255,255,0.04)", backdropFilter:"blur(50px) saturate(180%)", WebkitBackdropFilter:"blur(50px) saturate(180%)", borderTop:"1px solid rgba(255,255,255,0.09)" },
msgBot: { background:"rgba(255,255,255,0.07)", backdropFilter:"blur(30px)", WebkitBackdropFilter:"blur(30px)", border:"1px solid rgba(255,255,255,0.12)", boxShadow:"0 4px 20px rgba(0,0,0,0.15),inset 0 1px 0 rgba(255,255,255,0.09)" },
msgUser:{ background:"rgba(124,58,237,0.28)", backdropFilter:"blur(30px)", WebkitBackdropFilter:"blur(30px)", border:"1px solid rgba(167,139,250,0.35)", boxShadow:"0 8px 32px rgba(124,58,237,0.2),inset 0 1px 0 rgba(255,255,255,0.14)" },
input: { background:"rgba(255,255,255,0.07)", border:"1px solid rgba(255,255,255,0.18)", borderRadius:16, backdropFilter:"blur(20px)", WebkitBackdropFilter:"blur(20px)", boxShadow:"inset 0 1px 0 rgba(255,255,255,0.1)" },
btn: { background:"rgba(255,255,255,0.1)", border:"1px solid rgba(255,255,255,0.2)", backdropFilter:"blur(20px)", WebkitBackdropFilter:"blur(20px)", boxShadow:"0 4px 20px rgba(0,0,0,0.2),inset 0 1px 0 rgba(255,255,255,0.18)" },
};
function PasswordScreen({ onSuccess, unlocking }) {
const [pwd, setPwd] = useState("");
const [attempts, setAttempts] = useState(0);
const [status, setStatus] = useState("idle");
const [remaining, setRemaining] = useState(0);
const timerRef = useRef(null);
useEffect(()=>()=>clearInterval(timerRef.current),[]);
const startLockout = () => {
setStatus("locked"); setRemaining(LOCKOUT_MS);
timerRef.current = setInterval(()=>{
setRemaining(p=>{ if(p<=1000){clearInterval(timerRef.current);setAttempts(0);setStatus("idle");return 0;} return p-1000; });
},1000);
};
const handleSubmit = () => {
if(status==="locked") return;
if(pwd===CORRECT_PASSWORD){onSuccess();return;}
const n=attempts+1; setAttempts(n); setPwd("");
if(n>=MAX_ATTEMPTS) startLockout(); else setStatus("wrong");
};
return (
AURA
{unlocking?"ACESSO LIBERADO — BEM-VINDO!":status==="wrong"?"SENHA INCORRETA — TENTE NOVAMENTE":"ACESSO RESTRITO — DIGITE A SENHA"}
{unlocking&&
}
{status==="locked"?(
LIMITE DE TENTATIVAS ATINGIDO.
Tente novamente em {formatTime(remaining)}
):(
<>
{setPwd(e.target.value);setStatus("idle");}}
onKeyDown={e=>{if(e.key==="Enter")handleSubmit();}}
placeholder="••••••••••••"
style={{ width:"100%", padding:"15px 20px", fontSize:16, boxSizing:"border-box",
letterSpacing:6, color:"rgba(255,255,255,0.9)", fontFamily:FONT, ...G.input,
border:"1px solid "+(status==="wrong"?"rgba(252,165,165,0.5)":"rgba(255,255,255,0.18)") }}/>
>
)}
{status!=="locked"&&attempts>0?(MAX_ATTEMPTS-attempts)+" TENTATIVAS RESTANTES":"\u00A0"}
);
}
function ChatScreen({ onActivity }) {
const [messages, setMessages] = useState([]);
const [history, setHistory] = useState([]);
const [input, setInput] = useState("");
const [streaming, setStreaming] = useState(false);
const [displayText, setDisplayText] = useState("");
const [justDone, setJustDone] = useState(false);
const [invalidNiche, setInvalidNiche] = useState(false);
const [showInput, setShowInput] = useState(true);
const [pressedBtn, setPressedBtn] = useState(null);
const [confirmRestart, setConfirmRestart] = useState(false);
const [restarting, setRestarting] = useState(false);
const [restartFading, setRestartFading] = useState(false);
const streamBuf = useRef("");
const printerRef = useRef(null);
const scrolledUp = useRef(false);
const chatBoxRef = useRef(null);
const bottomRef = useRef(null);
const abortRef = useRef(null);
useEffect(()=>{
if(scrolledUp.current) return;
bottomRef.current?.scrollIntoView({behavior:"smooth"});
},[messages,displayText]);
const onScroll=()=>{
const el=chatBoxRef.current; if(!el) return;
scrolledUp.current = el.scrollHeight-el.scrollTop-el.clientHeight>=60;
};
const startPrinter=()=>{
if(printerRef.current) return;
printerRef.current=setInterval(()=>{
setDisplayText(p=>{
const b=streamBuf.current; if(p.length>=b.length) return p;
let e=p.length+1;
while(e{ clearInterval(printerRef.current); printerRef.current=null; };
const playOk=()=>{ try{ const ctx=new(window.AudioContext||window.webkitAudioContext)();[880,1100,1320].forEach((f,i)=>{const o=ctx.createOscillator(),g=ctx.createGain();o.connect(g);g.connect(ctx.destination);o.frequency.value=f;o.type="sine";g.gain.setValueAtTime(0,ctx.currentTime+i*0.12);g.gain.linearRampToValueAtTime(0.02,ctx.currentTime+i*0.12+0.04);g.gain.linearRampToValueAtTime(0,ctx.currentTime+i*0.12+0.18);o.start(ctx.currentTime+i*0.12);o.stop(ctx.currentTime+i*0.12+0.2);}); }catch(e){} };
const playCorrect = () => {
try {
const ctx = new (window.AudioContext || window.webkitAudioContext)();
const vol = 0.03;
[[523,0],[659,0.15],[784,0.30],[1047,0.48]].forEach(([f,t]) => {
const o = ctx.createOscillator(), g = ctx.createGain();
o.connect(g); g.connect(ctx.destination);
o.frequency.value = f; o.type = "sine";
g.gain.setValueAtTime(0, ctx.currentTime + t);
g.gain.linearRampToValueAtTime(vol, ctx.currentTime + t + 0.04);
g.gain.linearRampToValueAtTime(0, ctx.currentTime + t + 0.22);
o.start(ctx.currentTime + t); o.stop(ctx.currentTime + t + 0.25);
});
} catch(e) {}
};
const doRestart = () => {
setConfirmRestart(false);
setRestarting(true);
setRestartFading(false);
if(abortRef.current) abortRef.current.abort();
setTimeout(() => {
// start fade-out
setRestartFading(true);
setTimeout(() => {
stopPrinter();
streamBuf.current = "";
setMessages([]);
setHistory([]);
setInput("");
setDisplayText("");
setStreaming(false);
setShowInput(true);
setRestarting(false);
setRestartFading(false);
playCorrect();
}, 900);
}, 9100);
};
const playNo=()=>{ try{ const ctx=new(window.AudioContext||window.webkitAudioContext)();[300,220].forEach((f,i)=>{const o=ctx.createOscillator(),g=ctx.createGain();o.connect(g);g.connect(ctx.destination);o.frequency.value=f;o.type="sawtooth";g.gain.setValueAtTime(0,ctx.currentTime+i*0.18);g.gain.linearRampToValueAtTime(0.012,ctx.currentTime+i*0.18+0.03);g.gain.linearRampToValueAtTime(0,ctx.currentTime+i*0.18+0.18);o.start(ctx.currentTime+i*0.18);o.stop(ctx.currentTime+i*0.18+0.2);}); }catch(e){} };
const send=async(cmd)=>{
if(streaming) return;
setStreaming(true); setDisplayText(""); streamBuf.current=""; scrolledUp.current=false;
const hist=[...history,{role:"user",content:cmd}];
try{
const ctrl=new AbortController(); abortRef.current=ctrl;
const res=await fetch("https://api.anthropic.com/v1/messages",{
method:"POST", headers:{"Content-Type":"application/json"}, signal:ctrl.signal,
body:JSON.stringify({model:"claude-sonnet-4-20250514",max_tokens:15000,stream:true,system:SYSTEM_PROMPT,messages:hist}),
});
const reader=res.body.getReader(); const dec=new TextDecoder(); let full="";
startPrinter();
while(true){
const {done,value}=await reader.read(); if(done) break;
dec.decode(value,{stream:true}).split("\n").forEach(line=>{
line=line.trim(); if(!line.startsWith("data:")) return;
const js=line.slice(5).trim(); if(js==="[DONE]") return;
try{ const p=JSON.parse(js); if(p.type==="content_block_delta"&&p.delta?.text){full+=p.delta.text;streamBuf.current=full;} }catch(e){}
});
}
await new Promise(resolve=>{
const chk=setInterval(()=>setDisplayText(p=>{if(p.length>=streamBuf.current.length){clearInterval(chk);resolve();}return p;}),30);
});
stopPrinter();
const finalHist=[...hist,{role:"assistant",content:full}];
setHistory(finalHist); setDisplayText(""); setStreaming(false);
if(cmd==="..."){ setMessages([]); setHistory([]); setShowInput(true); return; }
const notNiche=full.toLowerCase().includes("isso não parece ser um nicho")||full.toLowerCase().includes("não é um nicho");
if(notNiche){ setShowInput(true); setInvalidNiche(true); playNo(); setTimeout(()=>setInvalidNiche(false),2500); }
else { playOk(); scrolledUp.current=false; }
setMessages(p=>[...p,{role:"assistant",content:full}]);
}catch(e){
if(e.name!=="AbortError"){ stopPrinter(); setDisplayText(""); setStreaming(false);
setMessages(p=>[...p,{role:"assistant",content:"❌ Erro de conexão. Tente novamente."}]); }
}
};
const sendNiche=()=>{
const t=input.trim(); if(!t||streaming) return;
onActivity?.(); setShowInput(false);
setMessages(p=>[...p,{role:"user",content:t}]); setInput(""); send(t);
};
const glassBtn=(name,accent,label)=>{
const pr=pressedBtn===name;
const C={purple:{bg:"rgba(124,58,237,0.2)",bo:"rgba(167,139,250,0.4)",co:"rgba(216,200,255,0.95)",gl:"rgba(124,58,237,0.25)"},green:{bg:"rgba(16,185,129,0.15)",bo:"rgba(52,211,153,0.35)",co:"rgba(110,231,183,0.95)",gl:"rgba(16,185,129,0.2)"},red:{bg:"rgba(220,38,38,0.12)",bo:"rgba(252,165,165,0.3)",co:"rgba(252,165,165,0.9)",gl:"rgba(220,38,38,0.18)"}};
const c=C[accent];
return(
);
};
return (
{/* Header */}
criado e desenvolvido por ocinor
Olá, sou a Aura
Seu Gerador de Ebooks Profissional
Qual é o nicho do seu produto?
{/* Messages */}
{messages.map((m,i)=>{
const isUser=m.role==="user";
return(
);
})}
{streaming&&(
)}
{/* Confirm Restart Popup */}
{confirmRestart && (
⚠️
Tem certeza?
Todo o conteúdo será apagado
)}
{/* Restarting Popup */}
{restarting && (
Reiniciando
)}
{/* Action buttons */}
{!showInput&&(
{glassBtn("more","purple","+ 10 Módulos")}
{glassBtn("finish","green","Finalizar eBook")}
)}
{/* Niche input */}
{showInput&&(
setInput(e.target.value)}
onKeyDown={e=>{if(e.key==="Enter")sendNiche();}}
placeholder="Digite o nicho do seu eBook..."
autoFocus
style={{ flex:1, background:"transparent", border:"none",
borderBottom:"1px solid rgba(255,255,255,0.18)",
padding:"10px 2px", color:"rgba(255,255,255,0.9)",
fontSize:22, fontWeight:400, letterSpacing:2,
fontFamily:FONT, textTransform:"uppercase",
transition:"border-color 0.3s", caretColor:"rgba(167,139,250,0.9)" }}/>
)}
);
}
export default function App() {
const [state, setState] = useState("lock");
const [locking, setLocking] = useState(false);
const [chatKey, setChatKey] = useState(0);
const [countdown, setCountdown] = useState(SESSION_TIMEOUT/1000);
const sessRef = useRef(null);
const countRef = useRef(null);
const clearTimers=()=>{ clearTimeout(sessRef.current); clearInterval(countRef.current); };
const startSession=()=>{
clearTimers(); setCountdown(SESSION_TIMEOUT/1000);
countRef.current=setInterval(()=>setCountdown(p=>p>0?p-1:0),1000);
sessRef.current=setTimeout(()=>{
clearTimers(); setLocking(true);
setTimeout(()=>{ setLocking(false); setState("lock"); setChatKey(k=>k+1); setCountdown(SESSION_TIMEOUT/1000); },700);
},SESSION_TIMEOUT);
};
useEffect(()=>()=>clearTimers(),[]);
const handleSuccess=()=>{ setState("unlocking"); setTimeout(()=>{ setState("chat"); startSession(); },1800); };
return (
{state!=="chat"&&(
)}
{state==="chat"&&(
{countdown<=5?"BLOQUEANDO...":formatCountdown(countdown)}
Tempo de Sessão
)}
);
}