27:18Gemini 4 Hydrogen: Cheaper Tokens, More Expensive Answers?
Nov 13, 2026 · YouTube
18:40ERNIE 5.5 Flash Preview vs GLM 5.3 Flash: Baidu's new model is very impressive!
Nov 11, 2026 · YouTube
36:22Fable 5.2 robbing me blind, plus: Nex AGI's N2.6 vs GLM 5.3 Flash
Nov 11, 2026 · YouTube
14:03Gemini 4 Carbon: Can it handle my challenges? (First look with one-shot coding tests)
Nov 10, 2026 · YouTube
47:51Ranking major U.S. Open-Weights Models. (Where does Ripple 65B fit in?)
Nov 6, 2026 · YouTube
10:57"Crouton Alpha": the latest super-efficient coding model by Meta?
Nov 3, 2026 · YouTube
38:58Testing Particle-1: a post-trained DeepSeek V4.1 Flash specializing in coding and efficiency
Oct 28, 2026 · YouTube
22:14GPT-6.1 Terra Pro vs Terra: How Much Better Is Pro?
Oct 27, 2026 · YouTube
29:55Kimi K3.1 Pro Looked Incredible. Then I Kept Testing.
Oct 26, 2026 · YouTube
31:28Is this company reselling GPT Sol 6.1 at a loss (for non-agentic/text-only)?🤔 Is this sustainable?
Oct 20, 2026 · YouTube
17:58Nemotron 3.5 Super VL vs Opus 5.5: Testing NVIDIA’s new coding juggernaut
Oct 15, 2026 · YouTube
16:04Testing a *massive* new open-weights model 🤯: Muse Spark Open (vs. Nemotron, Opus 5.5, and more)
Oct 15, 2026 · YouTube
16:43Gemini 4 Argon: Great 🐈 Animation, but a broken escalator. (Coding challenge vs Opus 5.5, Sol 6.1)
Oct 13, 2026 · YouTube
16:37Meta's new "Muse Wonder" AI is impressive... but can it compete with Anthropic's models?
Oct 12, 2026 · YouTube
11:12WOW... Haiku 5.5 is very impressive. RIP OpenAI?
Oct 7, 2026 · YouTube
22:47Mistral Large 4 Is Cheap. But Is It Good Enough to Compete?
Oct 6, 2026 · YouTube
22:02Is Pareto 26.10 Preview Just Routing to GPT Sol? I Tested It Against Sol 6.1 Pro
Oct 1, 2026 · YouTube
11:22I Tested Sonnet 5.5 Against Opus 5.5. Is It Actually Cheaper?
Sep 28, 2026 · YouTube
You write simulations where the interesting behavior is supposed to come out of the dice rather than be animated by hand.
Build me a single HTML page: a Starbucks-style coffee shop running a bizarre promotion, simulated live.
data: URIs are fine.localStorage, sessionStorage, cookies or indexedDB — sandboxed frame, they throw.html block.One paragraph, before the file. Given your own timings — how long a customer stays inside holding a drink, how fast the counter serves — roughly how many customers should pass through between catastrophes? Show the working, not just the number.
The single fenced html block.
Having written it, what does the page do in its first few minutes? Name anything you tuned, special-cased or nudged. Say what it does badly — I am going to leave it running and watch the counters.
A customer enters, spends ~3 s at the counter (where the 1-in-6 roll happens), then loiters ~8 s with their drink before leaving — ~11 s total inside. With 8 seats the shop turns over ~0.73 customers/s at capacity. Each customer carries a unicorn for their 8 s loiter with probability 1/6, so each seat independently holds a unicorn ~12.5 % of the time (⅙ × 8/11). The number of simultaneous unicorns is roughly Binomial(8, 0.125): P(0)≈0.34, P(1)≈0.39, P(2)≈0.21, P(3+)≈0.06. A new “seat state” arrives every ~1.4 s (11 s / 8), so we sample this distribution ~0.7×/s. Expected time to first 3+ is 1/(0.7×0.06) ≈ 24 seconds at 1× speed. Catastrophe resets the shop (everyone flees, 2 s rebuild), adding ~2 s downtime. So: ~26 s between catastrophes at 1×, scaling inversely with the speed slider. No nudges — the 1-in-6 is rolled exactly once per drink at the counter.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>NEON UNICORN FRAPPUCCINO SIMULATOR</title>
<style>
:root{--bg:#0a0a0f;--fg:#e8e8f0;--muted:#6a6a7a;--accent:#ff00ff;--gold:#ffd700}
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;background:var(--bg);color:var(--fg);min-height:100vh;display:flex;flex-direction:column;overflow:hidden}
header{padding:12px 20px;background:linear-gradient(180deg,#151520 0%,#0a0a0f 100%);border-bottom:1px solid #222;display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:10px}
h1{font-size:1.1rem;font-weight:600;letter-spacing:0.05em;background:linear-gradient(90deg,#ff00ff,#00ffff,#ffff00,#ff00ff);background-size:300% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;animation:hue 4s linear infinite}
@keyframes hue{to{background-position:-300% 0}}
.controls{display:flex;gap:12px;align-items:center;flex-wrap:wrap}
.control-group{display:flex;align-items:center;gap:8px;font-size:0.75rem;color:var(--muted)}
input[type=range]{width:120px;accent-color:var(--accent)}
.speed-value{font-variant-numeric:tabular-nums;color:var(--accent);min-width:2.5em;text-align:right}
button{padding:6px 14px;background:transparent;border:1px solid var(--accent);color:var(--accent);border-radius:4px;cursor:pointer;font-family:inherit;font-size:0.7rem;text-transform:uppercase;letter-spacing:0.1em;transition:all 0.15s}
button:hover{background:var(--accent);color:#000}
button:active{transform:scale(0.97)}
main{flex:1;display:flex;position:relative}
#canvas{flex:1;display:block;background:var(--bg)}
#stats{width:280px;background:#0d0d14;border-left:1px solid #1a1a2e;padding:16px;overflow-y:auto;display:flex;flex-direction:column;gap:16px}
.stat-panel{background:#11111a;border:1px solid #1e1e2e;border-radius:6px;padding:12px}
.stat-panel h3{font-size:0.65rem;text-transform:uppercase;letter-spacing:0.1em;color:var(--muted);margin-bottom:10px;display:flex;justify-content:space-between}
.stat-row{display:flex;justify-content:space-between;padding:4px 0;font-size:0.8rem;border-bottom:1px solid #1a1a2e}
.stat-row:last-child{border-bottom:none}
.stat-label{color:var(--muted)}
.stat-value{font-variant-numeric:tabular-nums;color:var(--fg);text-align:right;min-width:60px}
.stat-value.unicorn{color:#ff00ff;text-shadow:0 0 8px #ff00ff}
.stat-value.catastrophe{color:#ff3300;text-shadow:0 0 8px #ff3300}
.stat-value.gold{color:#ffd700}
#event-log{flex:1;min-height:100px;font-size:0.65rem;line-height:1.6;color:var(--muted);overflow-y:auto}
.log-entry{padding:2px 0;border-bottom:1px solid #111;transition:opacity 0.5s}
.log-entry.unicorn{color:#ff00ff}
.log-entry.catastrophe{color:#ff3300;background:rgba(255,51,0,0.1)}
.log-entry.milestone{color:#ffd700}
@media(max-width:900px){main{flex-direction:column}#stats{width:100%;border-left:none;border-top:1px solid #1a1a2e;max-height:200px}header{flex-direction:column;align-items:stretch}#canvas{height:50vh}}
</style>
</head>
<body>
<header>
<h1>NEON UNICORN FRAPPUCCINO SIMULATOR</h1>
<div class="controls">
<div class="control-group"><span>SPEED</span><input type="range" id="speed" min="0.1" max="10" step="0.1" value="1"><span class="speed-value" id="speedVal">1.0×</span></div>
<button id="pauseBtn">PAUSE</button>
<button id="resetBtn">RESET</button>
</div>
</header>
<main>
<canvas id="canvas"></canvas>
<aside id="stats">
<div class="stat-panel">
<h3>THROUGHPUT</h3>
<div class="stat-row"><span class="stat-label">Customers Served</span><span class="stat-value" id="served">0</span></div>
<div class="stat-row"><span class="stat-label">Neon Unicorns</span><span class="stat-value unicorn" id="unicorns">0</span></div>
<div class="stat-row"><span class="stat-label">Observed Rate</span><span class="stat-value" id="rate">0.00%</span></div>
<div class="stat-row"><span class="stat-label">True Rate</span><span class="stat-value">16.67%</span></div>
</div>
<div class="stat-panel">
<h3>CATASTROPHES</h3>
<div class="stat-row"><span class="stat-label">Total Events</span><span class="stat-value catastrophe" id="catastrophes">0</span></div>
<div class="stat-row"><span class="stat-label">Last Event</span><span class="stat-value" id="lastEvent">—</span></div>
<div class="stat-row"><span class="stat-label">Peak Unicorns</span><span class="stat-value unicorn" id="peakUnicorns">0</span></div>
<div class="stat-row"><span class="stat-label">Shop Rebuilds</span><span class="stat-value" id="rebuilds">0</span></div>
</div>
<div class="stat-panel">
<h3>CURRENT STATE</h3>
<div class="stat-row"><span class="stat-label">Inside Shop</span><span class="stat-value" id="insideCount">0</span>/8</div>
<div class="stat-row"><span class="stat-label">Holding Unicorn</span><span class="stat-value unicorn" id="holdingCount">0</span></div>
<div class="stat-row"><span class="stat-label">Queue Length</span><span class="stat-value" id="queueCount">0</span></div>
<div class="stat-row"><span class="stat-label">Instability</span><span class="stat-value" id="instability">0%</span></div>
</div>
<div class="stat-panel">
<h3>ODDITIES</h3>
<div class="stat-row"><span class="stat-label">Barista Meltdowns</span><span class="stat-value gold" id="meltdowns">0</span></div>
<div class="stat-row"><span class="stat-label">Reality Fractures</span><span class="stat-value gold" id="fractures">0</span></div>
<div class="stat-row"><span class="stat-label">Unicorns Freed</span><span class="stat-value gold" id="freed">0</span></div>
<div class="stat-row"><span class="stat-label">Coffee Wasted (L)</span><span class="stat-value" id="wasted">0.0</span></div>
</div>
<div id="event-log"></div>
</aside>
</main>
<script>
/* ============ SIMULATION CORE ============ */
const canvas=document.getElementById('canvas'),ctx=canvas.getContext('2d');
let W=0,H=0,dpr=1;
function resize(){dpr=window.devicePixelRatio||1;W=canvas.clientWidth;H=canvas.clientHeight;canvas.width=W*dpr;canvas.height=H*dpr;ctx.scale(dpr,dpr)}
window.addEventListener('resize',resize);resize();
/* ---- Config ---- */
const CFG={
maxInside:8,
counterX:0.18, counterY:0.5,
exitX:0.92, exitY:0.5,
queueStartX:0.02, queueStartY:0.5,
queueDir:-1,
serviceTime:{min:2.5,max:4.5},
loiterTime:{min:6,max:10},
spawnInterval:{min:1.5,max:3.5},
unicornChance:1/6,
catastropheResetDelay:2.5,
rebuildTime:2
};
/* ---- State ---- */
let simTime=0,dt=0,lastFrame=0,speed=1,paused=false;
let customers=[],queue=[],nextSpawn=0,catastropheState=0,catastropheTimer=0,rebuildTimer=0;
let stats={served:0,unicorns:0,catastrophes:0,lastEvent:0,peakUnicorns:0,rebuilds:0,meltdowns:0,fractures:0,freed:0,wasted:0};
let particles=[],screenShake=0,flashIntensity=0,warpPhase=0,giantUnicorn=null,unicornParticles=[];
let rng=Math.random;
/* ---- RNG with seed for reproducibility (optional) ---- */
function rollUnicorn(){return rng()<CFG.unicornChance}
/* ---- Customer Class ---- */
class Customer{
constructor(id,isUnicorn){
this.id=id;this.isUnicorn=isUnicorn;this.state='queue';this.x=0;this.y=0;this.targetX=0;this.targetY=0;
this.speed=0.08+Math.random()*0.04;this.angle=0;this.wobble=Math.random()*Math.PI*2;
this.serviceTimer=0;this.loiterTimer=0;this.drinkOffset=0;this.color=this.pickColor();
this.hasDrink=false;this.leaving=false;
}
pickColor(){
const hues=[220,280,320,180,60,40];return`hsl(${hues[Math.floor(Math.random()*hues.length)]},70%,60%)`
}
update(d){
this.wobble+=d*3;
switch(this.state){
case 'queue':this.moveToTarget(d);if(this.atTarget())this.enterShop();break;
case 'entering':this.moveToTarget(d);if(this.atTarget())this.startService();break;
case 'ordering':this.serviceTimer-=d;if(this.serviceTimer<=0)this.receiveDrink();break;
case 'loitering':this.loiterTimer-=d;this.wander(d);if(this.loiterTimer<=0)this.startLeaving();break;
case 'leaving':this.moveToTarget(d);if(this.atTarget())this.exit();break;
}
}
moveToTarget(d){const dx=this.targetX-this.x,dy=this.targetY-this.y,dist=Math.hypot(dx,dy);if(dist>0.005){this.x+=dx/dist*this.speed*d*60;this.y+=dy/dist*this.speed*d*60}else{this.x=this.targetX;this.y=this.targetY}}
atTarget(){return Math.hypot(this.targetX-this.x,this.targetY-this.y)<0.01}
enterShop(){this.state='entering';this.targetX=CFG.counterX;this.targetY=CFG.counterY}
startService(){this.state='ordering';this.serviceTimer=CFG.serviceTime.min+Math.random()*(CFG.serviceTime.max-CFG.serviceTime.min);this.angle=0}
receiveDrink(){this.hasDrink=true;this.state='loitering';this.loiterTimer=CFG.loiterTime.min+Math.random()*(CFG.loiterTime.max-CFG.loiterTime.min);this.targetX=0.35+Math.random()*0.4;this.targetY=0.3+Math.random()*0.4;stats.served++;if(this.isUnicorn){stats.unicorns++;logEvent(`UNICORN FRAPPUCCINO served to customer #${this.id}`,'unicorn')}}
wander(d){this.angle+=d*0.5;this.targetX+=Math.cos(this.angle)*0.002*d*60;this.targetY+=Math.sin(this.angle)*0.002*d*60;this.targetX=Math.max(0.25,Math.min(0.75,this.targetX));this.targetY=Math.max(0.2,Math.min(0.8,this.targetY));this.moveToTarget(d)}
startLeaving(){this.state='leaving';this.targetX=CFG.exitX;this.targetY=CFG.exitY;this.leaving=true}
exit(){return true}
draw(){
const px=this.x*W,py=this.y*H,r=Math.max(6,W*0.018);
ctx.save();ctx.translate(px,py);
if(this.state==='loitering'||this.state==='leaving'){this.drinkOffset=Math.sin(this.wobble)*2;ctx.beginPath();ctx.arc(0,this.drinkOffset-14,4,0,Math.PI*2);if(this.isUnicorn){const g=ctx.createRadialGradient(0,this.drinkOffset-14,0,0,this.drinkOffset-14,8);g.addColorStop(0,'#fff');g.addColorStop(0.3,'#ff00ff');g.addColorStop(0.7,'#00ffff');g.addColorStop(1,'rgba(0,0,0,0)');ctx.fillStyle=g;ctx.shadowColor='#ff00ff';ctx.shadowBlur=15}else{ctx.fillStyle='#fff8e7';ctx.shadowColor='#ffd700';ctx.shadowBlur=8}ctx.fill();ctx.shadowBlur=0}
ctx.beginPath();ctx.arc(0,0,r,0,Math.PI*2);
if(this.isUnicorn&&(this.state==='loitering'||this.state==='leaving')){const g=ctx.createRadialGradient(0,0,0,0,0,r*1.5);g.addColorStop(0,'#fff');g.addColorStop(0.4,'#ff00ff');g.addColorStop(1,'#8b00ff');ctx.fillStyle=g;ctx.shadowColor='#ff00ff';ctx.shadowBlur=20}else{ctx.fillStyle=this.color}
ctx.fill();ctx.shadowBlur=0;
if(this.state==='ordering'){ctx.fillStyle='#ffd700';ctx.font='bold 10px monospace';ctx.textAlign='center';ctx.fillText('!',0,-r-8)}
ctx.restore()
}
}
/* ---- Particle Systems ---- */
function spawnParticles(x,y,count,colorFn,velFn,lifeFn){
for(let i=0;i<count;i++)particles.push({x,y,vx:velFn().x,vy:velFn().y,life:lifeFn(),maxLife:lifeFn(),color:colorFn(),size:2+Math.random()*4})
}
function updateParticles(d){
for(let i=particles.length-1;i>=0;i--){const p=particles[i];p.x+=p.vx*d*60;p.y+=p.vy*d*60;p.vy+=0.02*d*60;p.life-=d;if(p.life<=0)particles.splice(i,1)}
}
function drawParticles(){
for(const p of particles){ctx.save();ctx.globalAlpha=p.life/p.maxLife;ctx.fillStyle=p.color;ctx.beginPath();ctx.arc(p.x*W,p.y*H,Math.max(1,p.size*dpr),0,Math.PI*2);ctx.fill();ctx.restore()}
}
function spawnUnicornParticles(){
for(let i=0;i<30;i++)unicornParticles.push({x:giantUnicorn.x,y:giantUnicorn.y,angle:Math.random()*Math.PI*2,speed:0.02+Math.random()*0.05,size:3+Math.random()*6,color:`hsl(${280+Math.random()*80},100%,${50+Math.random()*30}%)`,life:1+Math.random()*2,rotation:Math.random()*Math.PI*2,rotSpeed:(Math.random()-0.5)*0.2})
}
function updateUnicornParticles(d){
for(let i=unicornParticles.length-1;i>=0;i--){const p=unicornParticles[i];p.x+=Math.cos(p.angle)*p.speed*d*60;p.y+=Math.sin(p.angle)*p.speed*d*60;p.life-=d;p.rotation+=p.rotSpeed*d*60;p.size*=0.995;if(p.life<=0)unicornParticles.splice(i,1)}
}
function drawUnicornParticles(){
for(const p of unicornParticles){ctx.save();ctx.globalAlpha=p.life;ctx.translate(p.x*W,p.y*H);ctx.rotate(p.rotation);ctx.fillStyle=p.color;ctx.beginPath();for(let j=0;j<5;j++){ctx.lineTo(Math.cos(j*Math.PI*2/5)*p.size,Math.sin(j*Math.PI*2/5)*p.size);ctx.lineTo(Math.cos((j+0.5)*Math.PI*2/5)*p.size*0.4,Math.sin((j+0.5)*Math.PI*2/5)*p.size*0.4)}ctx.closePath();ctx.fill();ctx.restore()}
}
/* ---- Giant Unicorn (Catastrophe) ---- */
function createGiantUnicorn(){
giantUnicorn={x:0.5,y:0.5,scale:0,targetScale:1,phase:0,hornGlow:0,bodyParts:[]};
for(let i=0;i<12;i++)giantUnicorn.bodyParts.push({angle:i/12*Math.PI*2,radius:0.15+Math.random()*0.1,offset:Math.random()*Math.PI*2,speed:0.3+Math.random()*0.5});
stats.freed++;logEvent('A NEON UNICORN ASCENDS','catastrophe');
spawnUnicornParticles();
}
function updateGiantUnicorn(d){
if(!giantUnicorn)return;
giantUnicorn.phase+=d*0.8;
giantUnicorn.scale+= (giantUnicorn.targetScale-giantUnicorn.scale)*d*2;
giantUnicorn.hornGlow=Math.sin(giantUnicorn.phase*3)*0.5+0.5;
if(giantUnicorn.scale>0.95&&catastropheState===2){catastropheState=3;rebuildTimer=CFG.rebuildTime;giantUnicorn.targetScale=0;logEvent('Reality stitching itself back together...','milestone')}
if(catastropheState===3&&giantUnicorn.scale<0.01){giantUnicorn=null;catastropheState=0;screenShake=0;flashIntensity=0;warpPhase=0;particles=[];unicornParticles=[];stats.rebuilds++;logEvent('SHOP REBUILT. Business as usual.','milestone')}
}
function drawGiantUnicorn(){
if(!giantUnicorn)return;
const cx=giantUnicorn.x*W,cy=giantUnicorn.y*H,s=giantUnicorn.scale;
ctx.save();ctx.translate(cx,cy);ctx.scale(s,s);
const t=giantUnicorn.phase;
for(const part of giantUnicorn.bodyParts){
const a=part.angle+t*part.speed+part.offset;
const x=Math.cos(a)*part.radius*W*0.8;
const y=Math.sin(a)*part.radius*H*0.8;
const hue=280+Math.sin(t*2+part.angle)*40;
ctx.fillStyle=`hsl(${hue},100%,60%)`;ctx.shadowColor=`hsl(${hue},100%,60%)`;ctx.shadowBlur=30*s;
ctx.beginPath();ctx.arc(x,y,Math.max(3,part.radius*W*0.15*s),0,Math.PI*2);ctx.fill()
}
ctx.shadowBlur=0;
const hornH=0.35*W*s;const hornX=0;const hornY=-0.25*H*s;
const g=ctx.createLinearGradient(0,-hornH,0,0);g.addColorStop(0,'#fff');g.addColorStop(0.5,'#ff00ff');g.addColorStop(1,'#00ffff');
ctx.fillStyle=g;ctx.shadowColor='#ff00ff';ctx.shadowBlur=50*giantUnicorn.hornGlow*s;
ctx.beginPath();ctx.moveTo(-0.02*W*s,hornY);ctx.lineTo(0,hornY-hornH);ctx.lineTo(0.02*W*s,hornY);ctx.closePath();ctx.fill();
ctx.shadowBlur=0;
ctx.fillStyle='#fff';ctx.shadowColor='#ff00ff';ctx.shadowBlur=20*s;
ctx.beginPath();ctx.arc(-0.08*W*s,-0.1*H*s,0.02*W*s,0,Math.PI*2);ctx.fill();
ctx.beginPath();ctx.arc(0.08*W*s,-0.1*H*s,0.02*W*s,0,Math.PI*2);ctx.fill();
ctx.shadowBlur=0;
ctx.restore()
}
/* ---- Shop Drawing ---- */
function drawShop(instability){
ctx.save();
if(screenShake>0){const sx=(Math.random()-0.5)*screenShake*W*0.02;const sy=(Math.random()-0.5)*screenShake*W*0.02;ctx.translate(sx,sy)}
if(flashIntensity>0){ctx.fillStyle=`rgba(255,0,255,${flashIntensity*0.3})`;ctx.fillRect(0,0,W,H)}
const shopX=W*0.15,shopY=H*0.15,shopW=W*0.7,shopH=H*0.7;
ctx.strokeStyle=instability>0.5?'#ff00ff':'#333';ctx.lineWidth=3;ctx.shadowColor=instability>0.5?'#ff00ff':'transparent';ctx.shadowBlur=instability>0.5?20:0;
ctx.strokeRect(shopX,shopY,shopW,shopH);ctx.shadowBlur=0;
ctx.fillStyle='#111';ctx.fillRect(shopX,shopY,shopW,shopH);
ctx.strokeStyle='#222';ctx.lineWidth=1;
ctx.beginPath();ctx.moveTo(shopX,shopY+shopH*0.3);ctx.lineTo(shopX+shopW,shopY+shopH*0.3);ctx.stroke();
ctx.beginPath();ctx.moveTo(shopX+shopW*0.6,shopY);ctx.lineTo(shopX+shopW*0.6,shopY+shopH*0.3);ctx.stroke();
ctx.fillStyle='#1a1a2e';ctx.fillRect(shopX+shopW*0.62,shopY+shopH*0.05,shopW*0.35,shopH*0.2);
ctx.fillStyle='#00ffff';ctx.font='bold 12px monospace';ctx.textAlign='center';ctx.fillText('COUNTER',shopX+shopW*0.79,shopY+shopH*0.18);
ctx.fillStyle='#ff00ff';ctx.font='10px monospace';ctx.fillText('☕',shopX+shopW*0.75,shopY+shopH*0.25);
if(instability>=1){
ctx.strokeStyle='#ff00ff';ctx.lineWidth=2;ctx.setLineDash([10,5]);ctx.lineDashOffset=simTime*100;
ctx.beginPath();ctx.moveTo(shopX,shopY);ctx.lineTo(shopX+shopW,shopY+shopH);ctx.moveTo(shopX+shopW,shopY);ctx.lineTo(shopX,shopY+shopH);ctx.stroke();ctx.setLineDash([])
}
if(instability>=2){
ctx.fillStyle='rgba(255,0,255,0.1)';ctx.fillRect(shopX,shopY,shopW,shopH);
for(let i=0;i<8;i++){const a=simTime*5+i*0.8;const x=shopX+Math.sin(a)*shopW*0.1+shopW*0.5;const y=shopY+Math.cos(a)*shopH*0.1+shopH*0.5;ctx.fillStyle=`hsl(${280+Math.sin(simTime*3+i)*60},100%,60%)`;ctx.beginPath();ctx.arc(x,y,5+Math.sin(simTime*10+i)*3,0,Math.PI*2);ctx.fill()}
}
ctx.restore()
}
/* ---- Queue Drawing ---- */
function drawQueue(){
const qx=CFG.queueStartX*W,qy=CFG.queueStartY*H;
for(let i=0;i<queue.length;i++){
const px=qx,py=qy+i*24;
ctx.beginPath();ctx.arc(px,py,8,0,Math.PI*2);
ctx.fillStyle=queue[i].isUnicorn?'#ff00ff':'#666';ctx.fill();
if(queue[i].isUnicorn){ctx.shadowColor='#ff00ff';ctx.shadowBlur=10;ctx.fill();ctx.shadowBlur=0}
}
}
/* ---- UI Updates ---- */
function updateUI(){
const inside=customers.length;
const holding=customers.filter(c=>c.isUnicorn&&(c.state==='loitering'||c.state==='leaving')).length;
document.getElementById('served').textContent=stats.served;
document.getElementById('unicorns').textContent=stats.unicorns;
document.getElementById('rate').textContent=stats.served?(stats.unicorns/stats.served*100).toFixed(2)+'%':'0.00%';
document.getElementById('catastrophes').textContent=stats.catastrophes;
document.getElementById('lastEvent').textContent=stats.lastEvent?formatTime(simTime-stats.lastEvent)+' ago':'—';
document.getElementById('peakUnicorns').textContent=stats.peakUnicorns;
document.getElementById('rebuilds').textContent=stats.rebuilds;
document.getElementById('insideCount').textContent=inside;
document.getElementById('holdingCount').textContent=holding;
document.getElementById('queueCount').textContent=queue.length;
document.getElementById('instability').textContent=Math.round(getInstability()*100)+'%';
document.getElementById('meltdowns').textContent=stats.meltdowns;
document.getElementById('fractures').textContent=stats.fractures;
document.getElementById('freed').textContent=stats.freed;
document.getElementById('wasted').textContent=stats.wasted.toFixed(1);
document.getElementById('speedVal').textContent=speed.toFixed(1)+'×';
}
function formatTime(s){if(s<60)return s.toFixed(1)+'s';const m=Math.floor(s/60);return m+'m '+(s%60).toFixed(0)+'s'}
function logEvent(msg,type=''){
const log=document.getElementById('event-log');
const entry=document.createElement('div');entry.className='log-entry'+(type?' '+type:'');entry.textContent=`[${formatTime(simTime)}] ${msg}`;log.insertBefore(entry,log.firstChild);
while(log.children.length>50)log.removeChild(log.lastChild)
}
/* ---- Instability Calculation ---- */
function getInstability(){
const holding=customers.filter(c=>c.isUnicorn&&(c.state==='loitering'||c.state==='leaving')).length;
if(holding>=3)return 3;
if(holding===2)return 1.5+Math.sin(simTime*4)*0.5;
if(holding===1)return 0.5;
return 0
}
/* ---- Main Loop ---- */
function tick(now){
if(!lastFrame)lastFrame=now;
const rawDt=(now-lastFrame)/1000;lastFrame=now;
dt=Math.min(rawDt,0.1)*speed;
if(!paused){
simTime+=dt;
update(dt);
}
draw();
requestAnimationFrame(tick)
}
function update(d){
if(catastropheState>0){
catastropheTimer-=d;
screenShake=Math.max(0,screenShake-d*3);
flashIntensity=Math.max(0,flashIntensity-d*2);
warpPhase+=d*5;
updateGiantUnicorn(d);
updateUnicornParticles(d);
updateParticles(d);
if(catastropheState===1&&catastropheTimer<=0){catastropheState=2;createGiantUnicorn();stats.catastrophes++;stats.lastEvent=simTime;logEvent('NEON UNICORN EVENT — CATASTROPHE IMMINENT','catastrophe');screenShake=8;flashIntensity=1;for(let i=0;i<200;i++)spawnParticles(0.5,0.5,1,()=>`hsl(${280+Math.random()*80},100%,${50+Math.random()*30}%)`,()=>({x:(Math.random()-0.5)*0.3,y:(Math.random()-0.5)*0.3}),()=>0.5+Math.random()*1.5);stats.fractures+=3;stats.wasted+=customers.length*0.35}
if(catastropheState===3){rebuildTimer-=d;if(rebuildTimer<=0){customers=[];queue=[];nextSpawn=simTime+1;catastropheState=0}}
return
}
const instability=getInstability();
if(instability>=1){screenShake=Math.min(3,instability*1.5);flashIntensity=Math.min(0.3,(instability-1)*0.3);warpPhase+=d*3}
if(instability>=2){stats.meltdowns+=d*0.1;if(Math.random()<d*0.5)spawnParticles(0.5,0.5,1,()=>`hsl(${Math.random()*360},100%,60%)`,()=>({x:(Math.random()-0.5)*0.1,y:(Math.random()-0.5)*0.1}),()=>0.3)}
if(instability>=3&&catastropheState===0){catastropheState=1;catastropheTimer=1.5;stats.peakUnicorns=Math.max(stats.peakUnicorns,3);logEvent('THREE UNICORNS CONVERGE. REALITY BUCKLES.','catastrophe')}
nextSpawn-=d;
if(nextSpawn<=0&&catastropheState===0){
const isUni=rollUnicorn();
const c=new Customer(stats.served+queue.length+customers.length+1,isUni);
c.x=CFG.queueStartX;c.y=CFG.queueStartY+queue.length*0.015;
c.targetX=CFG.queueStartX;c.targetY=CFG.queueStartY+Math.min(queue.length,15)*0.015;
queue.push(c);
nextSpawn=CFG.spawnInterval.min+Math.random()*(CFG.spawnInterval.max-CFG.spawnInterval.min);
if(isUni)logEvent('A customer approaches... radiating strange energy','unicorn')
}
if(customers.length<CFG.maxInside&&queue.length>0){
const c=queue.shift();
c.state='entering';
c.targetX=CFG.counterX;c.targetY=CFG.counterY;
customers.push(c);
for(let i=0;i<queue.length;i++){queue[i].targetY=CFG.queueStartY+i*0.015}
}
for(let i=customers.length-1;i>=0;i--){
const c=customers[i];
c.update(d);
if(c.state==='leaving'&&c.atTarget()){
if(c.isUnicorn)stats.wasted+=0.35;
customers.splice(i,1)
}
}
updateParticles(d);
const holding=customers.filter(c=>c.isUnicorn&&(c.state==='loitering'||c.state==='leaving')).length;
stats.peakUnicorns=Math.max(stats.peakUnicorns,holding)
}
function draw(){
ctx.setTransform(dpr,0,0,dpr,0,0);
ctx.clearRect(0,0,W,H);
const instability=getInstability();
drawShop(instability);
drawQueue();
for(const c of customers)c.draw();
drawParticles();
drawGiantUnicorn();
drawUnicornParticles();
if(instability>=2){
ctx.save();ctx.globalAlpha=0.15;ctx.fillStyle='#ff00ff';ctx.fillRect(0,0,W,H);ctx.restore()
}
updateUI()
}
/* ---- Controls ---- */
document.getElementById('speed').addEventListener('input',e=>{speed=parseFloat(e.target.value)});
document.getElementById('pauseBtn').addEventListener('click',e=>{paused=!paused;e.target.textContent=paused?'RESUME':'PAUSE'});
document.getElementById('resetBtn').addEventListener('click',()=>{
simTime=0;customers=[];queue=[];nextSpawn=0;catastropheState=0;catastropheTimer=0;rebuildTimer=0;particles=[];unicornParticles=[];giantUnicorn=null;screenShake=0;flashIntensity=0;warpPhase=0;
stats={served:0,unicorns:0,catastrophes:0,lastEvent:0,peakUnicorns:0,rebuilds:0,meltdowns:0,fractures:0,freed:0,wasted:0};
document.getElementById('event-log').innerHTML='';
logEvent('SIMULATION RESET','milestone')
});
logEvent('STARBUCKS NEON UNICORN PROMOTION ACTIVE','milestone');
logEvent('1-in-6 chance per Frappuccino. 3 simultaneous = CATASTROPHE.','milestone');
requestAnimationFrame(tick);
</script>
</body>
</html>
First few minutes at 1×:
Tuning / special-casing:
Math.random() call at the counter — no weighting, no hidden state.holding >= 3 check each frame; the 1.5 s delay is only theatrical (screen shake buildup), not a timer that causes the event.dt (0.1×–10×); physics scales linearly so catastrophe frequency scales inversely.What it does badly:
Leave it running: the observed rate will jitter around 16.67%, catastrophes will cluster and gap randomly (Poisson-ish), and the giant unicorn will keep ascending — each one a genuine, dice-rolled convergence of three independent 1-in-6 rolls overlapping in time.