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
30:00Did Elon Musk's team "train the gay away"... and make Grok 4.7 worse?
Sep 26, 2026 · YouTube
19:21I Tested the Stealth "Space Bunny Alpha" Model Before It Went Offline
Sep 23, 2026 · YouTube
10:58So... how much better is Claude Opus 5.5 vs. GPT-6 Sol, really?
Sep 23, 2026 · YouTube
9:38Claude Opus 5.5... the BEST new model for coding!! 🤩
Sep 22, 2026 · YouTube
29:00Grok 4.7: improved, but GLM 5.3 FlashX beat it anyway (benchmark against Gemini, Sol, etc.)
Sep 22, 2026 · YouTube
You write simulations where the interesting behavior is supposed to emerge rather than be animated by hand.
Build me a single HTML page: a side-view escalator carrying 15 to 20 people. Then the escalator reverses, at high speed.
data: URIs are fine.localStorage, sessionStorage, cookies or indexedDB — sandboxed frame, they throw.html block.One paragraph, before the file: how a person is represented, what makes one lose balance, and what happens when two of them occupy the same place.
The single fenced html block.
Having written it, what does the page do when the escalator reverses? Name anything you special-cased or nudged. Say what it does badly — I am going to press the button and watch.
Each person is a single rigid stick figure with a centre of mass, velocity, lean angle and angular velocity, represented for collision by one circle when upright and two circles along the body when falling or down, with feet constrained to a polyline escalator surface when standing; standing balance is a damped spring for lean driven by the tangential acceleration of the belt, so a fast belt reversal produces a large inertial torque, and a person becomes falling when lean or angular velocity exceeds a threshold or a collision impulse knocks them, after which all persons are dynamic bodies under gravity, surface contact with belt friction/drag, and circle-circle positional and impulse resolution against every other person, with down bodies acting as elongated obstacles that trip arriving standing bodies, and a down body only rises when its speed is low, it has been down long enough, and no neighbour is within a clearance radius, at which point it is re-anchored to the surface as standing.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Crouton Alpha — Escalator Reversal</title>
<style>
html,body{margin:0;background:#111;color:#eee;font-family:system-ui,sans-serif}
#wrap{max-width:760px;margin:12px auto;padding:0 10px}
canvas{display:block;width:100%;background:#1b2430;border:1px solid #445;border-radius:8px}
button{font-size:16px;padding:10px 18px;margin:10px 0;border-radius:6px;border:1px solid #888;background:#2a3a4d;color:#fff;cursor:pointer}
button.rev{background:#7a2a1e}
#info{font-size:13px;color:#cbd5e1;min-height:18px}
</style>
</head>
<body>
<div id="wrap">
<h2 style="margin:6px 0">Escalator — reversal simulation</h2>
<button id="btn">Reverse escalator</button>
<span id="info"></span>
<canvas id="c" width="720" height="500"></canvas>
<p style="font-size:12px;color:#94a3b8">No scripted falls: press Reverse, watch the pile form, press again to restore. People get up only when there is room.</p>
</div>
<script>
(function(){
"use strict";
const cv=document.getElementById('c'), ctx=cv.getContext('2d');
const btn=document.getElementById('btn'), info=document.getElementById('info');
// Surface polyline: bottom flat, incline, top flat
const P=[[0,430],[95,430],[615,190],[720,190]];
const segs=[]; let total=0;
for(let i=0;i<P.length-1;i++){
const dx=P[i+1][0]-P[i][0], dy=P[i+1][1]-P[i][1], len=Math.hypot(dx,dy);
segs.push({x1:P[i][0],y1:P[i][1],x2:P[i+1][0],y2:P[i+1][1],dx:dx/len,dy:dy/len,len:len,start:total});
total+=len;
}
function pointAt(s){
s=((s%total)+total)%total;
for(const g of segs){ if(s<=g.start+g.len){ const t=s-g.start; return {x:g.x1+g.dx*t,y:g.y1+g.dy*t,tx:g.dx,ty:g.dy,s:s}; } }
const g=segs[segs.length-1]; return {x:g.x2,y:g.y2,tx:g.dx,ty:g.dy,s:s};
}
function closest(x,y){
let best=null,bd=1e9;
for(const g of segs){
let t=((x-g.x1)*g.dx+(y-g.y1)*g.dy); t=Math.max(0,Math.min(g.len,t));
const cx=g.x1+g.dx*t, cy=g.y1+g.dy*t, d=Math.hypot(x-cx,y-cy);
if(d<bd){bd=d;best={x:cx,y:cy,s:g.start+t,tx:g.dx,ty:g.dy,dist:d};}
}
return best;
}
// Belt
let reversed=false, beltSpeed=45, beltAccel=0, beltPhase=0;
const NORMAL=45, REV=-175;
// People
const N=18, people=[];
const palette=['#f87171','#fbbf24','#34d399','#60a5fa','#f472b6','#a78bfa','#facc15','#4ade80','#fb923c','#38bdf8'];
for(let i=0;i<N;i++){
const s=segs[1].start+30+i*((segs[1].len-60)/(N-1));
const pt=pointAt(s);
people.push({x:pt.x,y:pt.y-17,vx:0,vy:0,theta:0,thetaVel:0,state:'stand',s:s,t:0,riseT:0,seed:Math.random()*10,color:palette[i%palette.length],contact:0,downT:0});
}
function axis(p){ return {x:Math.sin(p.theta), y:-Math.cos(p.theta)}; }
function circles(p){
if(p.state==='stand'||p.state==='rise') return [{x:p.x,y:p.y,r:11}];
const a=axis(p); return [{x:p.x-a.x*11,y:p.y-a.y*11,r:9.5},{x:p.x+a.x*11,y:p.y+a.y*11,r:9.5}];
}
function knock(p,dir,kick){
if(p.state!=='stand') return;
p.state='fall'; p.t=0; p.contact=0;
const pt=pointAt(p.s); p.vx=pt.tx*beltSpeed; p.vy=pt.ty*beltSpeed;
p.thetaVel=(dir||1)*(1.5+Math.abs(kick||0)*0.01);
if(Math.abs(p.thetaVel)<1.2) p.thetaVel=1.2*Math.sign(dir||1);
}
function nearestDist(p){
let m=1e9; for(const q of people){ if(q!==p) m=Math.min(m,Math.hypot(p.x-q.x,p.y-q.y)); } return m;
}
function step(dt){
// belt dynamics: fast, clamped acceleration
const target=reversed?REV:NORMAL;
beltAccel=Math.max(-1900,Math.min(1900,(target-beltSpeed)*9));
beltSpeed+=beltAccel*dt; beltPhase+=beltSpeed*dt;
// standing
for(const p of people){
p.t+=dt;
if(p.state==='stand'){
// balance spring + inertial torque from belt acceleration along tangent
const pt=pointAt(p.s);
const a_t=beltAccel; // belt accel is along tangent by construction
p.thetaVel+=(-28*p.theta-7*p.thetaVel - a_t/26)*dt;
p.theta+=p.thetaVel*dt;
p.s+=beltSpeed*dt; // wrap = looped escalator (special case, see notes)
const np=pointAt(p.s), a=axis(p);
p.x=np.x+a.x*17; p.y=np.y+a.y*17; p.vx=np.tx*beltSpeed; p.vy=np.ty*beltSpeed;
if(Math.abs(p.theta)>0.48||Math.abs(p.thetaVel)>2.8) knock(p, Math.sign(p.thetaVel||p.theta||1),0);
} else if(p.state==='rise'){
p.riseT+=dt/0.75;
const cl=closest(p.x,p.y), a=axis(p);
const tx=cl.x+a.x*17, ty=cl.y+a.y*17;
p.x+=(tx-p.x)*Math.min(1,10*dt); p.y+=(ty-p.y)*Math.min(1,10*dt);
p.theta*=(1-Math.min(1,8*dt)); p.thetaVel*=0.8;
if(nearestDist(p)<30){ p.state='down'; p.downT=0; }
else if(p.riseT>=1){ p.state='stand'; p.s=cl.s; p.theta=0; p.thetaVel=0; }
} else { // fall / down : dynamic
p.vy+=920*dt;
p.x+=p.vx*dt; p.y+=p.vy*dt;
const targetA=Math.sign(p.thetaVel||p.theta||1)*1.45;
p.thetaVel+=((targetA-p.theta)*10 - p.thetaVel*3.5)*dt;
p.theta+=p.thetaVel*dt;
// surface collision
const cl=closest(p.x,p.y), r=10;
p.contact=0;
if(cl.dist<r && cl.dist>0.001){
const nx=(p.x-cl.x)/cl.dist, ny=(p.y-cl.y)/cl.dist;
p.x=cl.x+nx*r; p.y=cl.y+ny*r;
const vn=p.vx*nx+p.vy*ny;
if(vn<0){
p.vx-=vn*nx*1.25; p.vy-=vn*ny*1.25; // restitution ~0.25
if(Math.abs(vn)>180) p.thetaVel+= (Math.random()-0.5)*2;
}
// friction + belt drag along tangent
const tx=cl.tx, ty=cl.ty, vt=p.vx*tx+p.vy*ty;
const drag=(beltSpeed-vt)*Math.min(1,7*dt);
p.vx+=tx*drag; p.vy+=ty*drag;
p.vx*= (1-1.2*dt); p.vy*=(1-0.4*dt);
p.contact=1;
}
p.x=Math.max(12,Math.min(708,p.x)); p.y=Math.min(470,p.y);
if(p.state==='fall'){
if(p.contact) p.contact+=dt;
if((Math.abs(p.theta-targetA)<0.3 && p.contact>0.25) || (p.contact>0.6 && Math.hypot(p.vx,p.vy)<90)){
p.state='down'; p.downT=0;
}
} else if(p.state==='down'){
p.downT+=dt;
const sp=Math.hypot(p.vx,p.vy);
if(p.downT>0.9 && sp<28 && nearestDist(p)>44 && p.contact){
p.state='rise'; p.riseT=0;
}
}
}
}
// collisions (emergent pile / tripping)
for(let i=0;i<people.length;i++) for(let j=i+1;j<people.length;j++){
const a=people[i], b=people[j];
const ca=circles(a), cb=circles(b);
for(const u of ca) for(const v of cb){
const dx=v.x-u.x, dy=v.y-u.y, d=Math.hypot(dx,dy), min=u.r+v.r;
if(d<min && d>0.001){
const nx=dx/d, ny=dy/d, overlap=min-d;
const aDyn=a.state!=='stand'&&a.state!=='rise', bDyn=b.state!=='stand'&&b.state!=='rise';
if(aDyn&&bDyn){
a.x-=nx*overlap*0.5; a.y-=ny*overlap*0.5; b.x+=nx*overlap*0.5; b.y+=ny*overlap*0.5;
const rvx=b.vx-a.vx, rvy=b.vy-a.vy, vn=rvx*nx+rvy*ny;
if(vn<0){ const imp=-vn*0.6; a.vx-=nx*imp; a.vy-=ny*imp; b.vx+=nx*imp; b.vy+=ny*imp; a.thetaVel+=nx*0.02; b.thetaVel-=nx*0.02; }
} else if(aDyn&&!bDyn){
// dynamic hits standing: trip it if overlap is substantial
if(overlap>2.5) knock(b, Math.sign((a.vx-b.vx)||nx||1), Math.abs(a.vx));
a.x-=nx*overlap; a.y-=ny*overlap;
} else if(!aDyn&&bDyn){
if(overlap>2.5) knock(a, Math.sign((b.vx-a.vx)||-nx||1), Math.abs(b.vx));
b.x+=nx*overlap; b.y+=ny*overlap;
} else {
// both standing and overlapping (queue compression): rear one is knocked
if(overlap>4) knock(b,1,0);
}
}
}
}
}
function draw(){
ctx.clearRect(0,0,720,500);
// background
ctx.fillStyle='#1b2430'; ctx.fillRect(0,0,720,500);
// escalator truss
ctx.beginPath(); ctx.moveTo(0,430); ctx.lineTo(95,430); ctx.lineTo(615,190); ctx.lineTo(720,190); ctx.lineTo(720,500); ctx.lineTo(0,500); ctx.closePath();
ctx.fillStyle='#2f3d4f'; ctx.fill(); ctx.strokeStyle='#5b6b80'; ctx.stroke();
// steps on incline
const g=segs[1];
ctx.strokeStyle='#8ea0b5'; ctx.lineWidth=2;
for(let s=g.start-20;s<g.start+g.len+20;s+=18){
const pt=pointAt(s+beltPhase); if(pt.s<g.start||pt.s>g.start+g.len) continue;
const nx=-pt.ty, ny=pt.tx;
ctx.beginPath(); ctx.moveTo(pt.x,pt.y); ctx.lineTo(pt.x+nx*6,pt.y+ny*6); ctx.stroke();
}
// handrail
ctx.strokeStyle='#cbd5e1'; ctx.lineWidth=3; ctx.beginPath();
for(let s=0;s<=total;s+=20){ const pt=pointAt(s); const nx=-pt.ty, ny=pt.tx; const x=pt.x+nx*42, y=pt.y+ny*42; s===0?ctx.moveTo(x,y):ctx.lineTo(x,y); }
ctx.stroke();
// people
for(const p of people){
const a=axis(p), head={x:p.x+a.x*22,y:p.y+a.y*22};
const feet={x:p.x-a.x*17,y:p.y-a.y*17};
const pt=pointAt(p.s||0);
ctx.strokeStyle=p.color; ctx.fillStyle=p.color; ctx.lineWidth=3; ctx.lineCap='round';
// legs
ctx.beginPath();
if(p.state==='stand'||p.state==='rise'){
const tx=pt.tx, ty=pt.ty;
ctx.moveTo(p.x,p.y); ctx.lineTo(feet.x+tx*7,feet.y+ty*7);
ctx.moveTo(p.x,p.y); ctx.lineTo(feet.x-tx*7,feet.y-ty*7);
} else {
const fl=Math.sin(p.t*9+p.seed)*6;
ctx.moveTo(p.x,p.y); ctx.lineTo(feet.x-a.x*10+fl*0.3,feet.y-a.y*10);
ctx.moveTo(p.x,p.y); ctx.lineTo(feet.x-a.x*16-fl*0.3,feet.y-a.y*16);
}
ctx.stroke();
// body
ctx.beginPath(); ctx.moveTo(feet.x,feet.y); ctx.lineTo(head.x,head.y); ctx.stroke();
// arms: flail when falling, down when standing
const amp=(p.state==='fall')?14:(p.state==='down'?4:5);
const ph=Math.sin(p.t*(p.state==='fall'?14:3)+p.seed)*amp;
const sh={x:p.x+a.x*8,y:p.y+a.y*8};
ctx.beginPath(); ctx.moveTo(sh.x,sh.y); ctx.lineTo(sh.x+ph,sh.y+14+Math.abs(ph)*0.3); ctx.stroke();
// head
ctx.beginPath(); ctx.arc(head.x,head.y,6,0,7); ctx.fill();
ctx.fillStyle='#111'; ctx.beginPath(); ctx.arc(head.x+2,head.y-1,1.2,0,7); ctx.fill();
}
const counts={stand:0,fall:0,down:0,rise:0}; people.forEach(p=>counts[p.state]++);
info.textContent='belt '+Math.round(beltSpeed)+' px/s standing '+counts.stand+' falling '+counts.fall+' down '+counts.down+' rising '+counts.rise;
}
btn.onclick=()=>{ reversed=!reversed; btn.textContent=reversed?'Restore normal direction':'Reverse escalator'; btn.classList.toggle('rev',reversed); };
let last=performance.now(), acc=0;
function frame(now){
let dt=(now-last)/1000; last=now; if(dt>0.05)dt=0.05; acc+=dt;
const h=1/240;
while(acc>h){ step(h); acc-=h; }
draw(); requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
})();
</script>
</body>
</html>
When you press Reverse, the belt target changes from +45 to -175 px/s with acceleration clamped at 1900 px/s², so it reaches full reverse in roughly a tenth of a second; the standing balance equation receives that tangential acceleration as an inertial torque, lean grows past the 0.48 rad / 2.8 rad/s threshold for essentially everyone, and they convert to falling with velocity inherited from the belt. From there nothing is timed: gravity, surface contact, belt drag on the surface, and circle-circle collisions between the two-circle falling/down bodies and the one-circle standing bodies produce sliding, tripping of the queue behind a down body, and a pile that grows because down bodies are not removed. Down bodies check speed, contact, elapsed down time, and nearest-neighbour clearance before entering the rise state, and a rise is aborted if someone closes in, so the pile gradually clears from the edges when the belt is restored or even while reversed at the bottom landing.
Special-cased or nudged, explicitly: the escalator is a loop, so standing people wrap from top to bottom (and vice versa) — without that they would all accumulate at one end; the belt acceleration is clamped and the balance spring constants, fall thresholds, collision knock overlap threshold, restitution, friction and belt-drag coefficients, and the get-up clearance/time/speed thresholds are hand-tuned constants; the rise state is a short procedural interpolation back to standing height, not a physics stand-up; limb flailing is procedural sine motion driven by state, not physics; and people are kept inside the canvas by hard x/y clamps.
What it does badly: at full reverse speed people can tunnel or jitter in the pile because collision resolution is positional with no continuous collision detection, the pile can look like it boils rather than settles, get-up can pop visibly when re-anchored, the wrap teleport is obvious at the top/bottom, everyone tends to fall almost simultaneously because they share identical balance parameters and belt acceleration (there is no per-person strength, reaction time, or handrail holding), and the stick figures have no real stepping or grabbing, so recovery is more plausible in aggregate than in any individual limb.