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 the timings in the file, arrivals are exponential with mean 3.5 s, so λ = 0.286 customers/s. The counter takes uniform 2–4 s per drink (mean 3 s, capacity 0.333/s, utilisation about 0.86), so the queue stays short and the 8-person cap rarely binds. Each drink is a Neon Unicorn with p = 1/6, so unicorns come out at λ/6 = 0.0476/s. A holder stays 4–8 s (mean 6 s) after receiving it, so by Little's law the expected number of unicorn holders inside is 0.0476 × 6 = 0.286. A catastrophe fires when a unicorn is handed out while exactly two other holders are inside. Treating holders as Poisson with mean 0.286, P(exactly two) = e^−0.286 × 0.286²/2 ≈ 0.031, so the catastrophe rate is 0.0476 × 0.031 ≈ 0.00146/s. That is a mean gap of about 685 s, or 11.4 minutes. Customers per catastrophe = λ × 685 ≈ 196. The cross-check 1/(p × P(two others)) = 1/(0.1667 × 0.0307) ≈ 195 agrees. So expect roughly 195 customers and 33 Neon Unicorns between disasters. The Poisson step is an approximation, since sip times and service spacing are not Poisson, so real gaps will vary. If the process is roughly memoryless, about one gap in seven will exceed twice the mean.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Bloom & Brew — Neon Unicorn Promotion</title>
<style>
*{box-sizing:border-box}
body{margin:0;background:#07060f;color:#e9e6ff;font:14px/1.4 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif}
#wrap{max-width:1000px;margin:0 auto;padding:12px}
h1{font-size:18px;margin:4px 0 8px;letter-spacing:.08em;color:#ffd9f5;text-transform:uppercase}
#stage{width:100%;aspect-ratio:800/520;display:block;border-radius:10px;background:#000;box-shadow:0 0 0 1px #2a2450,0 0 40px #3b0a5a66}
.bar{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin:10px 0}
button{background:#1d1640;color:#e9e6ff;border:1px solid #4b3d8f;border-radius:6px;padding:6px 10px;cursor:pointer;font:inherit}
button:hover{border-color:#ff7cf0}
button.on{background:#7a2bd6;border-color:#c07bff}
#ffbtn{background:#3a1040;border-color:#ff5ce0}
.k{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:#9f95d6}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:8px}
.card{background:#120e26;border:1px solid #2c2358;border-radius:8px;padding:8px 10px}
.v{font-size:20px;font-variant-numeric:tabular-nums;color:#fff}
.s{font-size:11px;color:#9f95d6}
#log{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:12px;white-space:pre;background:#0c0a1b;border:1px solid #2c2358;border-radius:8px;padding:8px;height:150px;overflow:hidden;margin-top:8px;color:#cfc8ff}
</style>
</head>
<body>
<div id="wrap">
<h1>Bloom & Brew · Neon Unicorn Promotion</h1>
<canvas id="stage" width="800" height="520"></canvas>
<div class="bar">
<span class="k">Speed</span>
<button data-sp="0">Pause</button>
<button data-sp="1" class="on">1×</button>
<button data-sp="4">4×</button>
<button data-sp="16">16×</button>
<button data-sp="64">64×</button>
<button data-sp="256">256×</button>
<button id="ffbtn">Fast-forward to next disaster</button>
</div>
<div class="grid">
<div class="card"><div class="k">Frappuccinos served</div><div class="v" id="sv">0</div></div>
<div class="card"><div class="k">Neon Unicorns produced</div><div class="v" id="uv">0</div><div class="s" id="us">0 in the room now</div></div>
<div class="card"><div class="k">Observed unicorn rate</div><div class="v" id="rate">—</div><div class="s" id="rsub">true odds 16.67%</div></div>
<div class="card"><div class="k">Inside now</div><div class="v" id="inside">0 / 8</div><div class="s" id="insub"></div></div>
<div class="card"><div class="k">Catastrophes</div><div class="v" id="cat">0</div><div class="s">theory: one per ~195 customers</div></div>
<div class="card"><div class="k">Customers since last catastrophe</div><div class="v" id="since">0</div><div class="s" id="avg">average gap —</div></div>
<div class="card"><div class="k">Longest gap</div><div class="v" id="drought">0</div><div class="s">customers between disasters</div></div>
<div class="card"><div class="k">Near-misses</div><div class="v" id="near">0</div><div class="s">moments with exactly 2 unicorns inside</div></div>
<div class="card"><div class="k">Peak unicorns in room</div><div class="v" id="peak">0</div></div>
<div class="card"><div class="k">Cups lost</div><div class="v" id="cups">0</div><div class="s" id="evic">0 customers evacuated</div></div>
<div class="card"><div class="k">Insurance claims</div><div class="v" id="claims">$0</div></div>
<div class="card"><div class="k">Yelp rating</div><div class="v" id="stars">5.0 ★</div><div class="s" id="clock">sim 0:00:00</div></div>
</div>
<div id="log"></div>
</div>
<script>
(function(){
'use strict';
const W=800,H=520,DT=1/60;
const P_UNI=1/6, CAP=8, ARR_MEAN=3.5, SERV_MIN=2, SERV_MAX=4, SIP_MIN=4, SIP_MAX=8;
const EV_RUMBLE=1.8, EV_DANCE=2.6, EV_UNI=9.6, EV_END=11.6;
const DOOR={x:400,y:424}, SERVE={x:400,y:262};
const SLOTS=[[205,330],[315,330],[425,330],[535,330],[205,398],[315,398],[425,398],[535,398]];
const WALL='#17203a', TRIM='#3be3c6';
const $=id=>document.getElementById(id);
const cv=$('stage'), ctx=cv.getContext('2d');
const DPR=Math.max(1,Math.min(2,window.devicePixelRatio||1));
cv.width=W*DPR; cv.height=H*DPR;
const clamp=(v,a,b)=>Math.max(a,Math.min(b,v));
const rnd=(a,b)=>a+Math.random()*(b-a);
const hue=h=>((h%360)+360)%360;
const col=(h,s,l,a)=>a===undefined?`hsl(${hue(h).toFixed(0)},${s}%,${l}%)`:`hsla(${hue(h).toFixed(0)},${s}%,${l}%,${a})`;
const expo=m=>-Math.log(1-Math.random())*m;
function fmtT(s){s=Math.floor(s);const h=Math.floor(s/3600),m=Math.floor(s%3600/60),x=s%60;return `${h}:${String(m).padStart(2,'0')}:${String(x).padStart(2,'0')}`;}
const S={t:0,served:0,uni:0,cats:0,near:0,peak:0,sinceCat:0,drought:0,sumGaps:0,cups:0,evicted:0,claims:0,
nextArr:0.5,doorCd:0,mode:'run',evT:0,blasted:false,rebuilding:false,lastEv:0,
level:0,instab:0,flash:0,ff:false,speed:1,ffSteps:0};
let customers=[],lineArr=[],queue=[],counter=null,shards=[],cracks=[],parts=[],logs=[],nextId=1;
const slotUsed=[false,false,false,false,false,false,false,false];
const stars=[];for(let i=0;i<80;i++)stars.push({x:Math.random()*W,y:Math.random()*90,p:Math.random()*6.28});
function log(m){logs.unshift(`[${fmtT(S.t)}] ${m}`);if(logs.length>80)logs.length=80;}
function addPart(x,y,vx,vy,g,life,h,sz){parts.push({x,y,vx,vy,g,life,max:life,hue:h,sz});}
/* ---------- population helpers ---------- */
function holders(){let n=0;for(const c of customers)if(c.inside&&c.state==='sip'&&c.hasUni)n++;return n;}
function insideCount(){let n=0;for(const c of customers)if(c.inside)n++;return n;}
function layoutLine(){lineArr.forEach((c,i)=>{c.tx=360-Math.min(i,13)*24;c.ty=452;});}
function layoutQueue(){queue.forEach((c,j)=>{c.tx=440+j*30;c.ty=262;});}
function takeSlot(){for(let i=0;i<8;i++)if(!slotUsed[i]){slotUsed[i]=true;return i;}return -1;}
function releaseSlot(c){if(c.slot>=0){slotUsed[c.slot]=false;c.slot=-1;}}
function spawn(){
const c={id:nextId++,state:'line',inside:false,x:720,y:452,tx:360,ty:452,spd:120,t:0,
hasUni:false,slot:-1,hue:rnd(0,360),ph:rnd(0,6),moving:false};
customers.push(c);lineArr.push(c);layoutLine();
}
function enter(){
const c=lineArr.shift();c.state='queue';c.inside=true;queue.push(c);
layoutQueue();layoutLine();
}
function startService(){
const c=queue.shift();layoutQueue();
c.state='serving';c.tx=SERVE.x;c.ty=SERVE.y;
counter={c,t:rnd(SERV_MIN,SERV_MAX)};
}
function finishService(){
const c=counter.c;counter=null;
const uni=Math.random()<P_UNI; // the only roll. one per drink, at the counter.
S.served++;S.sinceCat++;
c.hasUni=uni;c.state='sip';c.t=rnd(SIP_MIN,SIP_MAX);
let k=takeSlot();if(k<0)k=0;c.slot=k;c.tx=SLOTS[k][0];c.ty=SLOTS[k][1];
if(uni)S.uni++;
const h=holders();
S.peak=Math.max(S.peak,h);
if(uni)log(`#${c.id} received a NEON UNICORN. ${h} in the room.`);
if(uni&&h===2){S.near++;log('Two Neon Unicorns in the room. Nobody mentions it.');}
if(h>=3)startEvent(h);
}
function startLeave(c){
c.state='leave';c.inside=false;releaseSlot(c);
c.tx=DOOR.x;c.ty=DOOR.y+4;c.spd=130;
}
function moveAll(){
for(let i=customers.length-1;i>=0;i--){
const c=customers[i];
const dx=c.tx-c.x,dy=c.ty-c.y,d=Math.hypot(dx,dy);
c.moving=d>1;
if(d>0.001){const m=Math.min(d,c.spd*DT);c.x+=dx/d*m;c.y+=dy/d*m;}
c.ph+=DT*(c.moving?12:2);
if((c.state==='leave'||c.state==='flee')&&d<3)customers.splice(i,1);
}
}
/* ---------- catastrophe ---------- */
function makeShards(){
const out=[],cols=7,rows=5,bx=150,by=120,bw=500,bh=300,cw=bw/cols,ch=bh/rows;
for(let i=0;i<cols;i++)for(let j=0;j<rows;j++){
const hx=bx+cw*(i+.5),hy=by+ch*(j+.5);
out.push({hx,hy,x:hx,y:hy,w:cw-3,h:ch-3,vx:0,vy:0,rot:0,spin:0,col:col(rnd(222,240),45,rnd(11,20))});
}
return out;
}
function makeCracks(){
const out=[];
for(let i=0;i<7;i++){
let x=rnd(170,630),y=rnd(140,400);const pts=[[x,y]];
for(let k=0;k<5;k++){x+=rnd(-40,40);y+=rnd(-30,30);pts.push([x,y]);}
out.push(pts);
}
return out;
}
function blast(){
for(const s of shards){
const dx=s.hx-400,dy=s.hy-270,L=Math.hypot(dx,dy)||1,sp=rnd(200,520);
s.x=s.hx;s.y=s.hy;
s.vx=dx/L*sp+rnd(-60,60);
s.vy=dy/L*sp*0.8-rnd(120,320);
s.spin=rnd(-6,6);
}
for(let i=0;i<140;i++)addPart(400,270,rnd(-420,420),rnd(-420,160),260,rnd(.6,1.8),rnd(0,360),rnd(2,5));
S.flash=1;
}
function startEvent(h){
S.mode='event';S.evT=0;S.blasted=false;S.rebuilding=false;S.ff=false;
S.cats++;S.sumGaps+=S.sinceCat;S.drought=Math.max(S.drought,S.sinceCat);S.sinceCat=0;
let ev=0,cups=0;
for(const c of customers){
if(!c.inside)continue;
ev++;if(c.state==='sip'||c.state==='serving')cups++;
c.inside=false;releaseSlot(c);
c.state='flee';c.spd=280;
c.tx=c.x<400?-70:870;c.ty=rnd(440,500);
}
queue=[];counter=null;
S.lastEv=ev;S.cups+=cups;S.evicted+=ev;S.claims+=40000+9500*ev;
shards=makeShards();cracks=makeCracks();
log(`CATASTROPHE #${S.cats}: ${h} Neon Unicorns in one room. Evacuating ${ev} customers.`);
}
function endEvent(){
S.mode='run';S.evT=0;S.blasted=false;S.rebuilding=false;
shards=[];cracks=[];S.flash=0;
customers=customers.filter(c=>c.state!=='flee');
S.level=0;S.instab=0;
log('Premises rebuilt. The menu now says "Frappuccino (structurally sound)".');
}
function eventStep(){
S.evT+=DT;const e=S.evT;
if(!S.blasted&&e>=EV_RUMBLE){S.blasted=true;blast();}
if(!S.rebuilding&&S.blasted){
for(const s of shards){
s.vy+=700*DT;s.x+=s.vx*DT;s.y+=s.vy*DT;s.rot+=s.spin*DT;
const fl=500-s.h/2;
if(s.y>fl){s.y=fl;s.vy=-Math.abs(s.vy)*0.35;s.vx*=0.7;s.spin*=0.6;if(Math.abs(s.vy)<20)s.vy=0;}
}
}
if(e>=EV_UNI&&!S.rebuilding){
S.rebuilding=true;
for(const s of shards){s.vx=0;s.vy=0;}
log('Rebuild crew arrives. Grout is now glitter.');
}
if(S.rebuilding){
const k=Math.min(1,DT*2.2);
for(const s of shards){s.x+=(s.hx-s.x)*k;s.y+=(s.hy-s.y)*k;s.rot+=(0-s.rot)*k;s.spin=0;}
}
if(e>EV_DANCE&&e<EV_UNI&&Math.random()<0.5){
addPart(rnd(100,700),-10,rnd(-30,30),rnd(40,120),40,rnd(2,3.5),rnd(0,360),rnd(3,5));
}
if(e>=EV_END)endEvent();
}
/* ---------- ordinary shop ---------- */
function holderFX(){
const p=S.level>=2?0.06:0.01;
for(const c of customers){
if(!(c.inside&&c.state==='sip'&&c.hasUni))continue;
if(Math.random()<p)addPart(c.x+rnd(-6,6),c.y-8,rnd(-30,30),rnd(-60,-20),-30,rnd(.6,1.4),rnd(0,360),rnd(2,3));
}
}
function runStep(){
S.nextArr-=DT;
if(S.nextArr<=0){spawn();S.nextArr=expo(ARR_MEAN);}
if(S.doorCd>0)S.doorCd-=DT;
if(lineArr.length&&S.doorCd<=0&&insideCount()<CAP){enter();S.doorCd=0.7;}
for(const c of customers)if(c.state==='sip'){c.t-=DT;if(c.t<=0)startLeave(c);}
if(!counter&&queue.length)startService();
if(counter){counter.t-=DT;if(counter.t<=0)finishService();}
if(S.mode!=='run')return;
const h=holders();
S.level=Math.min(3,h);
if(S.level===2)S.instab=Math.min(1,S.instab+DT*0.04);
else S.instab=Math.max(0,S.instab-DT*0.08);
if(S.level>=1)holderFX();
}
function step(){
S.t+=DT;
if(S.mode==='run')runStep();else eventStep();
moveAll();
for(let i=parts.length-1;i>=0;i--){
const p=parts[i];p.x+=p.vx*DT;p.y+=p.vy*DT;p.vy+=p.g*DT;p.life-=DT;
if(p.life<=0)parts.splice(i,1);
}
if(parts.length>700)parts.splice(0,parts.length-700);
if(S.flash>0)S.flash=Math.max(0,S.flash-DT*1.5);
}
/* ---------- drawing ---------- */
function drawSky(t){
const g=ctx.createLinearGradient(0,0,0,H);
g.addColorStop(0,'#07051a');g.addColorStop(0.45,'#1b0b3a');g.addColorStop(1,'#0c0820');
ctx.fillStyle=g;ctx.fillRect(0,0,W,H);
for(const s of stars){ctx.globalAlpha=0.3+0.7*Math.abs(Math.sin(t*1.7+s.p));ctx.fillStyle='#fff';ctx.fillRect(s.x,s.y,2,2);}
ctx.globalAlpha=1;
ctx.fillStyle='#fbe9ff';ctx.beginPath();ctx.arc(720,40,16,0,Math.PI*2);ctx.fill();
}
function drawStreet(){
ctx.fillStyle='#120e26';ctx.fillRect(0,424,W,96);
ctx.fillStyle='#2b2350';ctx.fillRect(0,424,W,4);
ctx.strokeStyle='#1f1a3c';ctx.lineWidth=1;
for(let x=-40;x<W;x+=80){ctx.beginPath();ctx.moveTo(x,430);ctx.lineTo(x-20,520);ctx.stroke();}
ctx.fillStyle='#2b2350';ctx.fillRect(700,330,4,94);ctx.fillRect(694,326,16,6);
}
function drawBuilding(a,t){
ctx.save();ctx.globalAlpha=a;
const run=S.mode==='run';
const wallC=run&&S.level>=2?col(230+Math.sin(t*2.3)*60*S.instab,45,12+4*S.instab):WALL;
ctx.fillStyle=wallC;ctx.fillRect(150,120,500,300);
ctx.fillStyle='#1c1638';ctx.fillRect(152,232,496,186);
for(const x of [170,510]){
const g=ctx.createLinearGradient(0,170,0,250);
g.addColorStop(0,'rgba(255,190,110,.55)');g.addColorStop(1,'rgba(120,60,255,.25)');
ctx.fillStyle=g;ctx.fillRect(x,170,120,80);
ctx.strokeStyle='#2a2150';ctx.lineWidth=3;ctx.strokeRect(x,170,120,80);
}
for(let x=150,i=0;x<650;x+=25,i++){ctx.fillStyle=i%2?'#0f6b63':'#e8fff8';ctx.fillRect(x,120,25,16);}
// sign
ctx.fillStyle='#0c2a2c';ctx.fillRect(250,84,300,32);
ctx.strokeStyle='#ffcf6b';ctx.lineWidth=2;ctx.strokeRect(250,84,300,32);
ctx.font='bold 17px system-ui,sans-serif';ctx.textAlign='center';
ctx.fillStyle=col(180+(run&&S.level>=1?Math.sin(t*9)*140:0),100,72);
ctx.fillText('BLOOM & BREW',400,106);
// counter, machine, barista
ctx.fillStyle='#2b2145';ctx.fillRect(300,205,220,27);
ctx.strokeStyle='#ff8ae6';ctx.lineWidth=2;ctx.strokeRect(300,205,220,27);
ctx.fillStyle='#3b3f57';ctx.fillRect(318,172,40,33);
ctx.fillStyle='#ffd5b0';ctx.beginPath();ctx.arc(410,186,12,0,Math.PI*2);ctx.fill();
ctx.fillStyle='#e94bb8';ctx.fillRect(398,200,24,8);
// door
ctx.fillStyle='#24193d';ctx.fillRect(380,380,40,44);
ctx.strokeStyle=TRIM;ctx.lineWidth=2;ctx.strokeRect(380,380,40,44);
// trim, plus neon halo at level 1+
ctx.strokeStyle=TRIM;ctx.strokeRect(150,120,500,300);
if(run&&S.level>=1){
ctx.save();ctx.shadowBlur=18+S.level*8;ctx.shadowColor=col(300+t*50,100,60);
ctx.strokeStyle=col(300+t*50,100,65,0.35+0.2*Math.sin(t*6));ctx.lineWidth=3;
ctx.strokeRect(150,120,500,300);ctx.restore();
}
ctx.restore();
}
function drawCracks(f){
if(!cracks.length)return;
ctx.save();ctx.strokeStyle='#ffe9ff';ctx.lineWidth=1.5;ctx.shadowBlur=6;ctx.shadowColor='#ff5ce0';
for(const pts of cracks){
ctx.beginPath();
const n=Math.max(2,Math.floor(pts.length*f));
for(let i=0;i<n&&i<pts.length;i++){const[x,y]=pts[i];i?ctx.lineTo(x,y):ctx.moveTo(x,y);}
ctx.stroke();
}
ctx.restore();
}
function drawShards(){
for(const s of shards){
ctx.save();ctx.translate(s.x,s.y);ctx.rotate(s.rot);
ctx.fillStyle=s.col;ctx.fillRect(-s.w/2,-s.h/2,s.w,s.h);
ctx.strokeStyle='rgba(255,92,224,.6)';ctx.lineWidth=1;ctx.strokeRect(-s.w/2,-s.h/2,s.w,s.h);
ctx.restore();
}
}
function drawRays(e,t){
const a=clamp((e-EV_RUMBLE-0.6)/0.6,0,1)*clamp((EV_END-e)/2,0,1);
if(a<=0)return;
ctx.save();ctx.translate(400,300);
for(let k=0;k<12;k++){
const ang=t*0.6+k*Math.PI/6;
ctx.strokeStyle=col(t*120+k*30,100,60,0.22*a);ctx.lineWidth=18;
ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(Math.cos(ang)*900,Math.sin(ang)*900);ctx.stroke();
}
ctx.restore();
}
function drawLineLabel(){
if(lineArr.length>13){
ctx.fillStyle='#cfc8ff';ctx.font='12px system-ui,sans-serif';ctx.textAlign='left';
ctx.fillText(`+${lineArr.length-13} more in line`,20,486);
}
}
function drawCustomer(c,t){
const holding=c.hasUni&&(c.state==='sip'||c.state==='leave'||c.state==='flee');
const bob=c.moving?Math.abs(Math.sin(c.ph))*3:0;
const jit=(holding&&S.mode==='run'&&S.level>=2)?rnd(-1,1)*S.instab*3:0;
const x=c.x+jit,y=c.y-bob,h=t*160+c.id*53;
ctx.save();
if(holding){ctx.shadowBlur=16;ctx.shadowColor=col(h,100,60);ctx.fillStyle=col(h,100,68);}
else ctx.fillStyle=col(c.hue,55,72);
ctx.beginPath();ctx.arc(x,y,9,0,Math.PI*2);ctx.fill();
if(holding){
ctx.fillStyle=col(h+60,100,78);
ctx.beginPath();ctx.moveTo(x-4,y-7);ctx.lineTo(x+4,y-7);ctx.lineTo(x,y-19);ctx.closePath();ctx.fill();
}
if(c.state==='sip'||c.state==='leave'||c.state==='flee'){
ctx.shadowBlur=0;
ctx.fillStyle=holding?col(h+120,100,70):'#e8d9c7';
ctx.fillRect(x+7,y-2,6,9);
}
ctx.restore();
}
function eventUnicorn(e,t){
const s=Math.min(clamp((e-2.0)/0.8,0,1),clamp((EV_END-e)/2,0,1));
if(s<=0.01)return;
const h=t*120;
ctx.save();
ctx.translate(400,300+Math.sin(t*6)*9*s);
ctx.rotate(Math.sin(t*4)*0.05);
ctx.scale(s,s);
ctx.shadowBlur=28;ctx.shadowColor=col(h,100,60);
for(let i=0;i<4;i++){
const lx=[-92,-48,52,96][i];
const ang=Math.sin(t*8+(i%2)*Math.PI+i*0.5)*0.45;
ctx.save();ctx.translate(lx,30);ctx.rotate(ang);
ctx.fillStyle=col(h+i*40,100,74);ctx.fillRect(-8,0,16,92);
ctx.restore();
}
ctx.lineCap='round';ctx.lineWidth=9;
for(let k=0;k<5;k++){
ctx.strokeStyle=col(h+k*35,100,68);
ctx.beginPath();ctx.moveTo(-120,-8+k*4);
ctx.bezierCurveTo(-170,-30+Math.sin(t*5+k)*18,-205,8+k*6,-178,42+k*6+Math.sin(t*4+k)*10);
ctx.stroke();
}
ctx.fillStyle=col(h,90,84);
ctx.beginPath();ctx.ellipse(0,0,130,56,0,0,Math.PI*2);ctx.fill();
ctx.beginPath();ctx.ellipse(104,-44,34,42,0.5,0,Math.PI*2);ctx.fill();
ctx.beginPath();ctx.arc(136,-80,34,0,Math.PI*2);ctx.fill();
ctx.fillStyle=col(h+20,90,90);
ctx.beginPath();ctx.ellipse(164,-64,16,12,0,0,Math.PI*2);ctx.fill();
ctx.shadowBlur=18;ctx.shadowColor=col(50,100,60);
ctx.fillStyle=col(48,100,68);
ctx.beginPath();ctx.moveTo(124,-108);ctx.lineTo(146,-108);ctx.lineTo(166,-172);ctx.closePath();ctx.fill();
ctx.shadowBlur=28;ctx.shadowColor=col(h,100,60);
ctx.fillStyle='#120a2a';ctx.beginPath();ctx.arc(148,-88,5,0,Math.PI*2);ctx.fill();
ctx.fillStyle='#fff';ctx.beginPath();ctx.arc(149.5,-89.5,1.8,0,Math.PI*2);ctx.fill();
ctx.lineWidth=9;
for(let k=0;k<7;k++){
ctx.strokeStyle=col(h+k*40,100,70);
ctx.beginPath();ctx.moveTo(122-k*13,-106+k*5);
ctx.bezierCurveTo(100-k*13,-140+Math.sin(t*6+k)*14,70-k*13,-90+Math.sin(t*5+k*1.3)*10,40-k*13,-58+k*8);
ctx.stroke();
}
ctx.restore();
}
function eventSub(e){
if(e<0.9)return 'Three Neon Unicorns. One room. Nobody ran the numbers.';
if(e<EV_RUMBLE+0.2)return 'The frosting has opinions.';
if(e<EV_DANCE)return 'Structural containment: none.';
if(e<EV_UNI)return `It is dancing. ${S.lastEv} customers evacuated, none asked to stay.`;
return 'Rebuilding the premises. The grout is now glitter.';
}
function drawEventText(e,t){
if(e<0.2)return;
const a=clamp((e-0.2)/0.4,0,1)*clamp((EV_END-e)/0.8,0,1);
ctx.save();ctx.globalAlpha=a;ctx.textAlign='center';
const gl=Math.random()<0.25, dx=gl?rnd(-6,6):0;
ctx.font='900 40px system-ui,sans-serif';
ctx.fillStyle=col(t*200,100,70);ctx.fillText('NEON UNICORN EVENT',400+dx,50);
if(gl){ctx.fillStyle='rgba(0,255,255,.7)';ctx.fillText('NEON UNICORN EVENT',400-dx*1.5,50);}
ctx.font='600 16px system-ui,sans-serif';ctx.fillStyle='#fff';
ctx.fillText(eventSub(e),400,78);
ctx.restore();
}
function drawParts(){
for(const p of parts){
ctx.fillStyle=col(p.hue,100,70,clamp(p.life/p.max,0,1));
ctx.fillRect(p.x-p.sz/2,p.y-p.sz/2,p.sz,p.sz);
}
}
function drawHUD(){
const h=holders();
ctx.save();
ctx.font='bold 12px system-ui,sans-serif';ctx.textAlign='left';
ctx.fillStyle='#cfc8ff';ctx.fillText(`UNICORNS IN ROOM ${h}/3`,14,20);
for(let i=0;i<3;i++){
ctx.fillStyle=i<h?col(S.t*200+i*60,100,70):'#2a2450';
ctx.beginPath();ctx.arc(20+i*18,38,6,0,Math.PI*2);ctx.fill();
}
const names=['all quiet','a suspicious glow','UNSTABLE COINCIDENCE'];
ctx.fillStyle=S.level>=2?col(S.t*300,100,70):'#9f95d6';
ctx.fillText(names[Math.min(2,S.level)],14,62);
ctx.restore();
}
function drawOverlays(t){
if(S.mode==='run'&&S.level>=2){
ctx.fillStyle=col(t*90,100,50,0.05+S.instab*0.1);ctx.fillRect(0,0,W,H);
if(Math.floor(t*8)%2===0){ctx.fillStyle=`rgba(255,255,255,${0.02+S.instab*0.05})`;ctx.fillRect(0,0,W,H);}
}else if(S.mode==='run'&&S.level===1){
ctx.fillStyle=col(t*60,100,60,0.04);ctx.fillRect(0,0,W,H);
}
if(S.flash>0){ctx.fillStyle=`rgba(255,240,255,${S.flash*0.85})`;ctx.fillRect(0,0,W,H);}
}
function render(){
const t=S.t,e=S.evT,ev=S.mode==='event';
ctx.setTransform(DPR,0,0,DPR,0,0);
ctx.fillStyle='#07051a';ctx.fillRect(0,0,W,H);
let sh=0;
if(!ev){if(S.level>=2)sh=2+S.instab*9;}
else if(e<EV_RUMBLE)sh=2+e*6;
else if(e<EV_RUMBLE+0.6)sh=20*(1-(e-EV_RUMBLE)/0.6);
else if(e<EV_UNI)sh=1.2;
ctx.save();
if(sh>0)ctx.translate(rnd(-sh,sh),rnd(-sh,sh));
drawSky(t);drawStreet();
if(!ev)drawBuilding(1,t);
else{
if(e<EV_RUMBLE){drawBuilding(1,t);drawCracks(clamp(e/EV_RUMBLE,0,1));}
else if(e>=EV_UNI)drawBuilding(clamp((e-EV_UNI)/(EV_END-EV_UNI),0,1)*0.9,t);
if(e>=EV_RUMBLE)drawShards();
drawRays(e,t);
}
drawLineLabel();
for(const c of customers)drawCustomer(c,t);
if(ev)eventUnicorn(e,t);
drawParts();
ctx.restore();
drawOverlays(t);
if(ev)drawEventText(e,t);else drawHUD();
}
/* ---------- UI ---------- */
const spBtns=[...document.querySelectorAll('[data-sp]')];
function markSpeed(){spBtns.forEach(b=>b.classList.toggle('on',+b.dataset.sp===S.speed));}
spBtns.forEach(b=>b.onclick=()=>{S.speed=+b.dataset.sp;markSpeed();});
$('ffbtn').onclick=()=>{
if(S.mode!=='run')return;
if(S.speed===0){S.speed=1;markSpeed();}
S.ff=true;S.ffSteps=0;
};
function updStats(){
const h=holders(),ins=insideCount(),r=S.served?S.uni/S.served:0;
$('sv').textContent=S.served;
$('uv').textContent=S.uni;
$('us').textContent=`${h} in the room right now`;
$('rate').textContent=S.served?(r*100).toFixed(2)+'%':'—';
if(S.served){const d=(r-P_UNI)*100;$('rsub').textContent=`true odds 16.67% · off by ${d>=0?'+':''}${d.toFixed(2)} pts`;}
else $('rsub').textContent='true odds 16.67%';
$('inside').textContent=`${ins} / ${CAP}`;
$('insub').textContent=`${queue.length} queued · ${lineArr.length} outside`;
$('cat').textContent=S.cats;
$('since').textContent=S.sinceCat;
$('avg').textContent=`average gap ${S.cats?Math.round(S.sumGaps/S.cats):'—'}`;
$('drought').textContent=S.drought;
$('near').textContent=S.near;
$('peak').textContent=S.peak;
$('cups').textContent=S.cups;
$('evic').textContent=`${S.evicted} customers evacuated`;
$('claims').textContent='$'+S.claims.toLocaleString('en-US');
$('stars').textContent=Math.max(0.5,5-0.4*S.cats).toFixed(1)+' ★';
$('clock').textContent='sim '+fmtT(S.t);
$('ffbtn').textContent=S.ff?'Searching… '+fmtT(S.t):'Fast-forward to next disaster';
$('log').textContent=logs.slice(0,8).join('\n');
}
let lastNow=performance.now(),acc=0,statTimer=0;
function frame(now){
const rdt=Math.min(0.1,Math.max(0,(now-lastNow)/1000));lastNow=now;
if(S.ff&&S.mode==='run'){
let n=0;
while(S.ff&&S.mode==='run'&&n<300000){step();n++;}
S.ffSteps+=n;
}else{
acc+=rdt*S.speed;
let n=0;
while(acc>=DT&&n<4000){step();acc-=DT;n++;}
if(acc>DT)acc=0;
}
render();
statTimer-=rdt;
if(statTimer<=0){statTimer=0.2;updStats();}
requestAnimationFrame(frame);
}
log('Doors open. The Neon Unicorn promotion is live. Nothing has gone wrong yet.');
markSpeed();updStats();
requestAnimationFrame(frame);
})();
</script>
</body>
</html>
First few minutes. Customers trickle in roughly every 3.5 seconds. The counter settles at about 85% utilisation, so the queue wobbles between zero and three or four, and the eight-person cap is only occasionally reached. Unicorns come out about every 21 seconds on average. About a quarter of the time someone is holding one and the shop glows faintly. A near-miss (two inside at once) lands about every 1.5 minutes, which is where the first shake and strobe show up. Over five minutes the chance of no catastrophe is about 64%, so the most likely outcome is a quiet first few minutes with some glow and some near-misses.
Things I tuned, special-cased or nudged:
Math.random() < 1/6 at the moment of service. The timings (arrival mean, service range, sip range) were chosen to keep the counter busy but not saturated. They set the catastrophe rate, not the probability.What it does badly, since you're going to leave it running:
Math.random, so you can't reproduce a run.