Claude Sonnet 4.6 (max)
AnthropicFebruary 2026
What it wrote
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Quantum Singularity</title>
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Share+Tech+Mono&family=Rajdhani:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{
--void:#030408;
--deep:#060a12;
--surface:#0c1120;
--surface2:#101828;
--surface3:#161f30;
--border:rgba(96,165,250,.1);
--border2:rgba(168,85,247,.18);
--purple:#a855f7;
--purple-dim:rgba(168,85,247,.5);
--blue:#60a5fa;
--cyan:#22d3ee;
--gold:#fbbf24;
--green:#34d399;
--red:#f87171;
--text:#dde4f0;
--muted:#47586e;
--font-d:'Orbitron',monospace;
--font-m:'Share Tech Mono',monospace;
--font-b:'Rajdhani',sans-serif;
}
html,body{width:100%;height:100%;overflow:hidden;background:var(--void);color:var(--text);font-family:var(--font-b);-webkit-font-smoothing:antialiased}
/* ── Starfield ── */
#sf{position:fixed;inset:0;z-index:0;pointer-events:none}
/* ── App shell ── */
#app{position:relative;z-index:1;display:flex;flex-direction:column;height:100vh;overflow:hidden}
/* ── Header ── */
header{
flex-shrink:0;height:50px;
display:flex;align-items:center;justify-content:space-between;
padding:0 18px;
background:linear-gradient(90deg,rgba(168,85,247,.07),rgba(6,10,18,.96),rgba(96,165,250,.07));
border-bottom:1px solid var(--border2);
backdrop-filter:blur(8px);
}
.h-title{display:flex;align-items:center;gap:9px}
.h-dot{width:7px;height:7px;border-radius:50%;background:var(--cyan);box-shadow:0 0 8px var(--cyan);animation:blink 2s ease-in-out infinite}
@keyframes blink{0%,100%{opacity:1}50%{opacity:.25}}
h1{
font-family:var(--font-d);font-size:.95rem;font-weight:900;letter-spacing:3px;text-transform:uppercase;
background:linear-gradient(90deg,var(--purple),var(--blue),var(--cyan));
-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;
}
.h-right{display:flex;align-items:center;gap:12px}
.save-lbl{font-family:var(--font-m);font-size:.6rem;color:var(--muted)}
#prestige-btn{
font-family:var(--font-d);font-size:.55rem;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;
padding:7px 16px;
background:linear-gradient(135deg,rgba(124,58,237,.2),rgba(79,70,229,.2));
border:1px solid rgba(168,85,247,.35);color:var(--purple);border-radius:4px;cursor:pointer;
transition:all .2s;position:relative;overflow:hidden;
}
#prestige-btn:not(:disabled):hover{border-color:var(--purple);color:#fff;box-shadow:0 0 22px rgba(168,85,247,.45),inset 0 0 20px rgba(168,85,247,.08);transform:translateY(-1px)}
#prestige-btn:disabled{opacity:.3;cursor:not-allowed}
/* ── Main 3-col ── */
#main{flex:1;display:grid;grid-template-columns:228px 1fr 268px;overflow:hidden;min-height:0}
/* ── Panels ── */
.panel{display:flex;flex-direction:column;overflow:hidden;border-right:1px solid var(--border);background:linear-gradient(180deg,rgba(12,17,32,.98),rgba(6,10,18,.98))}
.panel:last-child{border-right:none;border-left:1px solid var(--border)}
.p-scroll{flex:1;overflow-y:auto;overflow-x:hidden}
.p-scroll::-webkit-scrollbar{width:3px}
.p-scroll::-webkit-scrollbar-thumb{background:var(--border2);border-radius:2px}
.p-head{
flex-shrink:0;padding:7px 13px;
font-family:var(--font-d);font-size:.52rem;font-weight:700;letter-spacing:3px;text-transform:uppercase;color:var(--muted);
border-bottom:1px solid var(--border);background:rgba(21,30,46,.7);
}
/* ── Resource tiers ── */
.r-tier{
display:flex;align-items:center;justify-content:space-between;
padding:6px 13px;border-bottom:1px solid rgba(96,165,250,.05);
opacity:0;transform:translateX(-12px);transition:opacity .45s,transform .45s,background .15s;
}
.r-tier.vis{opacity:1;transform:translateX(0)}
.r-tier:hover{background:rgba(96,165,250,.04)}
.r-left{display:flex;align-items:center;gap:8px}
.r-ico{font-size:1.05rem;width:22px;text-align:center}
.r-name{font-size:.68rem;font-weight:600;letter-spacing:.5px;color:var(--muted);text-transform:uppercase}
.r-right{text-align:right}
.r-val{font-family:var(--font-m);font-size:.82rem;color:var(--text)}
.r-rate{font-family:var(--font-m);font-size:.62rem;color:var(--cyan)}
/* ── Essence block ── */
.ess-block{
margin:8px 11px;padding:9px 12px;
background:linear-gradient(135deg,rgba(251,191,36,.07),rgba(168,85,247,.07));
border:1px solid rgba(251,191,36,.2);border-radius:6px;
}
.ess-lbl{font-family:var(--font-d);font-size:.5rem;letter-spacing:2px;color:var(--gold);text-transform:uppercase;margin-bottom:2px}
.ess-val{font-family:var(--font-m);font-size:1.05rem;color:var(--gold);text-shadow:0 0 12px rgba(251,191,36,.45)}
.ess-bonus{font-size:.62rem;color:var(--muted);margin-top:1px}
/* ── Stats ── */
.stats-blk{padding:9px 13px;border-bottom:1px solid var(--border)}
.stat-row{display:flex;justify-content:space-between;align-items:baseline;padding:2px 0}
.stat-lbl{font-size:.66rem;color:var(--muted);font-weight:500}
.stat-v{font-family:var(--font-m);font-size:.7rem;color:var(--blue)}
/* ── Center panel ── */
#ctr{
display:flex;flex-direction:column;align-items:center;justify-content:center;gap:22px;
position:relative;overflow:hidden;
background:radial-gradient(ellipse at 50% 38%,rgba(168,85,247,.06),transparent 65%);
}
#ctr::before{
content:'';position:absolute;width:420px;height:420px;border-radius:50%;pointer-events:none;
background:radial-gradient(circle,rgba(168,85,247,.04),transparent 70%);
animation:amb 9s ease-in-out infinite alternate;
}
@keyframes amb{0%{transform:scale(.85) translate(-20px,15px)}100%{transform:scale(1.15) translate(20px,-15px)}}
/* ── Singularity button ── */
.s-wrap{position:relative;display:flex;align-items:center;justify-content:center;width:240px;height:240px}
.halo1{
position:absolute;inset:-7px;border-radius:50%;
background:conic-gradient(from 0deg,transparent 0deg,rgba(168,85,247,.85) 45deg,transparent 85deg,rgba(96,165,250,.85) 145deg,transparent 185deg,rgba(34,211,238,.85) 245deg,transparent 285deg,rgba(168,85,247,.5) 345deg,transparent);
animation:spin 2.8s linear infinite;
-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 2.5px),#fff calc(100% - 1.5px));
mask:radial-gradient(farthest-side,transparent calc(100% - 2.5px),#fff calc(100% - 1.5px));
}
.halo2{
position:absolute;inset:-15px;border-radius:50%;
background:conic-gradient(from 180deg,transparent,rgba(34,211,238,.45) 70deg,transparent 130deg,rgba(251,191,36,.3) 200deg,transparent 260deg,rgba(96,165,250,.4) 330deg,transparent);
animation:spin 4.5s linear infinite reverse;
-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 1.5px),#fff calc(100% - .5px));
mask:radial-gradient(farthest-side,transparent calc(100% - 1.5px),#fff calc(100% - .5px));
}
@keyframes spin{from{transform:rotate(0)}to{transform:rotate(360deg)}}
#sbtn{
width:180px;height:180px;border-radius:50%;
border:2px solid rgba(168,85,247,.28);cursor:pointer;
position:relative;overflow:hidden;
background:radial-gradient(circle at 37% 34%,rgba(185,105,255,.75),transparent 44%),
radial-gradient(circle at 64% 66%,rgba(55,25,140,.65),transparent 44%),
radial-gradient(circle at 50% 50%,#100422 30%,#070b1c 100%);
box-shadow:0 0 28px rgba(168,85,247,.55),0 0 60px rgba(168,85,247,.22),0 0 100px rgba(168,85,247,.1),
inset 0 0 30px rgba(0,0,0,.65),inset 0 0 60px rgba(168,85,247,.08);
transition:transform .12s cubic-bezier(.34,1.56,.64,1),box-shadow .2s;
user-select:none;-webkit-user-select:none;
}
#sbtn::before{
content:'';position:absolute;inset:0;border-radius:50%;
background:conic-gradient(from 0deg at 50% 50%,transparent,rgba(168,85,247,.1) 90deg,transparent 180deg,rgba(96,165,250,.07) 270deg,transparent);
animation:spin 7s linear infinite;
}
#sbtn::after{
content:'';position:absolute;inset:0;border-radius:50%;
background:radial-gradient(circle at 50% 0%,rgba(255,255,255,.06),transparent 50%);
}
#sbtn:hover{
box-shadow:0 0 40px rgba(168,85,247,.75),0 0 80px rgba(168,85,247,.38),0 0 120px rgba(168,85,247,.18),
inset 0 0 40px rgba(168,85,247,.14);
}
#sbtn:active{transform:scale(.94)}
.btn-c{
position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
height:100%;gap:3px;pointer-events:none;
}
.btn-em{
font-size:2.7rem;
filter:drop-shadow(0 0 14px rgba(168,85,247,.9)) drop-shadow(0 0 28px rgba(168,85,247,.4));
animation:flt 3.2s ease-in-out infinite;
}
@keyframes flt{0%,100%{transform:translateY(0) scale(1)}50%{transform:translateY(-5px) scale(1.05)}}
.btn-lbl{font-family:var(--font-d);font-size:.48rem;font-weight:900;letter-spacing:4px;text-transform:uppercase;color:rgba(255,255,255,.92);text-shadow:0 0 10px rgba(168,85,247,.8)}
.btn-pw{font-family:var(--font-m);font-size:.65rem;color:var(--cyan);text-shadow:0 0 8px rgba(34,211,238,.5)}
/* Click fx layer */
.fx{position:absolute;inset:0;pointer-events:none;overflow:visible}
/* ── Production info ── */
.prod-info{text-align:center}
.prod-qps{font-family:var(--font-m);font-size:1.45rem;color:var(--cyan);text-shadow:0 0 14px rgba(34,211,238,.45);line-height:1}
.prod-lbl{font-size:.6rem;color:var(--muted);letter-spacing:2px;text-transform:uppercase;margin-top:2px;font-weight:600}
/* ── Milestone ── */
.ms-wrap{width:256px}
.ms-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:5px}
.ms-name{font-family:var(--font-d);font-size:.52rem;color:var(--muted);letter-spacing:1.5px;text-transform:uppercase}
.ms-pct{font-family:var(--font-m);font-size:.65rem;color:var(--purple)}
.ms-track{height:3px;background:rgba(255,255,255,.06);border-radius:2px;overflow:hidden}
.ms-fill{height:100%;background:linear-gradient(90deg,var(--purple),var(--cyan));border-radius:2px;transition:width .5s ease;box-shadow:0 0 8px rgba(168,85,247,.55)}
/* ── Buy toggle ── */
.buy-tog{display:flex;gap:4px;padding:7px 10px;background:rgba(21,30,46,.45);border-bottom:1px solid var(--border);flex-shrink:0}
.buy-btn{
flex:1;padding:4px 0;font-family:var(--font-d);font-size:.48rem;font-weight:700;letter-spacing:1px;
color:var(--muted);background:transparent;border:1px solid var(--border);border-radius:3px;
cursor:pointer;transition:all .15s;text-transform:uppercase;
}
.buy-btn:hover{color:var(--text);border-color:rgba(96,165,250,.3)}
.buy-btn.act{background:rgba(168,85,247,.15);border-color:var(--purple);color:var(--purple)}
/* ── Generator card ── */
.gen{
padding:10px 13px;border-bottom:1px solid rgba(96,165,250,.05);
cursor:pointer;transition:background .15s;position:relative;
}
.gen:hover:not(.gen-lock){background:rgba(168,85,247,.055)}
.gen.gen-lock{opacity:.28;cursor:not-allowed}
.gen.gen-aff{background:rgba(168,85,247,.04)}
.gen.gen-aff::before{content:'';position:absolute;left:0;top:0;bottom:0;width:2px;background:var(--purple);box-shadow:0 0 8px rgba(168,85,247,.6)}
.gen-top{display:flex;justify-content:space-between;align-items:center;margin-bottom:3px}
.gen-lft{display:flex;align-items:center;gap:6px}
.gen-ico{font-size:.95rem}
.gen-nm{font-size:.77rem;font-weight:600;letter-spacing:.3px}
.gen-cnt{font-family:var(--font-m);font-size:.88rem;font-weight:700;color:var(--purple);min-width:26px;text-align:right}
.gen-dsc{font-size:.6rem;color:var(--muted);margin-bottom:4px}
.gen-bot{display:flex;justify-content:space-between;align-items:center}
.gen-cost{font-family:var(--font-m);font-size:.68rem;color:var(--gold)}
.gen-cost.aff{color:var(--green)}
.gen-prod{font-family:var(--font-m);font-size:.6rem;color:var(--cyan)}
/* ── Bottom ── */
#bot{flex-shrink:0;height:220px;border-top:1px solid var(--border2);display:flex;flex-direction:column;background:linear-gradient(180deg,rgba(12,17,32,.98),rgba(6,10,18,.99))}
.tab-bar{display:flex;border-bottom:1px solid var(--border);flex-shrink:0;background:rgba(21,30,46,.55)}
.tab-btn{
padding:8px 18px;font-family:var(--font-d);font-size:.5rem;font-weight:700;letter-spacing:2px;text-transform:uppercase;
color:var(--muted);background:none;border:none;border-bottom:2px solid transparent;cursor:pointer;transition:all .2s;
}
.tab-btn:hover:not(.act){color:var(--text)}
.tab-btn.act{color:var(--purple);border-bottom-color:var(--purple)}
.tab-pane{display:none;flex:1;overflow-y:auto;overflow-x:hidden;padding:10px 13px;gap:8px;flex-wrap:wrap;align-content:flex-start}
.tab-pane::-webkit-scrollbar{width:3px}
.tab-pane::-webkit-scrollbar-thumb{background:var(--border2);border-radius:2px}
.tab-pane.act{display:flex}
.tab-empty{color:var(--muted);font-size:.75rem;padding:8px;font-style:italic}
/* ── Upgrade card ── */
.up-card{
width:148px;flex-shrink:0;background:var(--surface2);border:1px solid var(--border);
border-radius:6px;padding:9px;cursor:pointer;transition:all .18s;
}
.up-card:hover:not(.up-b):not(.up-l){border-color:var(--purple);box-shadow:0 0 14px rgba(168,85,247,.35);transform:translateY(-2px)}
.up-card.up-b{opacity:.5;cursor:default;border-color:rgba(52,211,153,.2);background:rgba(52,211,153,.03)}
.up-card.up-l{opacity:.22;cursor:not-allowed;filter:grayscale(.8)}
.up-card.up-aff{border-color:rgba(168,85,247,.38);background:rgba(168,85,247,.04)}
.up-ico{font-size:1.35rem;margin-bottom:3px}
.up-nm{font-size:.7rem;font-weight:700;margin-bottom:2px}
.up-dsc{font-size:.6rem;color:var(--muted);line-height:1.3;margin-bottom:5px}
.up-cost{font-family:var(--font-m);font-size:.66rem;color:var(--gold)}
.up-card.up-b .up-cost{color:var(--green)}
/* ── Achievement card ── */
.ach-card{
width:148px;flex-shrink:0;background:var(--surface2);border:1px solid var(--border);
border-radius:6px;padding:9px;
}
.ach-card.ach-u{border-color:rgba(251,191,36,.22);background:rgba(251,191,36,.03)}
.ach-card.ach-l{opacity:.3;filter:grayscale(.7)}
.ach-ico{font-size:1.35rem;margin-bottom:3px}
.ach-nm{font-size:.7rem;font-weight:700;margin-bottom:2px}
.ach-dsc{font-size:.6rem;color:var(--muted);line-height:1.3}
/* ── Prestige shop card ── */
.pu-card{
width:178px;flex-shrink:0;background:var(--surface2);border:1px solid rgba(251,191,36,.14);
border-radius:6px;padding:9px;cursor:pointer;transition:all .18s;
}
.pu-card:hover:not(.pu-b):not(.pu-l){border-color:var(--gold);box-shadow:0 0 14px rgba(251,191,36,.3);transform:translateY(-2px)}
.pu-card.pu-b{opacity:.48;cursor:default;border-color:rgba(52,211,153,.18)}
.pu-card.pu-l{opacity:.22;cursor:not-allowed;filter:grayscale(.7)}
.pu-ico{font-size:1.35rem;margin-bottom:3px}
.pu-nm{font-size:.7rem;font-weight:700;margin-bottom:2px}
.pu-dsc{font-size:.6rem;color:var(--muted);line-height:1.3;margin-bottom:5px}
.pu-cost{font-family:var(--font-m);font-size:.66rem;color:var(--gold)}
.pu-card.pu-b .pu-cost{color:var(--green)}
/* ── Notification ── */
#notif{
position:fixed;bottom:234px;right:18px;width:255px;
background:linear-gradient(135deg,rgba(12,17,32,.97),rgba(21,30,46,.97));
border:1px solid var(--border2);border-left:3px solid var(--purple);
border-radius:8px;padding:11px 13px;z-index:999;
transform:translateX(125%);transition:transform .38s cubic-bezier(.34,1.56,.64,1);
box-shadow:0 8px 30px rgba(0,0,0,.55),0 0 20px rgba(168,85,247,.2);
pointer-events:none;
}
#notif.show{transform:translateX(0)}
.n-head{font-family:var(--font-d);font-size:.52rem;letter-spacing:2px;color:var(--purple);text-transform:uppercase;margin-bottom:3px}
.n-body{font-size:.8rem;font-weight:500}
/* ── Prestige modal ── */
#p-modal{display:none;position:fixed;inset:0;background:rgba(3,4,8,.88);z-index:2000;align-items:center;justify-content:center;backdrop-filter:blur(5px)}
#p-modal.show{display:flex}
.m-box{
background:linear-gradient(155deg,rgba(12,17,32,.99),rgba(6,10,18,.99));
border:1px solid var(--border2);border-radius:14px;padding:30px 34px;
max-width:400px;width:90%;
box-shadow:0 0 80px rgba(168,85,247,.22),0 30px 60px rgba(0,0,0,.85);
text-align:center;position:relative;overflow:hidden;
}
.m-box::before{content:'';position:absolute;inset:0;background:radial-gradient(ellipse at 50% 0%,rgba(168,85,247,.07),transparent 60%);pointer-events:none}
.m-title{font-family:var(--font-d);font-size:1.35rem;font-weight:900;letter-spacing:3px;text-transform:uppercase;background:linear-gradient(90deg,var(--gold),var(--purple));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;margin-bottom:11px}
.m-desc{font-size:.83rem;color:var(--muted);line-height:1.65;margin-bottom:18px}
.m-gain{background:rgba(251,191,36,.07);border:1px solid rgba(251,191,36,.22);border-radius:7px;padding:13px;margin-bottom:20px}
.m-glbl{font-family:var(--font-d);font-size:.5rem;letter-spacing:2px;color:var(--muted);text-transform:uppercase;margin-bottom:3px}
.m-gval{font-family:var(--font-m);font-size:1.55rem;color:var(--gold);text-shadow:0 0 18px rgba(251,191,36,.45)}
.m-btns{display:flex;gap:11px;justify-content:center}
.m-btn{padding:9px 26px;border-radius:5px;border:none;font-family:var(--font-d);font-size:.58rem;font-weight:700;letter-spacing:2px;text-transform:uppercase;cursor:pointer;transition:all .2s}
.m-btn.cancel{background:var(--surface2);border:1px solid var(--border);color:var(--muted)}
.m-btn.cancel:hover{color:var(--text);border-color:var(--muted)}
.m-btn.confirm{background:linear-gradient(135deg,rgba(124,58,237,.8),rgba(79,70,229,.8));border:1px solid var(--purple);color:#fff;box-shadow:0 0 18px rgba(168,85,247,.4)}
.m-btn.confirm:hover{transform:translateY(-2px);box-shadow:0 0 28px rgba(168,85,247,.6),0 8px 20px rgba(0,0,0,.4)}
/* ── Click effects ── */
.float-n{position:absolute;font-family:var(--font-m);font-size:.82rem;font-weight:bold;color:var(--cyan);text-shadow:0 0 10px rgba(34,211,238,.5);pointer-events:none;animation:fltUp 1s ease-out forwards;z-index:100;white-space:nowrap}
@keyframes fltUp{0%{opacity:1;transform:translateY(0) scale(1)}30%{opacity:1;transform:translateY(-22px) scale(1.12)}100%{opacity:0;transform:translateY(-65px) scale(.85)}}
.click-p{position:absolute;width:4px;height:4px;border-radius:50%;pointer-events:none;animation:pfly .7s ease-out forwards}
@keyframes pfly{0%{opacity:1;transform:translate(0,0) scale(1)}100%{opacity:0;transform:translate(var(--dx),var(--dy)) scale(.1)}}
.p-ring{position:absolute;border-radius:50%;border:1.5px solid rgba(168,85,247,.55);pointer-events:none;animation:rexp .85s ease-out forwards}
@keyframes rexp{0%{width:60px;height:60px;margin-left:-30px;margin-top:-30px;opacity:.9}100%{width:260px;height:260px;margin-left:-130px;margin-top:-130px;opacity:0}}
</style>
</head>
<body>
<canvas id="sf"></canvas>
<div id="app">
<header>
<div class="h-title">
<div class="h-dot"></div>
<h1>Quantum Singularity</h1>
</div>
<div class="h-right">
<span class="save-lbl" id="save-lbl">AUTOSAVE ON</span>
<button id="prestige-btn" disabled>💥 BIG BANG</button>
</div>
</header>
<div id="main">
<!-- LEFT: Resources -->
<div class="panel">
<div class="p-head">Quantum State</div>
<div class="p-scroll">
<div id="ess-blk" class="ess-block" style="display:none">
<div class="ess-lbl">✨ Cosmic Essence</div>
<div class="ess-val" id="ess-val">0</div>
<div class="ess-bonus" id="ess-bonus">+0% all production</div>
</div>
<div id="r-tiers"></div>
<div class="stats-blk">
<div class="stat-row"><span class="stat-lbl">Total Produced</span><span class="stat-v" id="s-total">0</span></div>
<div class="stat-row"><span class="stat-lbl">Click Power</span><span class="stat-v" id="s-click">1</span></div>
<div class="stat-row"><span class="stat-lbl">Production/s</span><span class="stat-v" id="s-qps">0</span></div>
<div class="stat-row"><span class="stat-lbl">Big Bangs</span><span class="stat-v" id="s-prestige">0</span></div>
<div class="stat-row"><span class="stat-lbl">Total Clicks</span><span class="stat-v" id="s-clicks">0</span></div>
</div>
</div>
</div>
<!-- CENTER: Singularity -->
<div id="ctr">
<div class="s-wrap" id="s-wrap">
<div class="halo2"></div>
<div class="halo1"></div>
<button id="sbtn">
<div class="btn-c">
<div class="btn-em">🌀</div>
<div class="btn-lbl">Singularity</div>
<div class="btn-pw" id="btn-pw">+1 quark</div>
</div>
</button>
<div class="fx" id="fx"></div>
</div>
<div class="prod-info">
<div class="prod-qps" id="c-qps">0</div>
<div class="prod-lbl">quarks per second</div>
</div>
<div class="ms-wrap">
<div class="ms-head">
<span class="ms-name" id="ms-name">Next milestone</span>
<span class="ms-pct" id="ms-pct">0%</span>
</div>
<div class="ms-track"><div class="ms-fill" id="ms-fill" style="width:0%"></div></div>
</div>
</div>
<!-- RIGHT: Generators -->
<div class="panel">
<div class="p-head">Generators</div>
<div class="buy-tog">
<button class="buy-btn act" data-n="1">×1</button>
<button class="buy-btn" data-n="10">×10</button>
<button class="buy-btn" data-n="100">×100</button>
<button class="buy-btn" data-n="max">Max</button>
</div>
<div class="p-scroll" id="gen-list"></div>
</div>
</div>
<!-- BOTTOM TABS -->
<div id="bot">
<div class="tab-bar">
<button class="tab-btn act" data-tab="upgrades">Upgrades</button>
<button class="tab-btn" data-tab="achievements">Achievements</button>
<button class="tab-btn" data-tab="prestige-shop">Prestige Shop</button>
</div>
<div class="tab-pane act" id="tab-upgrades"></div>
<div class="tab-pane" id="tab-achievements"></div>
<div class="tab-pane" id="tab-prestige-shop"></div>
</div>
</div>
<div id="notif">
<div class="n-head" id="n-head">Achievement</div>
<div class="n-body" id="n-body">Message</div>
</div>
<div id="p-modal">
<div class="m-box">
<div class="m-title">💥 Big Bang</div>
<div class="m-desc">
Collapse this universe and ignite a new one.<br>
Your quarks and generators reset — but you gain permanent <strong style="color:var(--gold)">Cosmic Essence</strong>.
</div>
<div class="m-gain">
<div class="m-glbl">You will receive</div>
<div class="m-gval" id="m-gval">+0 ✨</div>
</div>
<div class="m-btns">
<button class="m-btn cancel" id="m-cancel">Cancel</button>
<button class="m-btn confirm" id="m-confirm">Ignite! 💥</button>
</div>
</div>
</div>
<script>
// ════════════════════════════════════════════════════════
// DATA
// ════════════════════════════════════════════════════════
const TIERS = [
{name:'Quarks', icon:'⚛️', th:0 },
{name:'Particles', icon:'💫', th:1e3 },
{name:'Atoms', icon:'🔬', th:1e6 },
{name:'Molecules', icon:'🧬', th:1e9 },
{name:'Stars', icon:'⭐', th:1e12 },
{name:'Planets', icon:'🪐', th:1e15 },
{name:'Galaxies', icon:'🌌', th:1e18 },
{name:'Universes', icon:'🌐', th:1e21 },
];
const GENS = [
{id:'osc', name:'Quark Oscillator', icon:'🌀', desc:'Vibrates quantum foam', bc:10, bp:0.1, m:1.15},
{id:'lens', name:'Particle Lens', icon:'⚡', desc:'Focuses quantum fields', bc:100, bp:0.5, m:1.15},
{id:'reac', name:'Fusion Reactor', icon:'🔥', desc:'Fuses particles into energy', bc:1100, bp:4, m:1.15},
{id:'weav', name:'Molecular Weaver', icon:'🕸️', desc:'Weaves quantum threads', bc:12000, bp:30, m:1.15},
{id:'star', name:'Stellar Forge', icon:'⭐', desc:'Ignites stellar cores', bc:130000, bp:250, m:1.15},
{id:'plan', name:'Planetary Engine', icon:'🪐', desc:'Spins worlds into being', bc:1.4e6, bp:2000, m:1.15},
{id:'gal', name:'Galactic Weaver', icon:'🌌', desc:'Knits galaxies together', bc:2e7, bp:16000, m:1.15},
{id:'cos', name:'Cosmic Engine', icon:'🌐', desc:'Breathes life into universes', bc:3.3e8, bp:130000, m:1.15},
];
const UPGRADES = [
// click
{id:'c1',icon:'👆',name:'Better Fingers', desc:'Click power ×2', cost:50, eff:{t:'click',x:2}, req:{tq:25} },
{id:'c2',icon:'✨',name:'Quantum Touch', desc:'Click power ×5', cost:500, eff:{t:'click',x:5}, req:{tq:200} },
{id:'c3',icon:'💥',name:'Dimensional Strike', desc:'Click power ×10', cost:50000, eff:{t:'click',x:10}, req:{tq:10000} },
{id:'c4',icon:'🔱',name:'Reality Fracture', desc:'Click power ×20', cost:5e6, eff:{t:'click',x:20}, req:{tq:1e6} },
{id:'c5',icon:'👊',name:'Cosmic Fist', desc:'Click power ×50', cost:5e9, eff:{t:'click',x:50}, req:{tq:1e9} },
// per-gen
{id:'g1',icon:'〰️',name:'Fast Vibration', desc:'Oscillators ×2', cost:200, eff:{t:'gen',id:'osc', x:2}, req:{gen:{osc:5}} },
{id:'g2',icon:'📡',name:'Resonance Amp', desc:'Oscillators ×3', cost:2000, eff:{t:'gen',id:'osc', x:3}, req:{gen:{osc:10}} },
{id:'g3',icon:'🔊',name:'Quantum Resonance', desc:'Oscillators ×5', cost:200000,eff:{t:'gen',id:'osc', x:5}, req:{gen:{osc:25}} },
{id:'g4',icon:'🔭',name:'Lens Polish', desc:'Lenses ×2', cost:2000, eff:{t:'gen',id:'lens',x:2}, req:{gen:{lens:5}} },
{id:'g5',icon:'🎯',name:'Focus Beam', desc:'Lenses ×3', cost:20000, eff:{t:'gen',id:'lens',x:3}, req:{gen:{lens:10}}},
{id:'g6',icon:'💫',name:'Quantum Focus', desc:'Lenses ×5', cost:2e6, eff:{t:'gen',id:'lens',x:5}, req:{gen:{lens:25}}},
{id:'g7',icon:'♨️',name:'Plasma Temp+', desc:'Reactors ×2', cost:20000, eff:{t:'gen',id:'reac',x:2}, req:{gen:{reac:5}} },
{id:'g8',icon:'🔥',name:'Fusion Mastery', desc:'Reactors ×3', cost:200000,eff:{t:'gen',id:'reac',x:3}, req:{gen:{reac:10}}},
{id:'g9',icon:'☢️',name:'Core Ignition', desc:'Reactors ×5', cost:2e7, eff:{t:'gen',id:'reac',x:5}, req:{gen:{reac:25}}},
{id:'ga',icon:'🕸️',name:'Silken Threads', desc:'Weavers ×2', cost:200000,eff:{t:'gen',id:'weav',x:2}, req:{gen:{weav:5}} },
{id:'gb',icon:'🧵',name:'Weave Mastery', desc:'Weavers ×5', cost:2e7, eff:{t:'gen',id:'weav',x:5}, req:{gen:{weav:15}}},
{id:'gc',icon:'✨',name:'Brighter Stars', desc:'Stellar ×2', cost:2e6, eff:{t:'gen',id:'star',x:2}, req:{gen:{star:5}} },
{id:'gd',icon:'💫',name:'Supernova', desc:'Stellar ×5', cost:2e8, eff:{t:'gen',id:'star',x:5}, req:{gen:{star:15}}},
// global
{id:'gl1',icon:'⬛',name:'Dark Matter', desc:'All generators ×2', cost:1e7, eff:{t:'global',x:2}, req:{tq:5e6} },
{id:'gl2',icon:'🌑',name:'Dark Energy', desc:'All generators ×5', cost:1e10, eff:{t:'global',x:5}, req:{tq:5e9} },
{id:'gl3',icon:'🕳️',name:'Vacuum Energy', desc:'All generators ×10', cost:1e13, eff:{t:'global',x:10}, req:{tq:5e12}},
{id:'gl4',icon:'🌊',name:'Higgs Field', desc:'All generators ×25', cost:1e16, eff:{t:'global',x:25}, req:{tq:5e15}},
];
const ACHIEVEMENTS = [
{id:'a1', icon:'⚛️',name:'First Spark', desc:'Produce your first quark', req:{tq:1} },
{id:'a2', icon:'💫',name:'Particle Flux', desc:'Reach 1,000 total quarks', req:{tq:1e3} },
{id:'a3', icon:'🔬',name:'Atomic Age', desc:'Reach 1 million total quarks', req:{tq:1e6} },
{id:'a4', icon:'🧬',name:'Molecular Dawn', desc:'Reach 1 billion total quarks', req:{tq:1e9} },
{id:'a5', icon:'⭐',name:'Stellar Fire', desc:'Reach 1 trillion total quarks', req:{tq:1e12} },
{id:'a6', icon:'🪐',name:'Planetary Scale', desc:'Reach 1 quadrillion quarks', req:{tq:1e15} },
{id:'a7', icon:'🌌',name:'Galactic Horizon', desc:'Reach 1 quintillion quarks', req:{tq:1e18} },
{id:'a8', icon:'⚙️',name:'First Machine', desc:'Buy your first generator', req:{gt:1} },
{id:'a9', icon:'🏭',name:'Factory Floor', desc:'Own 10 generators total', req:{gt:10} },
{id:'a10',icon:'🏙️',name:'Megacomplex', desc:'Own 100 generators total', req:{gt:100} },
{id:'a11',icon:'🌞',name:'Dyson Sphere', desc:'Own 500 generators total', req:{gt:500} },
{id:'a12',icon:'👆',name:'Click Newbie', desc:'Click 100 times', req:{cl:100} },
{id:'a13',icon:'✌️',name:'Click Veteran', desc:'Click 1,000 times', req:{cl:1000} },
{id:'a14',icon:'🤚',name:'Click Master', desc:'Click 10,000 times', req:{cl:10000} },
{id:'a15',icon:'💥',name:'Big Banger', desc:'Perform your first Big Bang', req:{pr:1} },
{id:'a16',icon:'🔮',name:'Multiverse', desc:'Perform 5 Big Bangs', req:{pr:5} },
{id:'a17',icon:'✨',name:'Essence Hoarder', desc:'Collect 10 Cosmic Essence total', req:{te:10} },
{id:'a18',icon:'⚡',name:'Speed of Light', desc:'Reach 1,000 quarks/sec', req:{qps:1e3} },
{id:'a19',icon:'🚀',name:'Hyperdrive', desc:'Reach 1 million quarks/sec', req:{qps:1e6} },
{id:'a20',icon:'🌐',name:'Universe Engine', desc:'Reach 1 billion quarks/sec', req:{qps:1e9} },
];
const P_UPGRADES = [
{id:'pu1',icon:'🧠',name:'Quantum Memory', desc:'Start with 10 Oscillators each Bang', cost:1 },
{id:'pu2',icon:'🌊',name:'Residual Fields', desc:'Click power ×3 permanently', cost:2 },
{id:'pu3',icon:'⬛',name:'Dark Momentum', desc:'All generators ×2 permanently', cost:3 },
{id:'pu4',icon:'⏰',name:'Time Dilation', desc:'50% offline production efficiency', cost:5 },
{id:'pu5',icon:'🔗',name:'Entanglement', desc:'All generators ×5 permanently', cost:10},
{id:'pu6',icon:'📢',name:'Cosmic Amplifier', desc:'Click power ×10 permanently', cost:15},
{id:'pu7',icon:'🔮',name:'Parallel Worlds', desc:'All generators ×10 permanently', cost:25},
{id:'pu8',icon:'🌀',name:'Singularity Core', desc:'All production ×25', cost:50},
];
const MILESTONES = [
{name:'Particles', v:1e3 },
{name:'Atoms', v:1e6 },
{name:'Molecules', v:1e9 },
{name:'Stars', v:1e12},
{name:'Planets', v:1e15},
{name:'Galaxies', v:1e18},
{name:'Universes', v:1e21},
];
// ════════════════════════════════════════════════════════
// STATE
// ════════════════════════════════════════════════════════
let S = {
q:0, tq:0, cl:0, pr:0, ess:0, te:0,
g:{}, up:{}, ach:{}, pu:{},
lastSave: Date.now(), lastTick: Date.now(),
};
GENS.forEach(g => S.g[g.id] = 0);
let buyAmt = 1;
let qps = 0;
let frame = 0;
let lastSaveTime = Date.now();
let tierEls = [];
// ════════════════════════════════════════════════════════
// MATH
// ════════════════════════════════════════════════════════
function fmt(n) {
if (n < 0) return '-' + fmt(-n);
if (n < 1) return n < 0.01 ? '0' : n.toFixed(2);
if (n < 1e3) return Math.floor(n).toString();
if (n < 1e6) return (n/1e3).toFixed(2)+'K';
if (n < 1e9) return (n/1e6).toFixed(2)+'M';
if (n < 1e12) return (n/1e9).toFixed(2)+'B';
if (n < 1e15) return (n/1e12).toFixed(2)+'T';
if (n < 1e18) return (n/1e15).toFixed(2)+'Qa';
if (n < 1e21) return (n/1e18).toFixed(2)+'Qi';
if (n < 1e24) return (n/1e21).toFixed(2)+'Sx';
if (n < 1e27) return (n/1e24).toFixed(2)+'Sp';
return n.toExponential(2);
}
// Cost of buying 1 generator when `owned` are already owned
function costOne(g, owned) {
return Math.ceil(g.bc * Math.pow(g.m, owned));
}
// Cost of buying n generators starting from `owned`
function costN(g, owned, n) {
if (n <= 0) return 0;
const base = g.bc * Math.pow(g.m, owned);
return Math.ceil(base * (Math.pow(g.m, n) - 1) / (g.m - 1));
}
// Max affordable given current quarks
function maxAffordable(g) {
const owned = S.g[g.id];
const base = g.bc * Math.pow(g.m, owned);
if (base > S.q) return 0;
return Math.max(0, Math.floor(Math.log(S.q * (g.m - 1) / base + 1) / Math.log(g.m)));
}
function effectiveN(g) {
return buyAmt === 'max' ? maxAffordable(g) : buyAmt;
}
function clickPow() {
let p = 1;
UPGRADES.forEach(u => { if (S.up[u.id] && u.eff.t === 'click') p *= u.eff.x; });
if (S.pu['pu2']) p *= 3;
if (S.pu['pu6']) p *= 10;
return p;
}
function genMult(gid) {
let m = 1;
UPGRADES.forEach(u => {
if (!S.up[u.id]) return;
if (u.eff.t === 'gen' && u.eff.id === gid) m *= u.eff.x;
if (u.eff.t === 'global') m *= u.eff.x;
});
if (S.pu['pu3']) m *= 2;
if (S.pu['pu5']) m *= 5;
if (S.pu['pu7']) m *= 10;
if (S.pu['pu8']) m *= 25;
m *= (1 + S.ess * 0.05);
return m;
}
function calcQps() {
let t = 0;
GENS.forEach(g => { if (S.g[g.id] > 0) t += S.g[g.id] * g.bp * genMult(g.id); });
return t;
}
function genTotal() { return Object.values(S.g).reduce((a,b)=>a+b,0); }
function essGain() { return Math.floor(Math.sqrt(S.tq / 1e6)); }
function canPrestige() { return S.tq >= 1e9; }
function upReqMet(u) {
const r = u.req;
if (r.tq !== undefined && S.tq < r.tq) return false;
if (r.gen) for (const [id,n] of Object.entries(r.gen)) if ((S.g[id]||0) < n) return false;
return true;
}
// ════════════════════════════════════════════════════════
// ACTIONS
// ════════════════════════════════════════════════════════
function doClick(e) {
const p = clickPow();
S.q += p; S.tq += p; S.cl++;
spawnFx(e, p);
}
function buyGen(gid) {
const g = GENS.find(x=>x.id===gid);
if (!g) return;
const n = effectiveN(g);
if (n <= 0) return;
const cost = costN(g, S.g[g.id], n);
if (S.q < cost) return;
S.q -= cost;
S.g[g.id] += n;
}
function buyUp(uid) {
if (S.up[uid]) return;
const u = UPGRADES.find(x=>x.id===uid);
if (!u || !upReqMet(u) || S.q < u.cost) return;
S.q -= u.cost;
S.up[uid] = true;
notify('Upgrade Purchased', `${u.name}: ${u.desc}`);
}
function buyPUp(pid) {
if (S.pu[pid]) return;
const pu = P_UPGRADES.find(x=>x.id===pid);
if (!pu || S.ess < pu.cost) return;
S.ess -= pu.cost;
S.pu[pid] = true;
notify('✨ Prestige Upgrade', `${pu.name}: ${pu.desc}`);
}
function openPrestige() {
if (!canPrestige()) return;
document.getElementById('m-gval').textContent = `+${essGain()} ✨ Cosmic Essence`;
document.getElementById('p-modal').classList.add('show');
}
function doPrestige() {
const gain = essGain();
S.ess += gain; S.te += gain; S.pr++;
S.q = 0; S.tq = 0;
GENS.forEach(g => S.g[g.id] = 0);
S.up = {};
if (S.pu['pu1']) S.g['osc'] = 10;
document.getElementById('p-modal').classList.remove('show');
if (S.ess > 0) document.getElementById('ess-blk').style.display = '';
notify('💥 Big Bang!', `Universe collapsed! Gained +${gain} Cosmic Essence.`);
}
// ════════════════════════════════════════════════════════
// ACHIEVEMENTS
// ════════════════════════════════════════════════════════
function checkAch() {
ACHIEVEMENTS.forEach(a => {
if (S.ach[a.id]) return;
const r = a.req;
let met = false;
if (r.tq !== undefined && S.tq >= r.tq) met = true;
if (r.gt !== undefined && genTotal() >= r.gt) met = true;
if (r.cl !== undefined && S.cl >= r.cl) met = true;
if (r.pr !== undefined && S.pr >= r.pr) met = true;
if (r.te !== undefined && S.te >= r.te) met = true;
if (r.qps !== undefined && qps >= r.qps) met = true;
if (met) { S.ach[a.id] = true; notify(`🏆 ${a.name}`, a.desc); }
});
}
// ════════════════════════════════════════════════════════
// SAVE / LOAD
// ════════════════════════════════════════════════════════
const SK = 'qs_v3';
function save() {
try {
S.lastSave = Date.now();
localStorage.setItem(SK, JSON.stringify(S));
const d = new Date();
document.getElementById('save-lbl').textContent =
`SAVED ${d.getHours().toString().padStart(2,'0')}:${d.getMinutes().toString().padStart(2,'0')}`;
} catch(e) {}
}
function load() {
try {
const raw = localStorage.getItem(SK);
if (!raw) return;
const sv = JSON.parse(raw);
S.q = sv.q || 0;
S.tq = sv.tq || 0;
S.cl = sv.cl || 0;
S.pr = sv.pr || 0;
S.ess = sv.ess || 0;
S.te = sv.te || 0;
S.lastSave = sv.lastSave || Date.now();
if (sv.g) Object.assign(S.g, sv.g);
if (sv.up) Object.assign(S.up, sv.up);
if (sv.ach)Object.assign(S.ach,sv.ach);
if (sv.pu) Object.assign(S.pu, sv.pu);
// Offline progress
if (S.pu['pu4']) {
const secs = Math.min((Date.now() - S.lastSave) / 1000, 8*3600);
if (secs > 30) {
const earned = calcQps() * secs * 0.5;
if (earned > 0) {
S.q += earned; S.tq += earned;
setTimeout(() => notify('⏰ Offline Progress', `Gained ${fmt(earned)} quarks while away!`), 900);
}
}
}
if (S.ess > 0 || S.pr > 0) document.getElementById('ess-blk').style.display = '';
} catch(e) { console.error('Load failed', e); }
}
// ════════════════════════════════════════════════════════
// NOTIFICATIONS
// ════════════════════════════════════════════════════════
let nq = [], nActive = false;
function notify(head, body) {
nq.push({head,body});
if (!nActive) showNotif();
}
function showNotif() {
if (!nq.length) { nActive = false; return; }
nActive = true;
const {head,body} = nq.shift();
document.getElementById('n-head').textContent = head;
document.getElementById('n-body').textContent = body;
const el = document.getElementById('notif');
el.classList.add('show');
setTimeout(() => { el.classList.remove('show'); setTimeout(showNotif, 420); }, 3000);
}
// ════════════════════════════════════════════════════════
// CLICK EFFECTS
// ════════════════════════════════════════════════════════
const PCOLS = ['#a855f7','#60a5fa','#22d3ee','#34d399','#fbbf24','#f87171'];
function spawnFx(e, power) {
const wrap = document.getElementById('s-wrap');
const layer = document.getElementById('fx');
const r = wrap.getBoundingClientRect();
const cx = (e?.clientX || r.left + r.width/2) - r.left;
const cy = (e?.clientY || r.top + r.height/2) - r.top;
// Floating number
const n = document.createElement('div');
n.className = 'float-n';
n.textContent = '+' + fmt(power);
n.style.left = (cx + (Math.random()-.5)*50) + 'px';
n.style.top = (cy - 8) + 'px';
layer.appendChild(n);
setTimeout(() => n.remove(), 1050);
// Burst particles
for (let i = 0; i < 8; i++) {
const ang = (i/8)*Math.PI*2 + Math.random()*.7;
const dist = 55 + Math.random()*55;
const p = document.createElement('div');
p.className = 'click-p';
p.style.cssText = `left:${cx}px;top:${cy}px;background:${PCOLS[i%PCOLS.length]};box-shadow:0 0 5px currentColor;--dx:${Math.cos(ang)*dist}px;--dy:${Math.sin(ang)*dist}px`;
layer.appendChild(p);
setTimeout(() => p.remove(), 750);
}
// Ring
const ring = document.createElement('div');
ring.className = 'p-ring';
ring.style.left = cx + 'px';
ring.style.top = cy + 'px';
layer.appendChild(ring);
setTimeout(() => ring.remove(), 900);
}
// ════════════════════════════════════════════════════════
// STARFIELD
// ════════════════════════════════════════════════════════
function initStarfield() {
const c = document.getElementById('sf');
const ctx = c.getContext('2d');
const resize = () => { c.width = innerWidth; c.height = innerHeight; };
resize();
window.addEventListener('resize', resize);
const stars = Array.from({length:230}, () => ({
x: Math.random()*innerWidth, y: Math.random()*innerHeight,
r: Math.random()*1.5+.3,
base: Math.random()*.65+.15,
ph: Math.random()*Math.PI*2,
spd: Math.random()*.018+.003,
}));
const nebulae = [
{x:innerWidth*.2, y:innerHeight*.3, r:150, col:'rgba(168,85,247,.025)'},
{x:innerWidth*.8, y:innerHeight*.7, r:120, col:'rgba(96,165,250,.02)'},
{x:innerWidth*.6, y:innerHeight*.2, r:100, col:'rgba(34,211,238,.018)'},
{x:innerWidth*.1, y:innerHeight*.8, r:130, col:'rgba(124,58,237,.022)'},
];
(function draw() {
ctx.clearRect(0,0,c.width,c.height);
nebulae.forEach(nb => {
const grd = ctx.createRadialGradient(nb.x,nb.y,0,nb.x,nb.y,nb.r);
grd.addColorStop(0,nb.col); grd.addColorStop(1,'transparent');
ctx.fillStyle = grd;
ctx.beginPath(); ctx.arc(nb.x,nb.y,nb.r,0,Math.PI*2); ctx.fill();
});
stars.forEach(s => {
s.ph += s.spd;
const op = s.base + .22*Math.sin(s.ph);
ctx.beginPath(); ctx.arc(s.x,s.y,s.r,0,Math.PI*2);
ctx.fillStyle = `rgba(210,225,255,${op})`; ctx.fill();
});
requestAnimationFrame(draw);
})();
}
// ════════════════════════════════════════════════════════
// RENDER
// ════════════════════════════════════════════════════════
function renderResources() {
const container = document.getElementById('r-tiers');
if (tierEls.length === 0) {
TIERS.forEach((t,i) => {
const el = document.createElement('div');
el.className = 'r-tier';
el.id = 'rt'+i;
el.innerHTML = `
<div class="r-left">
<span class="r-ico">${t.icon}</span>
<span class="r-name">${t.name}</span>
</div>
<div class="r-right">
<div class="r-val" id="rv${i}">0</div>
<div class="r-rate" id="rr${i}"></div>
</div>`;
container.appendChild(el);
tierEls.push(el);
});
tierEls[0].classList.add('vis');
}
TIERS.forEach((t,i) => {
const show = i===0 || S.tq >= t.th * 0.005;
if (show && !tierEls[i].classList.contains('vis')) tierEls[i].classList.add('vis');
if (tierEls[i].classList.contains('vis')) {
const val = i===0 ? S.q : S.q / t.th;
const rate = i===0 ? qps : qps / t.th;
document.getElementById('rv'+i).textContent = fmt(val);
document.getElementById('rr'+i).textContent = qps > 0 ? `+${fmt(rate)}/s` : '';
}
});
// Essence
if (S.ess > 0 || S.pr > 0) {
document.getElementById('ess-blk').style.display = '';
document.getElementById('ess-val').textContent = fmt(S.ess) + ' ✨';
document.getElementById('ess-bonus').textContent = `+${(S.ess*5).toFixed(0)}% all production`;
}
// Stats
document.getElementById('s-total').textContent = fmt(S.tq);
document.getElementById('s-click').textContent = fmt(clickPow());
document.getElementById('s-qps').textContent = fmt(qps)+'/s';
document.getElementById('s-prestige').textContent= S.pr;
document.getElementById('s-clicks').textContent = fmt(S.cl);
}
function renderCenter() {
qps = calcQps();
document.getElementById('c-qps').textContent = fmt(qps);
const cp = clickPow();
document.getElementById('btn-pw').textContent = `+${fmt(cp)} quark${cp===1?'':'s'}`;
// Milestone
const next = MILESTONES.find(m => S.tq < m.v);
if (next) {
const idx = MILESTONES.indexOf(next);
const prev = idx > 0 ? MILESTONES[idx-1].v : 0;
const pct = Math.min(100, (S.tq - prev) / (next.v - prev) * 100);
document.getElementById('ms-name').textContent = `Next: ${next.name}`;
document.getElementById('ms-pct').textContent = pct.toFixed(1)+'%';
document.getElementById('ms-fill').style.width = pct+'%';
} else {
document.getElementById('ms-name').textContent = '🌌 All Milestones Reached!';
document.getElementById('ms-pct').textContent = '100%';
document.getElementById('ms-fill').style.width = '100%';
}
// Prestige button
const pb = document.getElementById('prestige-btn');
if (canPrestige()) {
pb.disabled = false;
pb.textContent = `💥 BIG BANG (+${essGain()} ✨)`;
} else {
pb.disabled = true;
pb.textContent = '💥 BIG BANG';
}
}
function renderGens() {
let html = '';
GENS.forEach((g,i) => {
const prev = GENS[i-1];
const vis = !prev || S.g[prev.id] > 0 || S.tq >= g.bc * 0.25;
if (!vis) return;
const cnt = S.g[g.id];
const n = effectiveN(g);
const n1 = Math.max(1, n);
const cost = n <= 0 ? costOne(g, cnt) : costN(g, cnt, n1);
const aff = n > 0 && S.q >= cost;
const pEa = g.bp * genMult(g.id);
html += `
<div class="gen ${aff?'gen-aff':''}" onclick="buyGen('${g.id}')">
<div class="gen-top">
<div class="gen-lft"><span class="gen-ico">${g.icon}</span><span class="gen-nm">${g.name}</span></div>
<span class="gen-cnt">${cnt}</span>
</div>
<div class="gen-dsc">${g.desc}</div>
<div class="gen-bot">
<span class="gen-cost ${aff?'aff':''}">×${n1} — ${fmt(cost)} ⚛️</span>
<span class="gen-prod">${cnt>0 ? fmt(cnt*pEa)+'/s' : fmt(pEa)+'/s ea.'}</span>
</div>
</div>`;
});
document.getElementById('gen-list').innerHTML = html ||
'<div class="tab-empty" style="padding:14px">Produce more quarks to reveal generators...</div>';
}
function renderUps() {
let html = '';
UPGRADES.forEach(u => {
const bought = S.up[u.id];
const met = upReqMet(u);
if (!bought && !met) return;
const aff = !bought && met && S.q >= u.cost;
let cls = 'up-card';
if (bought) cls += ' up-b';
else if (!met) cls += ' up-l';
else if (aff) cls += ' up-aff';
html += `
<div class="${cls}" onclick="buyUp('${u.id}')">
<div class="up-ico">${u.icon}</div>
<div class="up-nm">${u.name}</div>
<div class="up-dsc">${u.desc}</div>
<div class="up-cost">${bought ? '✓ Owned' : fmt(u.cost)+' ⚛️'}</div>
</div>`;
});
document.getElementById('tab-upgrades').innerHTML = html ||
'<div class="tab-empty">Produce more quarks to unlock upgrades...</div>';
}
function renderAch() {
document.getElementById('tab-achievements').innerHTML = ACHIEVEMENTS.map(a => {
const u = S.ach[a.id];
return `<div class="ach-card ${u?'ach-u':'ach-l'}">
<div class="ach-ico">${a.icon}</div>
<div class="ach-nm">${u ? a.name : '???'}</div>
<div class="ach-dsc">${u ? a.desc : 'Keep playing...'}</div>
</div>`;
}).join('');
}
function renderPShop() {
const tab = document.getElementById('tab-prestige-shop');
if (S.pr === 0) {
tab.innerHTML = '<div class="tab-empty">Perform your first Big Bang to unlock the Prestige Shop...</div>';
return;
}
tab.innerHTML = P_UPGRADES.map(pu => {
const bought = S.pu[pu.id];
const aff = !bought && S.ess >= pu.cost;
let cls = 'pu-card';
if (bought) cls += ' pu-b';
else if (!aff) cls += ' pu-l';
return `<div class="${cls}" onclick="buyPUp('${pu.id}')">
<div class="pu-ico">${pu.icon}</div>
<div class="pu-nm">${pu.name}</div>
<div class="pu-dsc">${pu.desc}</div>
<div class="pu-cost">${bought ? '✓ Owned' : pu.cost+' ✨'}</div>
</div>`;
}).join('');
}
// ════════════════════════════════════════════════════════
// GAME LOOP
// ════════════════════════════════════════════════════════
function tick() {
const now = Date.now();
const dt = Math.min((now - S.lastTick) / 1000, 1);
S.lastTick = now;
qps = calcQps();
const earned = qps * dt;
S.q += earned; S.tq += earned;
checkAch();
}
function loop() {
tick();
frame++;
renderResources();
renderCenter();
if (frame % 4 === 0) renderGens();
if (frame % 18 === 0) { renderUps(); renderAch(); renderPShop(); }
if (Date.now() - lastSaveTime > 30000) { lastSaveTime = Date.now(); save(); }
requestAnimationFrame(loop);
}
// ════════════════════════════════════════════════════════
// EVENTS
// ════════════════════════════════════════════════════════
function initEvents() {
document.getElementById('sbtn').addEventListener('click', doClick);
// Space bar to click
document.addEventListener('keydown', e => {
if (e.code === 'Space' && e.target === document.body) {
e.preventDefault();
doClick(null);
}
});
// Buy toggle
document.querySelectorAll('.buy-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.buy-btn').forEach(b => b.classList.remove('act'));
btn.classList.add('act');
buyAmt = btn.dataset.n === 'max' ? 'max' : parseInt(btn.dataset.n);
});
});
// Tabs
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('act'));
document.querySelectorAll('.tab-pane').forEach(p => p.classList.remove('act'));
btn.classList.add('act');
document.getElementById('tab-' + btn.dataset.tab).classList.add('act');
});
});
// Prestige
document.getElementById('prestige-btn').addEventListener('click', openPrestige);
document.getElementById('m-confirm').addEventListener('click', doPrestige);
document.getElementById('m-cancel').addEventListener('click', () => {
document.getElementById('p-modal').classList.remove('show');
});
// Save on exit
window.addEventListener('beforeunload', save);
}
// ════════════════════════════════════════════════════════
// INIT
// ════════════════════════════════════════════════════════
load();
initStarfield();
initEvents();
loop();
</script>
</body>
</html>