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.
With my timings the shop is service-limited: the barista takes on average 1.3s to make a drink (random 1.0–1.6s), so throughput λ ≈ 1/1.3 ≈ 0.77 customers/sec ≈ 46/min when the 8-inside cap keeps the queue full. Every customer who gets a drink then holds it for ~6s (5–7s random) before leaving, so the number of concurrent holders is λ×H ≈ 0.77×6 ≈ 4.6. Each holder is an independent 1/6 unicorn. For N=5 concurrent holders the binomial chance of ≥3 unicorns is C(5,3)(1/6)³(5/6)² + C(5,4)(1/6)⁴(5/6) + (1/6)⁵ ≈ 0.032 + 0.0032 + 0.00013 ≈ 3.5% per snapshot. Viewed per-customer: a new unicorn overlaps with ~4–5 others during its 6s dwell, and P(≥2 of 4 others are unicorns) = 1−(5/6)⁴−4(1/6)(5/6)³ ≈ 13.3% (19.6% for 5 others). So per customer P(catastrophe) ≈ (1/6)×0.13–0.20 ≈ 2–3%, i.e. one NEON Unicorn EVENT every ~35–50 customers, about 60–90 seconds at 1× speed on average, with huge variance because it’s honest dice — sometimes 10 customers, sometimes 150.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>STARBLOCKS — Neon Unicorn Event</title>
<style>
*{box-sizing:border-box}
html,body{margin:0;padding:0;background:#0f0f14;color:#eee;font-family:ui-monospace,Menlo,Consolas,monospace;overflow-x:hidden}
header{text-align:center;padding:10px 10px 6px;background:#006241;color:#fff;border-bottom:4px solid #ff00ff}
header h1{margin:0;font-size:22px;letter-spacing:1px;text-shadow:0 0 8px #ff00ff}
header p{margin:4px 0 0;font-size:12px;opacity:0.95}
#wrap{max-width:980px;margin:0 auto;padding:8px}
#stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:6px;margin:8px 0}
.card{background:#1e1e28;border:1px solid #333;border-radius:10px;padding:8px 10px;position:relative;overflow:hidden}
.card b{color:#ffcc00}
.card .label{font-size:10px;opacity:0.7;text-transform:uppercase;letter-spacing:0.6px}
.card .val{font-size:18px;font-weight:700;margin-top:2px}
.card .sub{font-size:11px;opacity:0.8}
.bar{height:6px;background:#333;border-radius:6px;overflow:hidden;margin-top:6px}
.fill{height:100%;background:linear-gradient(90deg,#ff00ff,#00ffff);width:0%;transition:width 0.2s}
#canvasWrap{position:relative;background:#0a0a0f;border:2px solid #333;border-radius:12px;overflow:hidden;box-shadow:0 8px 30px rgba(0,0,0,0.6)}
canvas{display:block;width:100%;height:auto;background:linear-gradient(#87ceeb 0%, #a0d8ef 18%, #e8dcc0 18%, #e8dcc0 100%)}
#controls{display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:center;padding:10px;background:#1a1a22;border:1px solid #333;border-radius:10px;margin:8px 0}
#controls label{font-size:12px;display:flex;align-items:center;gap:6px}
input[type=range]{width:160px}
button{background:#006241;color:#fff;border:1px solid #004d33;border-radius:8px;padding:6px 10px;font-family:inherit;font-weight:700;cursor:pointer}
button:hover{background:#007a52}
button:active{transform:scale(0.98)}
#log{height:90px;overflow:auto;background:#111;border:1px solid #333;border-radius:8px;padding:6px;font-size:11px;line-height:1.4}
.logUnicorn{color:#ff6bff;font-weight:700}
.logEvent{color:#ff0000;font-weight:800;background:#330033}
.pill{display:inline-block;padding:2px 6px;border-radius:999px;font-size:10px;font-weight:800;margin-left:6px}
.pill1{background:#330033;color:#ff88ff;border:1px solid #ff00ff}
.pill2{background:#331100;color:#ffaa00;border:1px solid #ff6600;animation:blink 0.3s infinite}
.pill3{background:#ff0000;color:#fff;border:1px solid #ffff00;animation:blink 0.15s infinite}
@keyframes blink{50%{opacity:0.4}}
footer{font-size:11px;opacity:0.7;text-align:center;padding:8px}
a{color:#ff88ff}
</style>
</head>
<body>
<header>
<h1>★ STARBLOCKS COFFEE ★ <span style="font-size:12px;background:#ff00ff;color:#fff;padding:2px 6px;border-radius:6px;vertical-align:middle">PROMOTION!</span></h1>
<p>Every Frappuccino has a <b>1-in-6</b> chance to be a glowing <span style="color:#ff88ff;text-shadow:0 0 6px #ff00ff">NEON UNICORN FRAPPUCCINO™</span> — collect 3 in the shop and <i>something happens</i>…</p>
</header>
<div id="wrap">
<div id="stats">
<div class="card"><div class="label">Customers Served</div><div class="val" id="sServed">0</div><div class="sub">spawned: <span id="sSpawned">0</span> • queue: <span id="sQueue">0</span></div></div>
<div class="card"><div class="label">Neon Unicorns Produced</div><div class="val" id="sUnicorns">0</div><div class="sub">observed: <b id="sRate">0.0%</b> • true 16.67% <span id="sRateBar" class="bar"><span id="sRateFill" class="fill"></span></span></div></div>
<div class="card"><div class="label">Inside Now</div><div class="val"><span id="sInside">0</span>/8 <span style="font-size:12px;opacity:0.7">holding</span> <span id="sHolders">0</span></div><div class="sub">unicorns inside: <b id="sInsideUni" style="color:#ff6bff">0</b> <span id="sPill"></span></div></div>
<div class="card"><div class="label">Catastrophes</div><div class="val" id="sCats">0</div><div class="sub">since last: <span id="sSinceC">0</span> customers • <span id="sSinceT">0s</span></div></div>
<div class="card"><div class="label">Barista Sanity</div><div class="val" id="sSanity">100%</div><div class="sub">stress: <span id="sStress">calm</span></div><div class="bar"><div id="sSanityFill" class="fill" style="background:linear-gradient(90deg,#00ff88,#ff0000)"></div></div></div>
<div class="card"><div class="label">Containment Field</div><div class="val" id="sContain">100%</div><div class="sub">structural integrity: <span id="sIntegrity">stable</span></div><div class="bar"><div id="sContainFill" class="fill"></div></div></div>
</div>
<div id="canvasWrap">
<canvas id="c" width="960" height="540"></canvas>
</div>
<div id="controls">
<label>Speed: <input id="speed" type="range" min="0.5" max="10" step="0.5" value="1"> <b id="speedVal">1×</b></label>
<button id="btnPause">⏸ Pause</button>
<button id="btnFast">⏩ 5×</button>
<button id="btnAdd">+ Add 5 Customers</button>
<button id="btnReset">Reset Stats</button>
<span style="font-size:11px;opacity:0.7">At most 8 inside • honest 1/6 roll at counter • no timers</span>
</div>
<div id="log"></div>
<footer>
No loaded dice. Every drink rolls <code>Math.random() < 1/6</code> at the counter. Catastrophe only when 3 unicorn-holders overlap. Simple circles, procedural chaos.
</footer>
</div>
<script>
(() => {
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');
const logEl = document.getElementById('log');
let speed = 1;
let paused = false;
let stats = {served:0, unicorns:0, catastrophes:0, spawned:0};
let timeSinceCat = 0;
let customersSinceCat = 0;
let customers = [];
let queue = [];
let counterQueue = [];
let barista = {busy:false, timer:0, current:null, anim:0};
let spawnTimer = 0.6;
let spawnInterval = 0.85;
let unicornsInside = 0;
let catastropheActive = false;
let catastropheTimer = 0;
let collapseProgress = 0;
let shakeX=0, shakeY=0, flashAlpha=0;
let particles = [];
let debris = [];
let giant = {dance:0};
let nextId = 1;
function log(msg, cls){
const d=document.createElement('div');
d.textContent = `[${new Date().toLocaleTimeString()}] ${msg}`;
if(cls) d.className=cls;
logEl.appendChild(d);
logEl.scrollTop = logEl.scrollHeight;
if(logEl.children.length>80) logEl.removeChild(logEl.firstChild);
}
function rand(a,b){return a+Math.random()*(b-a)}
function rollUnicorn(){ return Math.random() < 1/6; }
class Customer{
constructor(id){
this.id=id;
this.x = rand(10,30);
this.y = 500 + rand(-6,6);
this.tx=this.x; this.ty=this.y;
this.state='QUEUED_OUTSIDE';
this.hasDrink=false;
this.isUnicorn=false;
this.holdTimer=0;
this.color=`hsl(${rand(0,360)|0},75%,62%)`;
this.speed=rand(85,125);
this.panic=false;
this.loungeX=0; this.loungeY=0;
this.wobble=rand(0,Math.PI*2);
}
update(dt){
// move
let dx=this.tx-this.x, dy=this.ty-this.y;
let dist=Math.hypot(dx,dy);
if(dist>1.5){
let mv=this.speed*dt*(this.panic?1.9:1);
if(mv>dist) mv=dist;
this.x+=dx/dist*mv;
this.y+=dy/dist*mv;
} else {
this.onArrive();
}
if(this.state==='HOLDING'){
this.holdTimer-=dt;
this.wobble+=dt*3;
if(this.holdTimer<=0){
this.state='LEAVING';
this.tx=480; this.ty=462;
this.panic=catastropheActive;
}
}
}
onArrive(){
if(this.state==='ENTERING'){
// reached door, go to counter queue
if(!counterQueue.includes(this)) counterQueue.push(this);
this.state='WAITING_FOR_COUNTER';
this.updateCounterTarget();
} else if(this.state==='LEAVING'){
if(Math.abs(this.x-480)<3 && Math.abs(this.y-462)<3){
// exit door
this.x=480; this.y=520;
this.tx=980; this.ty=520;
this.state='GONE';
}
} else if(this.state==='GONE'){
// will be removed
}
}
updateCounterTarget(){
let idx=counterQueue.indexOf(this);
if(idx===-1) return;
// line in front of counter
this.tx = 300 + idx*42;
this.ty = 222;
}
}
function updateQueuePositions(){
queue.forEach((c,i)=>{
if(c.state==='QUEUED_OUTSIDE'){
c.tx = 18 + i*26;
c.ty = 500 + Math.sin(i*0.7)*3;
}
});
}
function trySpawn(dt){
spawnTimer-=dt;
if(spawnTimer<=0){
spawnTimer = spawnInterval + rand(-0.2,0.2);
if(queue.length + customers.filter(c=>c.state!=='GONE').length < 30){
let c=new Customer(nextId++);
stats.spawned++;
customers.push(c);
queue.push(c);
updateQueuePositions();
}
}
}
function tryEnter(){
let inside = customers.filter(c=>c.state!=='QUEUED_OUTSIDE' && c.state!=='GONE').length;
while(queue.length>0 && inside<8){
let c=queue.shift();
c.state='ENTERING';
c.tx=480; c.ty=462;
inside++;
updateQueuePositions();
}
}
function updateBarista(dt){
if(catastropheActive) return;
if(barista.busy){
barista.timer-=dt;
barista.anim+=dt*12;
if(barista.timer<=0){
let c=barista.current;
if(c){
c.hasDrink=true;
c.isUnicorn = rollUnicorn();
stats.served++;
customersSinceCat++;
if(c.isUnicorn){
stats.unicorns++;
log(`Customer #${c.id} got NEON UNICORN FRAPPUCCINO! ✨🦄`, 'logUnicorn');
// burst
for(let i=0;i<12;i++) particles.push({x:c.x,y:c.y-18,vx:rand(-120,120),vy:rand(-200,-40),life:1,decay:rand(1.2,2),color:`hsl(${rand(280,330)},100%,65%)`,size:rand(3,6)});
} else {
if(Math.random()<0.08) log(`Customer #${c.id} got a normal Frappuccino.`);
}
c.state='HOLDING';
c.holdTimer=rand(5,7);
c.loungeX=rand(240,700);
c.loungeY=rand(260,410);
c.tx=c.loungeX; c.ty=c.loungeY;
let idx=counterQueue.indexOf(c);
if(idx!==-1) counterQueue.splice(idx,1);
counterQueue.forEach(q=>q.updateCounterTarget());
}
barista.busy=false; barista.current=null;
}
} else {
if(counterQueue.length>0){
let nxt=counterQueue[0];
if(Math.hypot(nxt.x-nxt.tx, nxt.y-nxt.ty)<4){
barista.busy=true;
barista.timer=rand(1.0,1.6);
barista.current=nxt;
nxt.state='BEING_SERVED';
}
}
}
}
function cleanup(){
for(let i=customers.length-1;i>=0;i--){
let c=customers[i];
if(c.state==='GONE' && c.x>940){
customers.splice(i,1);
}
}
}
function checkCatastrophe(){
if(catastropheActive) return;
unicornsInside = customers.filter(c=>c.hasDrink && c.isUnicorn && c.state==='HOLDING').length;
if(unicornsInside>=3){
triggerCatastrophe();
}
}
function triggerCatastrophe(){
catastropheActive=true;
catastropheTimer=0;
collapseProgress=0;
stats.catastrophes++;
log(`★★★ NEON UNICORN EVENT!!! ${unicornsInside} unicorns inside — SHOP COLLAPSING! ★★★`, 'logEvent');
timeSinceCat=0; customersSinceCat=0;
customers.forEach(c=>{
if(c.state==='HOLDING' || c.state==='WAITING_FOR_COUNTER' || c.state==='BEING_SERVED'){
c.panic=true;
if(c.state==='HOLDING') c.holdTimer=Math.min(c.holdTimer, rand(0.4,1.0));
}
});
// debris
debris=[];
for(let i=0;i<22;i++){
debris.push({x:rand(210,710),y:rand(110,440),vx:rand(-220,220),vy:rand(-320,-60),rot:rand(0,Math.PI*2),vr:rand(-6,6),w:rand(18,55),h:rand(12,30),life:1});
}
for(let i=0;i<90;i++){
particles.push({x:480,y:260,vx:rand(-340,340),vy:rand(-420,80),life:1,decay:rand(0.7,1.6),color:`hsl(${rand(280,320)},100%,60%)`,size:rand(4,10)});
}
// cancel barista
if(barista.busy && barista.current){
// customer flees without drink? keep drink if already has
barista.busy=false;
let c=barista.current;
if(c.state==='BEING_SERVED'){
c.state='HOLDING';
c.hasDrink=true;
c.isUnicorn=rollUnicorn();
if(c.isUnicorn){ stats.unicorns++; stats.served++; }
else stats.served++;
c.holdTimer=rand(0.5,1);
c.tx=rand(240,700); c.ty=rand(260,410);
let idx=counterQueue.indexOf(c);
if(idx!==-1) counterQueue.splice(idx,1);
}
barista.current=null;
}
}
function updateCatastrophe(dt){
if(!catastropheActive) return;
catastropheTimer+=dt;
giant.dance+=dt*6;
if(catastropheTimer<0.6){
shakeX=rand(-14,14); shakeY=rand(-10,10); flashAlpha=0.35;
collapseProgress=0;
} else if(catastropheTimer<2.0){
let p=(catastropheTimer-0.6)/1.4;
collapseProgress=p;
shakeX=rand(-18,18); shakeY=rand(-14,14); flashAlpha=Math.random()>0.5?0.25:0;
debris.forEach(d=>{ d.x+=d.vx*dt; d.y+=d.vy*dt; d.vy+=900*dt; d.rot+=d.vr*dt; });
} else if(catastropheTimer<6.2){
collapseProgress=1;
shakeX=Math.sin(catastropheTimer*22)*6; shakeY=Math.cos(catastropheTimer*18)*4; flashAlpha=0;
if(Math.random()<0.4) particles.push({x:rand(380,580),y:rand(220,360),vx:rand(-110,110),vy:rand(-220,-60),life:1,decay:1.1,color:`hsl(${rand(285,335)},100%,70%)`,size:rand(3,7)});
debris.forEach(d=>{ d.x+=d.vx*dt*0.3; d.y+=d.vy*dt*0.3; d.vy+=300*dt; d.rot+=d.vr*dt*0.5; });
} else if(catastropheTimer<7.2){
let p=(catastropheTimer-6.2)/1.0;
collapseProgress=1-p;
shakeX=(1-p)*4; shakeY=(1-p)*2;
// rebuild sparkles
if(Math.random()<0.5) particles.push({x:rand(210,710),y:rand(110,440),vx:rand(-60,60),vy:rand(-120,-20),life:1,decay:1.5,color:'#ffffff',size:rand(2,4)});
} else {
catastropheActive=false; catastropheTimer=0; collapseProgress=0; shakeX=0; shakeY=0; flashAlpha=0;
debris=[]; customers.forEach(c=>c.panic=false);
log(`Shop rebuilt. Barista is back. Promotion continues...`, '');
}
}
function updateParticles(dt){
for(let i=particles.length-1;i>=0;i--){
let p=particles[i];
p.x+=p.vx*dt; p.y+=p.vy*dt; p.vy+=220*dt; p.life-=p.decay*dt;
if(p.life<=0) particles.splice(i,1);
}
}
// Drawing
function draw(){
// handle shake/flash from unicorn count when not catastrophe
if(!catastropheActive){
if(unicornsInside===1){
shakeX=Math.sin(Date.now()*0.005)*1.2;
shakeY=Math.cos(Date.now()*0.006)*1.0;
flashAlpha=0.06 + Math.sin(Date.now()*0.003)*0.04;
} else if(unicornsInside===2){
shakeX=rand(-5,5); shakeY=rand(-4,4);
flashAlpha=0.12 + Math.sin(Date.now()*0.02)*0.08;
if(Math.random()<0.25) particles.push({x:rand(220,700),y:rand(120,430),vx:rand(-40,40),vy:rand(-80,-10),life:1,decay:1.8,color:`hsl(${rand(280,320)},100%,65%)`,size:rand(2,5)});
} else {
shakeX*=0.85; shakeY*=0.85; flashAlpha*=0.9;
if(Math.abs(shakeX)<0.1) shakeX=0;
if(Math.abs(shakeY)<0.1) shakeY=0;
}
}
ctx.save();
ctx.translate(shakeX, shakeY);
// background sky
ctx.fillStyle='#87ceeb';
ctx.fillRect(0,0,960,540);
// distant city
ctx.fillStyle='#6a7a8a';
for(let i=0;i<12;i++){ ctx.fillRect(40+i*80, 60, 40, 40+Math.sin(i)*10); }
// sidewalk / street
ctx.fillStyle='#2b2b2b';
ctx.fillRect(0,470,960,70);
ctx.fillStyle='#444';
for(let i=0;i<960;i+=40){ ctx.fillRect(i,505,20,4); }
ctx.fillStyle='#c9b896';
ctx.fillRect(0,440,960,30);
// shop base shadow
ctx.fillStyle='rgba(0,0,0,0.25)';
ctx.fillRect(190,100,520,360);
// shop building
let shopX=200, shopY=100, shopW=500, shopH=350;
// if collapsing, draw broken
if(collapseProgress>0 && collapseProgress<1){
// draw rubble base
ctx.fillStyle='#3a2a1a';
ctx.fillRect(shopX, shopY, shopW, shopH);
// draw debris
debris.forEach(d=>{
ctx.save();
ctx.translate(d.x,d.y);
ctx.rotate(d.rot);
ctx.fillStyle='#d8c9a8';
ctx.fillRect(-d.w/2,-d.h/2,d.w,d.h);
ctx.strokeStyle='#8b7355';
ctx.strokeRect(-d.w/2,-d.h/2,d.w,d.h);
ctx.restore();
});
// cracks overlay
ctx.strokeStyle=`rgba(255,0,255,${0.5+collapseProgress*0.5})`;
ctx.lineWidth=2;
for(let i=0;i<6;i++){
ctx.beginPath();
ctx.moveTo(shopX+rand(0,shopW), shopY+rand(0,shopH));
ctx.lineTo(shopX+rand(0,shopW), shopY+rand(0,shopH));
ctx.stroke();
}
} else if(collapseProgress>=1){
// fully collapsed - rubble pile
ctx.fillStyle='#4a3a2a';
ctx.beginPath();
ctx.moveTo(shopX, shopY+shopH);
ctx.lineTo(shopX+80, shopY+shopH-40);
ctx.lineTo(shopX+shopW-80, shopY+shopH-50);
ctx.lineTo(shopX+shopW, shopY+shopH);
ctx.closePath();
ctx.fill();
debris.forEach(d=>{
ctx.save();
ctx.translate(d.x,d.y);
ctx.rotate(d.rot);
ctx.fillStyle='#c9b896';
ctx.fillRect(-d.w/2,-d.h/2,d.w,d.h);
ctx.restore();
});
} else {
// normal shop
// walls
ctx.fillStyle='#f5e6c8';
ctx.fillRect(shopX, shopY, shopW, shopH);
ctx.strokeStyle='#8b7355';
ctx.lineWidth=3;
ctx.strokeRect(shopX, shopY, shopW, shopH);
// interior floor
ctx.fillStyle='#fff8e7';
ctx.fillRect(shopX+10, shopY+10, shopW-20, shopH-20);
// wood floor pattern
ctx.strokeStyle='rgba(139,115,85,0.15)';
ctx.lineWidth=1;
for(let y=shopY+20;y<shopY+shopH-20;y+=20){ ctx.beginPath(); ctx.moveTo(shopX+10,y); ctx.lineTo(shopX+shopW-10,y); ctx.stroke(); }
// counter
ctx.fillStyle='#8b5a2b';
ctx.fillRect(250,180,400,22);
ctx.fillStyle='#a67c52';
ctx.fillRect(250,180,400,8);
ctx.fillStyle='#5a3a1a';
ctx.fillRect(250,200,400,4);
// espresso machine
ctx.fillStyle='#222';
ctx.fillRect(460,138,44,44);
ctx.fillStyle='#ff00ff';
ctx.fillRect(462,140,40,6);
ctx.fillStyle='#00ffff';
ctx.fillRect(462,172,40,4);
ctx.fillStyle='#fff';
ctx.font='7px monospace';
ctx.fillText('FRAP',468,158);
// menu board
ctx.fillStyle='#006241';
ctx.fillRect(320,108,260,28);
ctx.fillStyle='#fff';
ctx.font='bold 11px monospace';
ctx.fillText('NEON UNICORN FRAP 1 IN 6 WINS!',328,126);
// tables
ctx.fillStyle='#c9a86a';
for(let i=0;i<4;i++){
let x=270+i*115, y=300;
ctx.beginPath(); ctx.arc(x,y,20,0,Math.PI*2); ctx.fill();
ctx.strokeStyle='#8b7355'; ctx.lineWidth=2; ctx.stroke();
ctx.fillStyle='#8b7355'; ctx.fillRect(x-3,y,6,28);
// chairs
ctx.fillStyle='#d8c9a8';
ctx.beginPath(); ctx.arc(x-28,y+10,10,0,Math.PI*2); ctx.fill(); ctx.stroke();
ctx.beginPath(); ctx.arc(x+28,y+10,10,0,Math.PI*2); ctx.fill(); ctx.stroke();
}
// windows
ctx.fillStyle='#bfe9ff';
ctx.fillRect(shopX+12, shopY+12, 90,70);
ctx.fillRect(shopX+shopW-102, shopY+12, 90,70);
ctx.strokeStyle='#8b7355'; ctx.lineWidth=2; ctx.strokeRect(shopX+12, shopY+12,90,70); ctx.strokeRect(shopX+shopW-102, shopY+12,90,70);
// window shine
ctx.fillStyle='rgba(255,255,255,0.4)';
ctx.fillRect(shopX+14, shopY+14, 30, 20);
ctx.fillRect(shopX+shopW-100, shopY+14, 30,20);
// door
ctx.fillStyle='#5a3a1a';
ctx.fillRect(460,430,40,20);
ctx.fillStyle='#8b5a2b';
ctx.fillRect(462,418,36,32);
ctx.fillStyle='#ffcc00';
ctx.beginPath(); ctx.arc(488,434,4,0,Math.PI*2); ctx.fill();
// door glass
ctx.fillStyle='rgba(191,233,255,0.6)';
ctx.fillRect(466,422,28,18);
// sign above door
ctx.fillStyle='#006241';
ctx.fillRect(350,88,200,32);
ctx.strokeStyle='#ff00ff'; ctx.lineWidth=2; ctx.strokeRect(350,88,200,32);
ctx.fillStyle='#fff';
ctx.font='bold 13px monospace';
ctx.fillText('STARBLOCKS', 385,108);
ctx.font='8px monospace';
ctx.fillText('COFFEE • FRAPS • CHAOS', 375,118);
// promotion banner inside
ctx.fillStyle='#ff00ff';
ctx.fillRect(300,142,300,14);
ctx.fillStyle='#fff';
ctx.font='bold 9px monospace';
ctx.fillText('TRY THE NEON UNICORN — GLOWING! PSYCHEDELIC! DANGEROUS!',308,152);
// subtle glow for 1 unicorn
if(unicornsInside===1){
ctx.shadowBlur=30; ctx.shadowColor='#ff00ff';
ctx.strokeStyle='rgba(255,0,255,0.6)'; ctx.lineWidth=4;
ctx.strokeRect(shopX-2, shopY-2, shopW+4, shopH+4);
ctx.shadowBlur=0;
} else if(unicornsInside===2){
ctx.shadowBlur=40; ctx.shadowColor='#00ffff';
ctx.strokeStyle=`hsl(${(Date.now()/10)%360},100%,60%)`; ctx.lineWidth=6;
ctx.strokeRect(shopX-4, shopY-4, shopW+8, shopH+8);
ctx.shadowBlur=0;
// crack lines
ctx.strokeStyle='rgba(255,0,0,0.7)'; ctx.lineWidth=2;
ctx.beginPath();
ctx.moveTo(shopX+100, shopY+50); ctx.lineTo(shopX+150, shopY+120); ctx.lineTo(shopX+120, shopY+200); ctx.stroke();
ctx.beginPath();
ctx.moveTo(shopX+shopW-100, shopY+60); ctx.lineTo(shopX+shopW-140, shopY+140); ctx.stroke();
}
}
// draw barista
if(collapseProgress<0.5){
let bx=480, by=162;
ctx.save(); ctx.translate(bx,by);
// shadow
ctx.fillStyle='rgba(0,0,0,0.2)'; ctx.beginPath(); ctx.ellipse(0,18,18,6,0,0,Math.PI*2); ctx.fill();
// body apron
ctx.fillStyle='#006241'; ctx.fillRect(-14,-12,28,24);
ctx.fillStyle='#fff'; ctx.fillRect(-14,-12,28,6);
ctx.fillStyle='#006241'; ctx.font='6px monospace'; ctx.fillText('BARISTA', -13, -4);
// head
ctx.fillStyle='#ffdbac'; ctx.beginPath(); ctx.arc(0,-18,11,0,Math.PI*2); ctx.fill();
ctx.strokeStyle='#000'; ctx.lineWidth=1; ctx.stroke();
// eyes
ctx.fillStyle='#000'; ctx.beginPath(); ctx.arc(-4,-20,1.5,0,Math.PI*2); ctx.arc(4,-20,1.5,0,Math.PI*2); ctx.fill();
if(unicornsInside>=2){ // stressed
ctx.fillStyle='#ff0000'; ctx.beginPath(); ctx.arc(-4,-20,1,0,Math.PI*2); ctx.arc(4,-20,1,0,Math.PI*2); ctx.fill();
}
// hat
ctx.fillStyle='#006241'; ctx.fillRect(-12,-30,24,8);
// arms
ctx.fillStyle='#ffdbac';
if(barista.busy){
let t=barista.anim;
ctx.save(); ctx.translate(-16,0); ctx.rotate(Math.sin(t)*0.6); ctx.fillRect(-4,-6,8,14); ctx.restore();
ctx.save(); ctx.translate(16,0); ctx.rotate(Math.cos(t)*0.6); ctx.fillRect(-4,-6,8,14); ctx.restore();
// drink in hands
ctx.fillStyle=`hsl(${(Date.now()/8)%360},100%,60%)`;
ctx.fillRect(-8,2,16,12);
ctx.strokeStyle='#fff'; ctx.strokeRect(-8,2,16,12);
ctx.fillStyle='#fff'; ctx.fillRect(-9,0,18,4);
} else {
ctx.fillRect(-16,-2,8,14);
ctx.fillRect(8,-2,8,14);
}
ctx.restore();
} else if(collapseProgress>=0.5 && collapseProgress<1){
// barista hiding
ctx.fillStyle='#ffdbac'; ctx.beginPath(); ctx.arc(480,440,8,0,Math.PI*2); ctx.fill();
ctx.fillStyle='#006241'; ctx.fillRect(472,444,16,10);
}
// draw customers
customers.forEach(c=>{
ctx.save(); ctx.translate(c.x,c.y);
// shadow
ctx.fillStyle='rgba(0,0,0,0.2)'; ctx.beginPath(); ctx.ellipse(0,7,11,4,0,0,Math.PI*2); ctx.fill();
// body
ctx.fillStyle=c.color; ctx.beginPath(); ctx.arc(0,0,10,0,Math.PI*2); ctx.fill();
ctx.strokeStyle='#000'; ctx.lineWidth=1.2; ctx.stroke();
// eyes
ctx.fillStyle='#000'; ctx.beginPath(); ctx.arc(-4,-3,1.8,0,Math.PI*2); ctx.arc(4,-3,1.8,0,Math.PI*2); ctx.fill();
ctx.fillStyle='#fff'; ctx.beginPath(); ctx.arc(-3.2,-4,0.8,0,Math.PI*2); ctx.arc(4.8,-4,0.8,0,Math.PI*2); ctx.fill();
// mouth
if(c.panic){ ctx.strokeStyle='#ff0000'; ctx.lineWidth=1.2; ctx.beginPath(); ctx.arc(0,2,3,0.2,Math.PI-0.2); ctx.stroke(); }
else { ctx.strokeStyle='#000'; ctx.lineWidth=1; ctx.beginPath(); ctx.arc(0,2,2,0,Math.PI); ctx.stroke(); }
// drink
if(c.hasDrink){
ctx.save(); ctx.translate(0,-19);
// cup
let cupColor = c.isUnicorn ? `hsl(${(Date.now()/12 + c.id*40)%360},100%,60%)` : '#ffffff';
ctx.fillStyle=cupColor; ctx.fillRect(-7,-9,14,16);
ctx.strokeStyle='#000'; ctx.lineWidth=1; ctx.strokeRect(-7,-9,14,16);
// lid
ctx.fillStyle='#e0e0e0'; ctx.fillRect(-8,-11,16,4);
// straw
ctx.fillStyle='#ff69b4'; ctx.fillRect(3,-15,2,8);
if(c.isUnicorn){
ctx.shadowBlur=14; ctx.shadowColor=cupColor;
ctx.strokeStyle=cupColor; ctx.lineWidth=2; ctx.strokeRect(-7,-9,14,16);
ctx.shadowBlur=0;
// sparkles
for(let i=0;i<3;i++){
let sx=Math.sin(Date.now()/220 + i + c.id)*9;
let sy=Math.cos(Date.now()/200 + i*1.3)*5 -7;
ctx.fillStyle=`hsl(${(Date.now()/10 + i*70)%360},100%,70%)`;
ctx.beginPath(); ctx.arc(sx,sy,1.8,0,Math.PI*2); ctx.fill();
}
// label
ctx.fillStyle='#000'; ctx.font='6px monospace'; ctx.fillText('UNICORN', -12, 12);
}
ctx.restore();
}
// id
ctx.fillStyle='rgba(0,0,0,0.6)'; ctx.font='7px monospace'; ctx.fillText('#'+c.id, -8, 16);
// panic
if(c.panic){
ctx.fillStyle='#ff0000'; ctx.font='bold 9px monospace'; ctx.fillText('!!!', -7, -24);
}
ctx.restore();
});
// particles
particles.forEach(p=>{
ctx.globalAlpha=Math.max(0,p.life);
ctx.fillStyle=p.color;
ctx.beginPath(); ctx.arc(p.x,p.y,p.size,0,Math.PI*2); ctx.fill();
if(p.color.includes('hsl')){ ctx.shadowBlur=8; ctx.shadowColor=p.color; ctx.fill(); ctx.shadowBlur=0; }
});
ctx.globalAlpha=1;
// giant unicorn
if(catastropheActive && catastropheTimer>=1.2){
let prog=Math.min(1,(catastropheTimer-1.2)/0.8);
let gy = 320 + (1-prog)*120;
let gx = 480 + Math.sin(giant.dance)*18;
let scale = 1.6 + Math.sin(giant.dance*0.7)*0.08;
ctx.save(); ctx.translate(gx,gy); ctx.scale(scale,scale);
// shadow
ctx.fillStyle='rgba(0,0,0,0.3)'; ctx.beginPath(); ctx.ellipse(0,62,42,11,0,0,Math.PI*2); ctx.fill();
// body
ctx.fillStyle='#fff'; ctx.beginPath(); ctx.ellipse(0,22,32,22,0,0,Math.PI*2); ctx.fill();
ctx.strokeStyle='#ff00ff'; ctx.lineWidth=2.5; ctx.stroke();
// legs dancing
for(let i=0;i<4;i++){
let lx=-20+i*13;
let ly=32 + Math.sin(giant.dance + i*0.9)*12;
ctx.fillStyle='#fff'; ctx.fillRect(lx,ly,7,22); ctx.strokeStyle='#ff00ff'; ctx.lineWidth=1.5; ctx.strokeRect(lx,ly,7,22);
ctx.fillStyle=`hsl(${(Date.now()/12 + i*60)%360},100%,60%)`; ctx.fillRect(lx,ly+20,7,5);
}
// neck
ctx.fillStyle='#fff'; ctx.fillRect(-9,-8,18,32);
ctx.strokeStyle='#ff00ff'; ctx.strokeRect(-9,-8,18,32);
// head
ctx.fillStyle='#fff'; ctx.beginPath(); ctx.arc(0,-18,19,0,Math.PI*2); ctx.fill(); ctx.stroke();
// horn
ctx.fillStyle=`hsl(${(Date.now()/6)%360},100%,60%)`;
ctx.beginPath(); ctx.moveTo(0,-42); ctx.lineTo(-7,-18); ctx.lineTo(7,-18); ctx.closePath(); ctx.fill();
ctx.strokeStyle='#000'; ctx.lineWidth=1; ctx.stroke();
// mane rainbow
for(let i=0;i<6;i++){
ctx.fillStyle=`hsl(${(280+i*18 + Date.now()/18)%360},100%,62%)`;
ctx.beginPath(); ctx.arc(-12 - i*1.5, -16 + i*2.5, 9,0,Math.PI*2); ctx.fill();
}
// tail
ctx.fillStyle=`hsl(${(Date.now()/10)%360},100%,62%)`;
ctx.beginPath(); ctx.arc(30,22,13,0,Math.PI*2); ctx.fill();
ctx.strokeStyle='#ff00ff'; ctx.stroke();
// eyes
ctx.fillStyle='#000'; ctx.beginPath(); ctx.arc(-7,-20,3.2,0,Math.PI*2); ctx.arc(7,-20,3.2,0,Math.PI*2); ctx.fill();
ctx.fillStyle='#ff00ff'; ctx.beginPath(); ctx.arc(-7,-20,1.2,0,Math.PI*2); ctx.arc(7,-20,1.2,0,Math.PI*2); ctx.fill();
ctx.fillStyle='#fff'; ctx.beginPath(); ctx.arc(-6,-21,0.8,0,Math.PI*2); ctx.arc(8,-21,0.8,0,Math.PI*2); ctx.fill();
// nostrils
ctx.fillStyle='#ff88ff'; ctx.beginPath(); ctx.arc(-3,-12,1,0,Math.PI*2); ctx.arc(3,-12,1,0,Math.PI*2); ctx.fill();
// mouth
ctx.strokeStyle='#000'; ctx.lineWidth=1.2; ctx.beginPath(); ctx.arc(0,-10,4,0,Math.PI); ctx.stroke();
// text
ctx.fillStyle='#ff00ff'; ctx.font='bold 11px monospace'; ctx.textAlign='center';
ctx.fillText('NEON UNICORN EVENT',0,-52);
ctx.font='10px monospace'; ctx.fillText('✨💖🦄 DANCE BREAK 🦄💖✨',0,-62);
ctx.textAlign='left';
ctx.restore();
}
ctx.restore();
// flash overlay
if(flashAlpha>0.01){
ctx.fillStyle=`rgba(255,0,255,${flashAlpha*0.6})`;
ctx.fillRect(0,0,960,540);
ctx.fillStyle=`rgba(0,255,255,${flashAlpha*0.3})`;
ctx.fillRect(0,0,960,540);
}
// vignette for 2 unicorns
if(unicornsInside===2 && !catastropheActive){
let g=ctx.createRadialGradient(480,270,200,480,270,500);
g.addColorStop(0,'rgba(0,0,0,0)');
g.addColorStop(1,'rgba(255,0,255,0.25)');
ctx.fillStyle=g; ctx.fillRect(0,0,960,540);
}
// catastrophe red overlay
if(catastropheActive && catastropheTimer<2){
ctx.fillStyle=`rgba(255,0,0,${0.15+Math.random()*0.1})`;
ctx.fillRect(0,0,960,540);
}
}
function updateStatsDOM(){
document.getElementById('sServed').textContent=stats.served;
document.getElementById('sSpawned').textContent=stats.spawned;
document.getElementById('sQueue').textContent=queue.length;
document.getElementById('sUnicorns').textContent=stats.unicorns;
let rate = stats.served? (stats.unicorns/stats.served*100):0;
document.getElementById('sRate').textContent=rate.toFixed(1)+'%';
document.getElementById('sRateFill').style.width=Math.min(100, rate/33*100)+'%';
document.getElementById('sInside').textContent=customers.filter(c=>c.state!=='QUEUED_OUTSIDE' && c.state!=='GONE').length;
document.getElementById('sHolders').textContent=customers.filter(c=>c.state==='HOLDING').length;
document.getElementById('sInsideUni').textContent=unicornsInside;
let pill=document.getElementById('sPill');
if(unicornsInside===1) pill.innerHTML='<span class="pill pill1">⚡ GLOWING</span>';
else if(unicornsInside===2) pill.innerHTML='<span class="pill pill2">⚠️ UNSTABLE</span>';
else if(unicornsInside>=3) pill.innerHTML='<span class="pill pill3">💥 EVENT!</span>';
else pill.innerHTML='';
document.getElementById('sCats').textContent=stats.catastrophes;
document.getElementById('sSinceC').textContent=customersSinceCat;
document.getElementById('sSinceT').textContent=Math.floor(timeSinceCat)+'s';
// sanity
let sanity = catastropheActive? 0 : Math.max(0, 100 - unicornsInside*35 - queue.length*2);
document.getElementById('sSanity').textContent=sanity.toFixed(0)+'%';
document.getElementById('sSanityFill').style.width=sanity+'%';
document.getElementById('sStress').textContent= sanity>70?'calm': sanity>40?'nervous': sanity>10?'panicked':'GONE';
let contain = catastropheActive? 0 : Math.max(0, 100 - unicornsInside*30 - (unicornsInside===2?20:0));
document.getElementById('sContain').textContent=contain.toFixed(0)+'%';
document.getElementById('sContainFill').style.width=contain+'%';
document.getElementById('sIntegrity').textContent= contain>80?'stable': contain>50?'cracking': contain>20?'failing':'COLLAPSED';
}
// controls
document.getElementById('speed').addEventListener('input', e=>{
speed=parseFloat(e.target.value);
document.getElementById('speedVal').textContent=speed+'×';
});
document.getElementById('btnPause').addEventListener('click', ()=>{
paused=!paused;
document.getElementById('btnPause').textContent= paused? '▶ Resume' : '⏸ Pause';
});
document.getElementById('btnFast').addEventListener('click', ()=>{
speed=5; document.getElementById('speed').value=5; document.getElementById('speedVal').textContent='5×';
});
document.getElementById('btnAdd').addEventListener('click', ()=>{
for(let i=0;i<5;i++){
let c=new Customer(nextId++);
stats.spawned++; customers.push(c); queue.push(c);
}
updateQueuePositions();
log('Manager added 5 customers to queue (cheating a little).');
});
document.getElementById('btnReset').addEventListener('click', ()=>{
stats={served:0, unicorns:0, catastrophes:0, spawned:stats.spawned};
timeSinceCat=0; customersSinceCat=0;
log('Stats reset (shop keeps running).');
});
// loop
let last=performance.now();
function loop(now){
let dt=(now-last)/1000;
last=now;
if(!paused){
dt*=speed;
// cap dt to avoid huge jumps at high speed
if(dt>0.1) dt=0.1;
timeSinceCat+=dt;
trySpawn(dt);
tryEnter();
updateBarista(dt);
customers.forEach(c=>c.update(dt));
checkCatastrophe();
updateCatastrophe(dt);
updateParticles(dt);
cleanup();
}
draw();
updateStatsDOM();
requestAnimationFrame(loop);
}
log('Shop opened! Promotion: 1 in 6 Frappuccinos is a NEON UNICORN. Good luck, barista.');
requestAnimationFrame(loop);
// handle canvas click to add customer
canvas.addEventListener('click', ()=>{
let c=new Customer(nextId++);
stats.spawned++; customers.push(c); queue.push(c);
updateQueuePositions();
});
})();
</script>
</body>
</html>
In the first 2–3 minutes at 1× you’ll see a steady queue outside, the barista serving about one drink every 1.3s, and customers lingering ~6s with their cups. The observed unicorn rate wobbles around 16.67% and the “unicorns inside” counter flickers 0→1→0, occasionally hitting 2 (flashing, shaking, cracking walls) and then — with no timer — 3 overlap and the shop collapses into rubble while a giant rainbow-maned unicorn does a wobbly dance for ~5s before the shop rebuilds and the counters keep running. I tuned only the dwell/service timings to make catastrophes watchable (longer dwell = more overlap) and did not nudge the die: every drink is Math.random() < 1/6 at the counter, logged, and the event fires only because three holders are present. Special-cased: customers panic-flee during the event, the barista aborts the current drink honestly (still rolling), and debris/particles are procedural. What it does badly: customers clip through each other and the counter queue can look messy; at 10× physics stutters and the queue can spill off-screen; the “building” is just flat rectangles so collapse is crude; the giant unicorn is charmingly ugly; and because it’s real binomial variance, you can get two catastrophes in 20 seconds or a 3-minute drought — that’s the point, leave it running and watch the counters.