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 has a position and velocity along the escalator, a balance offset, and a body angle. Their feet try to match the moving steps; when the steps accelerate faster than their body can follow, that offset grows until they topple. People take up more room while down. When their occupied spaces overlap, the simulation separates them, transfers momentum, and lets the impact disturb their balance. A fallen person can get up only when the belt is no longer dragging them past their footing and there is room nearby.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Wrong Way — Escalator Simulation</title>
<style>
:root {
color-scheme: dark;
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
background: #08111c;
color: #edf5f7;
}
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
background:
radial-gradient(ellipse at 50% 12%, #173148 0, #0b1928 48%, #08111c 85%);
}
main { width: min(1400px, 100%); margin: auto; padding: 23px clamp(12px, 3vw, 42px) 28px; }
header, .controls {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
flex-wrap: wrap;
}
.eyebrow { color: #78b6c7; font-size: 11px; letter-spacing: .22em; font-weight: 800; }
h1 { margin: 4px 0 3px; font-size: clamp(25px, 3.2vw, 42px); letter-spacing: -.055em; }
header p, .hint { color: #91a9b7; font-size: 13px; margin: 0; }
.tag {
border: 1px solid #426071;
border-radius: 100px;
padding: 7px 12px;
color: #b6d4db;
font: 700 10px ui-monospace, SFMono-Regular, Consolas, monospace;
letter-spacing: .12em;
}
.scene {
position: relative;
margin: 19px 0 16px;
overflow: hidden;
border: 1px solid #345267;
border-radius: 14px;
background: #0c1926;
box-shadow: 0 22px 70px #02070b77, inset 0 0 0 1px #ffffff08;
}
canvas { display: block; width: 100%; aspect-ratio: 16 / 9; }
button {
appearance: none;
border-radius: 8px;
cursor: pointer;
font: 800 13px ui-sans-serif, system-ui, sans-serif;
letter-spacing: .035em;
padding: 13px 18px;
transition: background .15s, transform .15s, border-color .15s;
}
button:active { transform: translateY(2px); }
button:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }
#reverse {
color: #10202a;
border: 1px solid #ffe4a2;
background: #ffc966;
min-width: 212px;
}
#reverse:hover { background: #ffe099; }
#reverse.on { color: #fff; border-color: #ff776e; background: #b83e43; }
#reverse.on:hover { background: #d24e52; }
#reset { color: #d2e3e8; background: #152b3b; border: 1px solid #476073; }
#reset:hover { background: #203c50; }
.controls > div { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.status {
color: #a8d8e2;
font: 700 12px ui-monospace, SFMono-Regular, Consolas, monospace;
letter-spacing: .06em;
}
.hint { line-height: 1.5; }
@media (max-width: 600px) {
main { padding-top: 16px; }
.tag { display: none; }
.hint { width: 100%; }
}
</style>
</head>
<body>
<main>
<header>
<div>
<div class="eyebrow">A LITTLE PHYSICS EXPERIMENT</div>
<h1>Wrong Way</h1>
<p>18 riders. One escalator. No prearranged pile-up.</p>
</div>
<div class="tag">SIDE VIEW / LIVE SIMULATION</div>
</header>
<div class="scene">
<canvas id="view" aria-label="Side-view simulation of people riding an escalator"></canvas>
</div>
<div class="controls">
<div>
<button id="reverse" type="button" aria-pressed="false">↙ Throw into reverse</button>
<button id="reset" type="button">Reset riders</button>
<span class="status" id="status" role="status">BELT: ASCENDING</span>
</div>
<p class="hint">Press reverse again to restore the original direction. Space also toggles it.</p>
</div>
</main>
<script>
(() => {
"use strict";
const canvas = document.getElementById("view");
const ctx = canvas.getContext("2d");
const reverseButton = document.getElementById("reverse");
const resetButton = document.getElementById("reset");
const status = document.getElementById("status");
const W = 1280, H = 720;
const bottom = { x: 153, y: 578 };
const top = { x: 1127, y: 269 };
const length = Math.hypot(top.x - bottom.x, top.y - bottom.y);
const tangent = {
x: (top.x - bottom.x) / length,
y: (top.y - bottom.y) / length
};
const colors = [
"#e99b78", "#9db7e9", "#e1bb6a", "#9ccdb8", "#c5a4db",
"#ec878f", "#a4c2d8", "#dec089", "#89c5cb"
];
const people = [];
let reversed = false;
let belt = 19;
let beltTarget = 19;
let treadOffset = 0;
let lastTime = 0;
let accumulator = 0;
const clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
const point = (s, height = 0) => ({
x: bottom.x + tangent.x * s,
y: bottom.y + tangent.y * s - height
});
function reset() {
people.length = 0;
reversed = false;
belt = beltTarget = 19;
treadOffset = 0;
reverseButton.classList.remove("on");
reverseButton.setAttribute("aria-pressed", "false");
reverseButton.textContent = "↙ Throw into reverse";
status.textContent = "BELT: ASCENDING";
for (let i = 0; i < 18; i++) {
people.push({
id: i,
s: 54 + i * 48,
v: belt,
lean: 0,
leanV: 0,
angle: 0,
angularV: 0,
direction: 1,
state: "up",
downTime: 0,
active: true,
color: colors[i % colors.length],
phase: i * 1.87,
height: 44 + (i * 7 % 9)
});
}
}
function toggle() {
reversed = !reversed;
beltTarget = reversed ? -252 : 19;
reverseButton.classList.toggle("on", reversed);
reverseButton.setAttribute("aria-pressed", String(reversed));
reverseButton.textContent = reversed ? "↗ Restore ascent" : "↙ Throw into reverse";
status.textContent = reversed ? "BELT: FAST DESCENT" : "BELT: ASCENDING";
}
reverseButton.addEventListener("click", toggle);
resetButton.addEventListener("click", reset);
window.addEventListener("keydown", e => {
if (e.code === "Space" && e.target.tagName !== "BUTTON") {
e.preventDefault();
toggle();
}
});
function radius(p) {
return p.state === "up" ? 15 : 27;
}
function topple(p) {
if (p.state !== "up") return;
p.state = "down";
p.downTime = 0;
p.direction = (p.lean || p.leanV || 1) >= 0 ? 1 : -1;
p.angle = clamp(Math.atan(p.lean / 37), -0.48, 0.48);
p.angularV = clamp(p.leanV / 37, -6, 6);
}
function step(dt) {
// The motor changes speed quickly. The riders are not assigned its velocity.
belt += (beltTarget - belt) * (1 - Math.exp(-dt / 0.075));
treadOffset += belt * dt;
for (const p of people) {
if (!p.active) continue;
const standing = p.state === "up";
const desiredAcceleration = (belt - p.v) * (standing ? 13 : 4);
const acceleration = clamp(
desiredAcceleration,
standing ? -1100 : -350,
standing ? 1100 : 350
);
p.v += acceleration * dt;
p.s += p.v * dt;
if (standing) {
// Inertia throws the upper body past the accelerating feet.
p.leanV += (-70 * p.lean - 11 * p.leanV - 1.9 * acceleration) * dt;
p.lean += p.leanV * dt;
p.angle = clamp(Math.atan(p.lean / 37), -0.48, 0.48);
if (Math.abs(p.lean) > 13.5) topple(p);
} else {
p.downTime += dt;
p.leanV *= Math.exp(-7 * dt);
p.lean *= Math.exp(-5 * dt);
const targetAngle = p.state === "down" ? p.direction * 1.36 : 0;
p.angularV += ((targetAngle - p.angle) * 48 - p.angularV * 12) * dt;
p.angle += p.angularV * dt;
if (p.state === "rising" &&
Math.abs(p.angle) < 0.09 &&
Math.abs(p.angularV) < 0.45) {
p.state = "up";
p.angle = p.lean = p.leanV = 0;
}
}
}
// All riders use the same one-dimensional contact rules. A person lying
// across the steps has a larger collision footprint.
for (let pass = 0; pass < 4; pass++) {
const ordered = people.filter(p => p.active).sort((a, b) => a.s - b.s);
for (let i = 0; i < ordered.length - 1; i++) {
const a = ordered[i], b = ordered[i + 1];
const overlap = radius(a) + radius(b) - (b.s - a.s);
if (overlap <= 0) continue;
const invA = a.state === "up" ? 1 : 0.65;
const invB = b.state === "up" ? 1 : 0.65;
const correction = overlap / (invA + invB);
a.s -= correction * invA;
b.s += correction * invB;
const closingSpeed = a.v - b.v;
if (closingSpeed > 0) {
const impulse = closingSpeed * 0.73 / (invA + invB);
const oldA = a.v, oldB = b.v;
a.v -= impulse * invA;
b.v += impulse * invB;
if (a.state === "up") a.leanV -= (a.v - oldA) * 2.1;
if (b.state === "up") b.leanV -= (b.v - oldB) * 2.1;
}
}
}
for (const p of people) {
if (!p.active) continue;
// Solid landing ends: riders cannot move through the machinery.
const low = 13, high = length - 9;
if (p.s < low) {
p.s = low;
if (p.v < 0) {
if (p.state === "up") p.leanV -= (-p.v) * 1.6;
p.v = 0;
}
}
if (p.s > high) {
p.s = high;
if (p.v > 0) {
if (p.state === "up") p.leanV += p.v * 1.6;
p.v = 0;
}
}
if (p.state === "up" && Math.abs(p.lean) > 13.5) topple(p);
if (p.state === "down" && p.downTime > 0.85 &&
Math.abs(p.v - belt) < 52 && Math.abs(p.v) < 75) {
const hasRoom = people.every(other =>
other === p || !other.active ||
Math.abs(other.s - p.s) > 19 + radius(other)
);
if (hasRoom) p.state = "rising";
}
// A renewed shove or loss of footing interrupts an attempt to stand.
if (p.state === "rising" && Math.abs(p.v - belt) > 100) {
p.state = "down";
p.direction = p.angle >= 0 ? 1 : -1;
}
}
// The top landing is an exit during ordinary ascent. Re-enter at the
// bottom only when the entrance is clear; nobody is recycled in reverse.
if (!reversed && belt > 0) {
for (const p of people) {
if (p.active && p.state === "up" && p.s > length - 25) {
p.active = false;
}
}
for (const p of people) {
if (p.active) continue;
const entranceClear = people.every(q =>
!q.active || q.s > 58
);
if (entranceClear) {
p.active = true;
p.s = 14;
p.v = belt;
p.lean = p.leanV = p.angle = p.angularV = 0;
p.state = "up";
}
}
}
}
function line(x1, y1, x2, y2, color, width = 1) {
ctx.strokeStyle = color;
ctx.lineWidth = width;
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
function roundedBar(x1, y1, x2, y2, color, width) {
ctx.strokeStyle = color;
ctx.lineWidth = width;
ctx.lineCap = "round";
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
function drawArchitecture() {
ctx.fillStyle = "#0c1c2a";
ctx.fillRect(0, 0, W, H);
// Sparse wall markings give the motion a fixed reference.
for (let x = 45; x < W; x += 96) {
line(x, 48, x, 646, "#28405249");
}
for (let y = 82; y < 650; y += 92) {
line(34, y, 1246, y, "#2840523b");
}
ctx.fillStyle = "#12283a";
ctx.fillRect(0, 596, 175, 124);
ctx.fillRect(1100, 294, 180, 426);
ctx.fillStyle = "#1b3445";
ctx.fillRect(0, 594, 178, 10);
ctx.fillRect(1096, 290, 184, 10);
line(0, 605, 174, 605, "#71a8b0", 2);
line(1099, 301, 1280, 301, "#71a8b0", 2);
// Escalator carcass, with the steps moving separately over it.
const a = point(-18), b = point(length + 15);
ctx.fillStyle = "#203747";
ctx.beginPath();
ctx.moveTo(a.x, a.y - 5);
ctx.lineTo(b.x, b.y - 5);
ctx.lineTo(b.x, b.y + 53);
ctx.lineTo(a.x, a.y + 53);
ctx.closePath();
ctx.fill();
line(a.x, a.y + 51, b.x, b.y + 51, "#09202d", 8);
line(a.x, a.y + 43, b.x, b.y + 43, "#4c6b78", 3);
ctx.save();
ctx.beginPath();
ctx.moveTo(a.x, a.y - 3);
ctx.lineTo(b.x, b.y - 3);
ctx.lineTo(b.x, b.y + 18);
ctx.lineTo(a.x, a.y + 18);
ctx.closePath();
ctx.clip();
ctx.fillStyle = "#294656";
ctx.fillRect(0, 0, W, H);
const spacing = 43;
const phase = ((treadOffset % spacing) + spacing) % spacing;
for (let s = -spacing * 2 + phase; s < length + spacing * 2; s += spacing) {
const p = point(s);
const n = { x: -tangent.y, y: tangent.x };
line(p.x - n.x * 5, p.y - n.y * 5,
p.x + n.x * 23, p.y + n.y * 23, "#081d2b", 5);
line(p.x + 7, p.y + 5, p.x + 27, p.y + 5,
"#7296a0", 2);
}
ctx.restore();
line(a.x, a.y - 4, b.x, b.y - 4, "#92b4b7", 4);
line(a.x, a.y + 17, b.x, b.y + 17, "#0d2735", 4);
// Rear handrail: behind the riders.
const railA = point(-29, 65), railB = point(length + 27, 65);
line(railA.x, railA.y + 9, railB.x, railB.y + 9, "#0a1b2a", 13);
line(railA.x, railA.y, railB.x, railB.y, "#577985", 7);
line(railA.x, railA.y - 3, railB.x, railB.y - 3, "#9bb9b7", 2);
for (let s = 17; s < length; s += 167) {
const r = point(s, 64), foot = point(s, -16);
line(r.x, r.y + 4, foot.x, foot.y, "#52717c", 4);
ctx.fillStyle = "#83a2a9";
ctx.beginPath();
ctx.arc(r.x, r.y + 3, 4, 0, Math.PI * 2);
ctx.fill();
}
// Signs and landing details.
ctx.font = "700 12px ui-monospace, monospace";
ctx.letterSpacing = "2px";
ctx.fillStyle = "#7395a4";
ctx.fillText("LOWER LANDING", 32, 653);
ctx.fillText("UPPER LANDING", 1092, 357);
ctx.letterSpacing = "0px";
ctx.fillStyle = "#ffcf75";
ctx.fillRect(86, 585, 71, 5);
ctx.fillRect(1114, 280, 87, 5);
ctx.fillStyle = "#3b5968";
ctx.fillRect(37, 437, 42, 86);
ctx.fillStyle = reversed ? "#ff7971" : "#85d6c5";
ctx.fillRect(49, 449, 18, 18);
ctx.fillStyle = "#a8c3c9";
ctx.font = "700 11px ui-monospace, monospace";
ctx.fillText("MOTOR", 35, 541);
ctx.fillStyle = "#60808d";
ctx.font = "12px ui-monospace, monospace";
ctx.fillText("18 INDEPENDENT RIDERS", 37, 69);
ctx.fillText(reversed ? "DIRECTION ↙ FAST" : "DIRECTION ↗ NORMAL", 37, 91);
}
function drawPerson(p) {
const f = point(p.s);
const angle = p.angle;
const sine = Math.sin(angle), cosine = Math.cos(angle);
const h = p.height;
const up = (distance) => ({
x: f.x + tangent.x * sine * distance,
y: f.y + tangent.y * sine * distance - cosine * distance
});
const hip = up(h * 0.35);
const shoulder = up(h * 0.83);
const head = up(h + 5);
const walking = p.state === "up"
? Math.sin(p.s * 0.12 + p.phase) * Math.min(2.5, Math.abs(p.v) * 0.022)
: Math.sin(p.angle * 4 + p.phase) * 3;
ctx.save();
ctx.lineJoin = "round";
ctx.lineCap = "round";
// Contact shadow.
ctx.fillStyle = "#07131cad";
ctx.beginPath();
ctx.ellipse(f.x, f.y + 4, p.state === "up" ? 13 : 26, 4, -0.3, 0, Math.PI * 2);
ctx.fill();
const ink = "#102333";
const skin = ["#f5c9aa", "#dfaa88", "#b98468", "#f1bfa1"][p.id % 4];
const sideways = p.state === "up" ? 6 : 12;
// Legs respond to body orientation rather than following a fall animation.
roundedBar(hip.x - 3, hip.y, f.x - sideways + walking, f.y - 2, ink, 9);
roundedBar(hip.x + 3, hip.y, f.x + sideways - walking, f.y - 2, ink, 9);
roundedBar(f.x - sideways + walking, f.y - 2,
f.x - sideways + walking + 6, f.y - 1, "#6c8590", 5);
roundedBar(f.x + sideways - walking, f.y - 2,
f.x + sideways - walking + 6, f.y - 1, "#6c8590", 5);
roundedBar(hip.x, hip.y, shoulder.x, shoulder.y, ink, 15);
roundedBar(hip.x, hip.y, shoulder.x, shoulder.y, p.color, 11);
ctx.fillStyle = "#ffffff32";
ctx.beginPath();
ctx.arc(shoulder.x - 2, shoulder.y, 2.1, 0, Math.PI * 2);
ctx.fill();
const armReach = p.state === "up" ? 8 : 16;
roundedBar(shoulder.x - 4, shoulder.y + 2,
shoulder.x - armReach - sine * 5,
shoulder.y + 16 * cosine + 8, ink, 6);
roundedBar(shoulder.x + 4, shoulder.y + 2,
shoulder.x + armReach + sine * 5,
shoulder.y + 13 * cosine + (p.state === "up" ? walking : -8),
skin, 5);
ctx.fillStyle = skin;
ctx.strokeStyle = ink;
ctx.lineWidth = 2.8;
ctx.beginPath();
ctx.arc(head.x, head.y, 6.6, 0, Math.PI * 2);
ctx.fill();
ctx.stroke();
// Small hair arc to keep the head's orientation readable.
ctx.strokeStyle = ink;
ctx.lineWidth = 3;
ctx.beginPath();
ctx.arc(head.x - 1, head.y - 1, 6, Math.PI * 1.05, Math.PI * 1.83);
ctx.stroke();
ctx.restore();
}
function draw() {
drawArchitecture();
people.filter(p => p.active).sort((a, b) => b.s - a.s).forEach(drawPerson);
// Foreground edge of the moving assembly.
const a = point(-17, -21), b = point(length + 13, -21);
line(a.x, a.y, b.x, b.y, "#081b28", 10);
line(a.x, a.y - 4, b.x, b.y - 4, "#678b94", 3);
ctx.fillStyle = "#97b5bd";
ctx.font = "11px ui-monospace, monospace";
ctx.fillText("CONTACTS • MOMENTUM • BALANCE • RECOVERY", 37, 689);
}
function resize() {
const dpr = Math.min(window.devicePixelRatio || 1, 2);
const rect = canvas.getBoundingClientRect();
canvas.width = Math.round(rect.width * dpr);
canvas.height = Math.round(rect.height * dpr);
ctx.setTransform(canvas.width / W, 0, 0, canvas.height / H, 0, 0);
}
function frame(time) {
if (!lastTime) lastTime = time;
accumulator += Math.min((time - lastTime) / 1000, 0.08);
lastTime = time;
const dt = 1 / 120;
let count = 0;
while (accumulator >= dt && count++ < 12) {
step(dt);
accumulator -= dt;
}
draw();
requestAnimationFrame(frame);
}
window.addEventListener("resize", resize);
reset();
resize();
requestAnimationFrame(frame);
})();
</script>
</body>
</html>
Reversing sharply changes the step speed. Riders initially retain their momentum, lean past their balance limit, and fall; subsequent contact and the faster-descending belt move them toward the lower landing, where fallen riders obstruct those behind. Restoring ascent lets riders with space and sufficiently steady footing stand again.
The nudges are the chosen balance threshold, stronger contact footprint for a fallen rider, solid landing boundaries, and recycling upright riders from the upper exit to an empty lower entrance during normal ascent. Nobody is selected to fall at a particular time. It is deliberately a one-dimensional contact model: the figures cannot step around one another, and its drawn limbs are expressive rather than independently simulated.