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
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
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
You make short animated pieces for the web, and you have spent time on the part of the internet that makes cats famous.
Build me a single HTML page: a cat in a living room that lifts off the floor and spins in the air when you click it.
Make this the Oiia Cat — the spinning cat meme, the one whose loop is written out as "oiia oiia oiiaiooooiai". Match the original's look and feel, not a generic rotation:
Build toward what that meme feels like at full speed: too fast, too loud, and funnier every time it goes further.
data: URIs are fine.localStorage, sessionStorage, cookies or indexedDB — sandboxed frame, they throw.html block.The single fenced html block.
Five bullets.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Oiia Cat</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{overflow:hidden;background:#0a0a0c;font-family:system-ui,sans-serif;touch-action:none}
#c{display:block;width:100vw;height:100vh;cursor:pointer}
#ui{position:fixed;bottom:20px;right:20px;z-index:10;display:flex;gap:12px;align-items:center;pointer-events:none}
.btn{pointer-events:auto;background:rgba(15,15,18,0.9);border:1px solid rgba(255,255,255,0.15);color:#f0e8e0;padding:10px 16px;border-radius:8px;font-size:13px;cursor:pointer;backdrop-filter:blur(8px);transition:all 0.15s;user-select:none}
.btn:hover{background:rgba(30,30,35,0.95);border-color:rgba(255,255,255,0.3);transform:translateY(-1px)}
.btn:active{transform:translateY(0)}
.btn.muted{border-color:#e86c6c;color:#e86c6c}
.stage-ind{color:#8b8680;font-size:11px;letter-spacing:0.5px;text-transform:uppercase;pointer-events:none;min-width:80px;text-align:right}
@media(prefers-reduced-motion:reduce){* {animation:none!important;transition:none!important}}
</style>
</head>
<body>
<canvas id="c"></canvas>
<div id="ui">
<span class="stage-ind" id="stageText">STAGE 0</span>
<button class="btn" id="muteBtn" aria-label="Mute">🔊 SOUND ON</button>
</div>
<script>
/* ============ CAT RENDERER ============ */
const C = document.getElementById('c');
const CTX = C.getContext('2d', {alpha:false, desynchronized:true});
let W=0,H=0,DPR=1;
function resize(){DPR=Math.min(window.devicePixelRatio||1,2);W=C.width=innerWidth*DPR;H=C.height=innerHeight*DPR;CTX.scale(DPR,DPR);buildRoom();}
window.addEventListener('resize',resize);resize();
/* ============ ROOM GEOMETRY ============ */
const room = {
floorY:0, // set in buildRoom
walls:[],
floorPattern:null,
wallTexture:null,
shadowMap:null,
lightDir:{x:0.3,y:-0.8,z:0.4},
buildTime:0
};
function buildRoom(){
const cw=innerWidth, ch=innerHeight;
room.floorY = ch * 0.72;
room.walls = [
{x:0,y:0,w:cw,h:room.floorY}, // back wall
{x:-cw*2,y:room.floorY,w:cw*5,h:ch-room.floorY} // floor extends
];
// Floor texture - wood planks
const ft = document.createElement('canvas');
ft.width=512; ft.height=512;
const ftx=ft.getContext('2d');
const plankH=32;
for(let y=0;y<512;y+=plankH){
const hue = 28 + Math.random()*6;
const sat = 12 + Math.random()*8;
const light = 38 + Math.random()*10;
ftx.fillStyle=`hsl(${hue},${sat}%,${light}%)`;
ftx.fillRect(0,y,512,plankH);
// grain
for(let i=0;i<40;i++){
ftx.strokeStyle=`hsla(${hue},${sat}%,${light-15}%,0.08)`;
ftx.beginPath();
ftx.moveTo(Math.random()*512,y);
ftx.lineTo(Math.random()*512,y+plankH);
ftx.stroke();
}
// plank gap
ftx.strokeStyle='rgba(0,0,0,0.06)';
ftx.beginPath(); ftx.moveTo(0,y+plankH); ftx.lineTo(512,y+plankH); ftx.stroke();
}
room.floorPattern = CTX.createPattern(ft,'repeat');
// Wall texture - subtle wallpaper
const wt = document.createElement('canvas');
wt.width=512; wt.height=512;
const wtx=wt.getContext('2d');
wtx.fillStyle='#e8e0d8';
wtx.fillRect(0,0,512,512);
for(let i=0;i<2000;i++){
wtx.fillStyle=`rgba(120,110,100,${Math.random()*0.015})`;
wtx.fillRect(Math.random()*512,Math.random()*512,1,1);
}
room.wallTexture = CTX.createPattern(wt,'repeat');
// Contact shadow map for cat
const st = document.createElement('canvas');
st.width=256; st.height=128;
const stx=st.getContext('2d');
const g=stx.createRadialGradient(128,100,0,128,100,110);
g.addColorStop(0,'rgba(20,18,16,0.35)');
g.addColorStop(0.5,'rgba(20,18,16,0.12)');
g.addColorStop(1,'rgba(20,18,16,0)');
stx.fillStyle=g; stx.fillRect(0,0,256,128);
room.shadowMap = st;
room.buildTime = performance.now();
}
/* ============ CAT DEFINITION ============ */
// Cat drawn in local coordinates: center at (0,0), facing +Z (toward camera)
// We'll project to 2D with rotation around Y axis
const Cat = {
// Base dimensions (pixels at 1x scale)
bodyW:160, bodyH:110, bodyD:140,
headW:100, headH:95, headD:90,
earH:45, earW:32,
eyeW:28, eyeH:32,
pupilW:14, pupilH:18,
noseW:14, noseH:10,
whiskerL:70,
tailW:25, tailL:120,
legW:22, legH:50,
// Colors
furBase:'#f5efe6', furDark:'#d8cfc4', furLight:'#fdfbf7',
noseCol:'#e8a8a0', earPink:'#f5c8c0', eyeWhite:'#ffffff',
pupilCol:'#1a1614', irisCol:'#8b6f4a', whiskerCol:'#c8c0b8',
// Parts as draw functions
drawBody(ctx, scale, rotY, lift, spinPhase, stage){
ctx.save();
ctx.scale(scale, scale);
// Body ellipse with perspective
const bw = this.bodyW * (0.85 + 0.15*Math.cos(rotY));
const bh = this.bodyH;
// Fur layers - back to front
const layers = 6;
for(let l=layers;l>=0;l--){
const t = l/layers;
const alpha = 0.15 + t*0.2;
const sz = 1 + (1-t)*0.08;
const col = l===layers ? this.furLight : (l===0 ? this.furDark : this.furBase);
ctx.globalAlpha = alpha;
ctx.fillStyle = col;
ctx.beginPath();
ctx.ellipse(0, -bh*0.3, bw*sz*0.5, bh*sz*0.5, 0, 0, Math.PI*2);
ctx.fill();
}
// Belly lighter patch
ctx.globalAlpha=1;
const grad = ctx.createRadialGradient(0,-bh*0.1,0,0,-bh*0.1,bw*0.35);
grad.addColorStop(0,'rgba(253,251,247,0.6)');
grad.addColorStop(1,'rgba(253,251,247,0)');
ctx.fillStyle=grad;
ctx.beginPath(); ctx.ellipse(0,-bh*0.1,bw*0.35,bh*0.3,0,0,Math.PI*2); ctx.fill();
ctx.restore();
},
drawHead(ctx, scale, rotY, lift, spinPhase, stage){
ctx.save();
ctx.scale(scale, scale);
ctx.translate(0, -this.bodyH*0.55 - this.headH*0.3);
// Head turns with body but slightly leads
const headRot = rotY * 1.1;
const hw = this.headW * (0.8 + 0.2*Math.cos(headRot));
const hh = this.headH;
// Head fur
for(let l=5;l>=0;l--){
const t=l/5;
ctx.globalAlpha=0.12+t*0.18;
ctx.fillStyle = l===5?this.furLight:(l===0?this.furDark:this.furBase);
ctx.beginPath();
ctx.ellipse(0,-hh*0.15, hw*0.5*(1+(1-t)*0.06), hh*0.5*(1+(1-t)*0.06), 0,0,Math.PI*2);
ctx.fill();
}
ctx.globalAlpha=1;
// Cheeks
ctx.fillStyle=this.furBase;
[-1,1].forEach(s=>{
ctx.beginPath();
ctx.ellipse(s*hw*0.35, -hh*0.05, hw*0.22, hh*0.25, 0,0,Math.PI*2);
ctx.fill();
});
// Ears
const earBaseY = -hh*0.55;
[-1,1].forEach(s=>{
ctx.save();
ctx.translate(s*hw*0.32, earBaseY);
ctx.rotate(s*0.15);
// Ear back
ctx.fillStyle=this.furDark;
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(-s*this.earW*0.5, -this.earH*0.2);
ctx.lineTo(-s*this.earW*0.3, -this.earH);
ctx.lineTo(s*this.earW*0.3, -this.earH);
ctx.lineTo(s*this.earW*0.5, -this.earH*0.2);
ctx.closePath(); ctx.fill();
// Ear inner
ctx.fillStyle=this.earPink;
ctx.beginPath();
ctx.moveTo(0,-this.earH*0.1);
ctx.lineTo(-s*this.earW*0.25, -this.earH*0.3);
ctx.lineTo(-s*this.earW*0.15, -this.earH*0.8);
ctx.lineTo(s*this.earW*0.15, -this.earH*0.8);
ctx.lineTo(s*this.earW*0.25, -this.earH*0.3);
ctx.closePath(); ctx.fill();
// Ear tuft
ctx.strokeStyle=this.furLight;
ctx.lineWidth=2;
for(let i=0;i<3;i++){
ctx.beginPath();
ctx.moveTo(s*(2+i*3), -this.earH*0.7+i*2);
ctx.lineTo(s*(5+i*3), -this.earH*0.9+i*2);
ctx.stroke();
}
ctx.restore();
});
// Eyes - THE OIIA STARE
const eyeY = -hh*0.15;
const eyeSep = hw*0.28;
[-1,1].forEach(s=>{
const ex = s*eyeSep;
// Eye white
ctx.fillStyle=this.eyeWhite;
ctx.beginPath();
ctx.ellipse(ex, eyeY, this.eyeW*0.5, this.eyeH*0.5, 0,0,Math.PI*2);
ctx.fill();
// Iris - wide, dilated
const irisR = this.eyeW*0.45;
const ig = ctx.createRadialGradient(ex,eyeY,0, ex,eyeY,irisR);
ig.addColorStop(0,this.irisCol);
ig.addColorStop(0.7,'#5a4a32');
ig.addColorStop(1,'#2a2218');
ctx.fillStyle=ig;
ctx.beginPath();
ctx.ellipse(ex, eyeY, irisR, this.eyeH*0.45, 0,0,Math.PI*2);
ctx.fill();
// Pupil - huge, round, dead center
ctx.fillStyle=this.pupilCol;
ctx.beginPath();
ctx.ellipse(ex, eyeY, this.pupilW*0.5, this.pupilH*0.5, 0,0,Math.PI*2);
ctx.fill();
// Catch lights - multiple for realism
ctx.fillStyle='rgba(255,255,255,0.95)';
ctx.beginPath(); ctx.ellipse(ex-this.eyeW*0.18, eyeY-this.eyeH*0.12, 5, 3.5, -0.5,0,Math.PI*2); ctx.fill();
ctx.beginPath(); ctx.ellipse(ex+this.eyeW*0.12, eyeY-this.eyeH*0.08, 3, 2, 0.3,0,Math.PI*2); ctx.fill();
// Lower lid highlight
ctx.strokeStyle='rgba(255,255,255,0.15)';
ctx.lineWidth=1.5;
ctx.beginPath(); ctx.ellipse(ex, eyeY+this.eyeH*0.35, this.eyeW*0.45, 4, 0, 0, Math.PI); ctx.stroke();
});
// Nose
ctx.fillStyle=this.noseCol;
ctx.beginPath();
ctx.ellipse(0, eyeY+hh*0.22, this.noseW*0.5, this.noseH*0.5, 0,0,Math.PI*2);
ctx.fill();
// Nose highlight
ctx.fillStyle='rgba(255,255,255,0.3)';
ctx.beginPath(); ctx.ellipse(-2, eyeY+hh*0.2, 2, 1.5, 0,0,Math.PI*2); ctx.fill();
// Mouth - tiny w
ctx.strokeStyle='rgba(26,22,20,0.6)';
ctx.lineWidth=1.5;
ctx.lineCap='round';
ctx.beginPath();
ctx.moveTo(-4, eyeY+hh*0.28);
ctx.quadraticCurveTo(0, eyeY+hh*0.32, 4, eyeY+hh*0.28);
ctx.stroke();
// Whiskers
ctx.strokeStyle=this.whiskerCol;
ctx.lineWidth=1;
[-1,1].forEach(s=>{
for(let i=0;i<4;i++){
const yy = eyeY+hh*0.2 + i*5;
ctx.beginPath();
ctx.moveTo(s*this.noseW*0.7, yy);
ctx.quadraticCurveTo(s*this.whiskerL*0.5, yy-s*2, s*this.whiskerL, yy+s*5);
ctx.stroke();
}
});
ctx.restore();
},
drawLegs(ctx, scale, rotY, lift, spinPhase, stage){
ctx.save();
ctx.scale(scale, scale);
ctx.translate(0, this.bodyH*0.2);
const legY = 0;
const legX = this.bodyW*0.35 * (0.7+0.3*Math.cos(rotY));
[-1,1].forEach(s=>{
ctx.save();
ctx.translate(s*legX, legY);
// Front leg
ctx.fillStyle=this.furBase;
ctx.beginPath();
ctx.roundRect(-this.legW*0.5, 0, this.legW, this.legH, 8);
ctx.fill();
// Paw
ctx.fillStyle=this.furLight;
ctx.beginPath();
ctx.ellipse(0, this.legH+5, this.legW*0.6, 10, 0,0,Math.PI*2);
ctx.fill();
// Toe beans
ctx.fillStyle=this.noseCol;
for(let i=0;i<4;i++){
ctx.beginPath();
ctx.ellipse(-this.legW*0.3 + i*this.legW*0.2, this.legH+5, 4, 3, 0,0,Math.PI*2);
ctx.fill();
}
ctx.restore();
});
// Back legs hint
ctx.fillStyle=this.furDark;
[-1,1].forEach(s=>{
ctx.beginPath();
ctx.ellipse(s*this.bodyW*0.25, this.bodyH*0.15, this.legW*0.7, this.legH*0.4, 0,0,Math.PI*2);
ctx.fill();
});
ctx.restore();
},
drawTail(ctx, scale, rotY, lift, spinPhase, stage){
ctx.save();
ctx.scale(scale, scale);
ctx.translate(this.bodyW*0.45*Math.cos(rotY), -this.bodyH*0.1);
ctx.rotate(-0.3 + spinPhase*0.5);
ctx.fillStyle=this.furBase;
ctx.beginPath();
ctx.moveTo(0,0);
for(let i=0;i<8;i++){
const t=i/7;
const x = Math.sin(t*Math.PI*2 + spinPhase)*this.tailW*0.5;
const y = t*this.tailL;
ctx.lineTo(x,y);
}
for(let i=7;i>=0;i--){
const t=i/7;
const x = Math.sin(t*Math.PI*2 + spinPhase)*this.tailW*0.5;
const y = t*this.tailL;
ctx.lineTo(-x,y);
}
ctx.closePath(); ctx.fill();
// Tail tip
ctx.fillStyle=this.furLight;
ctx.beginPath(); ctx.ellipse(0, this.tailL, this.tailW*0.6, 12, 0,0,Math.PI*2); ctx.fill();
ctx.restore();
},
drawFull(ctx, params){
const {scale, rotY, lift, spinPhase, stage, blur} = params;
ctx.save();
ctx.translate(params.cx, params.cy);
// Contact shadow
if(lift < 120){
const shadowAlpha = (1 - lift/120) * 0.35;
ctx.globalAlpha = shadowAlpha;
ctx.drawImage(room.shadowMap, -128*scale, -64*scale, 256*scale, 128*scale);
ctx.globalAlpha = 1;
}
// Tail (behind body)
this.drawTail(ctx, scale, rotY, lift, spinPhase, stage);
// Body
this.drawBody(ctx, scale, rotY, lift, spinPhase, stage);
// Legs
this.drawLegs(ctx, scale, rotY, lift, spinPhase, stage);
// Head
this.drawHead(ctx, scale, rotY, lift, spinPhase, stage);
ctx.restore();
}
};
/* ============ PARTICLES / EFFECTS ============ */
const particles = [];
function spawnParticles(cx, cy, count, type, stage){
for(let i=0;i<count;i++){
particles.push({
x:cx + (Math.random()-0.5)*80,
y:cy + (Math.random()-0.5)*60,
vx:(Math.random()-0.5)*8,
vy:(Math.random()-0.5)*8 - 2,
life:1, maxLife:1+Math.random()*2,
size:2+Math.random()*4,
hue: type==='fur' ? 30+Math.random()*20 : (type==='glitch' ? 200+Math.random()*60 : 40+Math.random()*30),
sat: type==='fur' ? 20+Math.random()*20 : 80+Math.random()*20,
light: type==='fur' ? 70+Math.random()*20 : 40+Math.random()*40,
alpha:1,
rot:Math.random()*Math.PI*2,
vr:(Math.random()-0.5)*0.3,
type,
stage
});
}
}
function updateParticles(dt){
for(let i=particles.length-1;i>=0;i--){
const p=particles[i];
p.x+=p.vx*dt*60;
p.y+=p.vy*dt*60;
p.vy+=0.3*dt*60;
p.life-=dt;
p.alpha=p.life/p.maxLife;
p.rot+=p.vr*dt*60;
if(p.life<=0) particles.splice(i,1);
}
}
function drawParticles(ctx){
particles.forEach(p=>{
ctx.save();
ctx.globalAlpha=p.alpha*0.8;
ctx.translate(p.x,p.y);
ctx.rotate(p.rot);
if(p.type==='fur'){
ctx.fillStyle=`hsl(${p.hue},${p.sat}%,${p.light}%)`;
ctx.beginPath();
ctx.ellipse(0,0,p.size,p.size*0.5,0,0,Math.PI*2);
ctx.fill();
}else if(p.type==='glitch'){
ctx.fillStyle=`hsl(${p.hue},${p.sat}%,${p.light}%)`;
ctx.fillRect(-p.size,-p.size,p.size*2,p.size*2);
}else{
ctx.strokeStyle=`hsl(${p.hue},${p.sat}%,${p.light}%)`;
ctx.lineWidth=2;
ctx.beginPath();
ctx.moveTo(-p.size,0); ctx.lineTo(p.size,0);
ctx.stroke();
}
ctx.restore();
});
}
/* ============ AUDIO ENGINE ============ */
const AudioEngine = (()=>{
let actx=null, masterGain=null, muted=false;
let oiiaBuffer=null, oiiaSource=null, oiiaGain=null;
let currentRate=1, targetRate=1;
let playing=false;
// Formant frequencies for vowels (male-ish cat)
const formants = {
o: [500, 900, 2500, 3500, 4500],
i: [300, 2300, 3000, 3500, 4500],
a: [800, 1200, 2600, 3200, 4200],
ia: [350, 2000, 2800, 3400, 4400]
};
const formantBW = [80, 100, 150, 200, 250];
function ensureContext(){
if(actx) return;
actx = new (window.AudioContext||window.webkitAudioContext)();
masterGain = actx.createGain();
masterGain.connect(actx.destination);
masterGain.gain.value = 0.7;
oiiaGain = actx.createGain();
oiiaGain.connect(masterGain);
buildOiiaLoop();
}
function buildOiiaLoop(){
// Generate a 2-second loop of "oiia oiia oiiaiooooiai" at base pitch
const sampleRate = actx.sampleRate;
const duration = 2.0; // seconds
const len = sampleRate * duration;
const buffer = actx.createBuffer(1, len, sampleRate);
const data = buffer.getChannelData(0);
// Base fundamental
const f0 = 180; // Hz - cat vocal range
// Oiia pattern timing
const pattern = [
{v:'o', t:0.00, d:0.25},
{v:'i', t:0.25, d:0.15},
{v:'i', t:0.40, d:0.15},
{v:'a', t:0.55, d:0.20},
{v:'o', t:0.75, d:0.25},
{v:'i', t:1.00, d:0.15},
{v:'i', t:1.15, d:0.15},
{v:'a', t:1.30, d:0.20},
{v:'i', t:1.50, d:0.10},
{v:'o', t:1.60, d:0.30},
{v:'o', t:1.90, d:0.10},
{v:'i', t:2.00, d:0.10},
{v:'a', t:2.10, d:0.10},
{v:'i', t:2.20, d:0.10}
];
// We'll synthesize with multiple formants
for(let s=0;s<len;s++){
const t = s/sampleRate;
let sample = 0;
// Find current vowel
let currentV = 'a';
for(const seg of pattern){
if(t >= seg.t && t < seg.t + seg.d){
currentV = seg.v;
break;
}
}
const f = formants[currentV] || formants.a;
// Glottal pulse approximation
const phase = (t * f0) % 1;
const pulse = Math.exp(-20 * Math.abs(phase - 0.5)) * Math.sin(phase * Math.PI * 2);
// Formant filtering via additive synthesis (cheap approximation)
let formantSum = 0;
for(let i=0;i<5;i++){
const fi = f[i] * (1 + 0.02*Math.sin(t*8+i)); // slight wobble
formantSum += Math.sin(t * fi * Math.PI * 2) * (0.4/(i+1));
}
// Breath noise
const noise = (Math.random()-0.5)*0.02;
// Envelope per segment
let env = 0;
for(const seg of pattern){
if(t >= seg.t && t < seg.t + seg.d){
const localT = (t - seg.t)/seg.d;
env = Math.sin(localT * Math.PI) * (0.6 + 0.4*Math.sin(t*20));
break;
}
}
sample = (pulse * 0.5 + formantSum * 0.5 + noise) * env * 0.3;
data[s] = sample;
}
// High-pass to remove DC
let hp=0;
for(let s=0;s<len;s++){
const cur=data[s];
data[s]=cur-hp*0.995;
hp=cur;
}
oiiaBuffer = buffer;
}
function play(){
if(playing) return;
ensureContext();
if(actx.state==='suspended') actx.resume();
oiiaSource = actx.createBufferSource();
oiiaSource.buffer = oiiaBuffer;
oiiaSource.loop = true;
oiiaSource.playbackRate.value = currentRate;
oiiaSource.connect(oiiaGain);
oiiaGain.gain.value = 1;
oiiaSource.start();
playing=true;
}
function stop(){
if(oiiaSource){
oiiaGain.gain.exponentialRampToValueAtTime(0.001, actx.currentTime+0.1);
setTimeout(()=>{ if(oiiaSource) oiiaSource.stop(); oiiaSource=null; }, 200);
}
playing=false;
}
function setRate(r){
targetRate = r;
currentRate = r;
if(oiiaSource) oiiaSource.playbackRate.value = r;
}
function setMuted(m){
muted=m;
if(masterGain) masterGain.gain.value = m?0:0.7;
}
function update(dt){
// Smooth rate changes
if(Math.abs(currentRate - targetRate) > 0.01){
currentRate += (targetRate - currentRate) * Math.min(1, dt*8);
if(oiiaSource) oiiaSource.playbackRate.value = currentRate;
}
}
return {play, stop, setRate, setMuted, update, get playing(){return playing}, get context(){return actx}};
})();
/* ============ GAME STATE ============ */
const State = {
stage: 0, // 0=idle, 1-4 active
clickCount: 0,
spinPhase: 0,
spinSpeed: 0,
targetSpinSpeed: 0,
lift: 0,
targetLift: 0,
rotY: 0,
targetRotY: 0,
scale: 1,
targetScale: 1,
roomRot: 0,
roomTargetRot: 0,
roomScale: 1,
roomTargetScale: 1,
shake: 0,
glitchAmount: 0,
hueShift: 0,
saturation: 1,
brightness: 1,
invert: 0,
duplicateCats: [],
time: 0,
lastClick: 0,
cx: innerWidth/2,
cy: innerHeight/2
};
const STAGE_CONFIG = [
{}, // 0
{ // 1 - Liftoff
spin: 8, lift: 80, scale: 1.1, roomRot: 0, roomScale: 1,
duration: 3000, name: 'STAGE 1: LIFTOFF'
},
{ // 2 - Acceleration
spin: 25, lift: 180, scale: 1.25, roomRot: 0.15, roomScale: 1.1,
duration: 3000, name: 'STAGE 2: WINDUP'
},
{ // 3 - Blur
spin: 60, lift: 300, scale: 1.5, roomRot: 0.5, roomScale: 1.3,
duration: 4000, name: 'STAGE 3: BLUR'
},
{ // 4 - Transcendence
spin: 140, lift: 450, scale: 2.2, roomRot: 2.5, roomScale: 2.0,
duration: 999999, name: 'STAGE 4: OIIA SINGULARITY'
}
];
function advanceStage(){
State.clickCount++;
State.stage = Math.min(4, State.clickCount);
const cfg = STAGE_CONFIG[State.stage];
State.targetSpinSpeed = cfg.spin || 0;
State.targetLift = cfg.lift || 0;
State.targetScale = cfg.scale || 1;
State.roomTargetRot = cfg.roomRot || 0;
State.roomTargetScale = cfg.roomScale || 1;
document.getElementById('stageText').textContent = cfg.name || 'STAGE 0';
// Spawn particles
if(State.stage>=1) spawnParticles(State.cx, State.cy - State.lift, 15, 'fur', State.stage);
if(State.stage>=2) spawnParticles(State.cx, State.cy - State.lift, 25, 'fur', State.stage);
if(State.stage>=3){
spawnParticles(State.cx, State.cy - State.lift, 40, 'glitch', State.stage);
State.shake = 8;
}
if(State.stage===4){
// Spawn duplicate cats
State.duplicateCats = [];
for(let i=0;i<6;i++){
State.duplicateCats.push({
angle: (i/6)*Math.PI*2,
radius: 200 + Math.random()*100,
phase: Math.random()*Math.PI*2,
scale: 0.5 + Math.random()*0.5,
hueShift: Math.random()*360
});
}
State.shake = 20;
spawnParticles(State.cx, State.cy - State.lift, 80, 'glitch', 4);
spawnParticles(State.cx, State.cy - State.lift, 60, 'fur', 4);
}
AudioEngine.play();
}
function handleClick(e){
const rect=C.getBoundingClientRect();
const x=e.clientX-rect.left, y=e.clientY-rect.top;
// Check if clicking cat (rough hit test)
const catScreenY = State.cy - State.lift;
const catScreenX = State.cx;
const catW = Cat.bodyW * State.scale * 0.8;
const catH = (Cat.bodyH + Cat.headH) * State.scale;
if(x>catScreenX-catW/2 && x<catScreenX+catW/2 && y>catScreenY-catH/2 && y<catScreenY+catH/2){
advanceStage();
}
}
C.addEventListener('click', handleClick);
C.addEventListener('touchstart', e=>{e.preventDefault(); handleClick(e.touches[0]);},{passive:false});
document.getElementById('muteBtn').addEventListener('click',()=>{
const btn=document.getElementById('muteBtn');
const muted = !btn.classList.contains('muted');
btn.classList.toggle('muted', muted);
btn.textContent = muted ? '🔇 SOUND OFF' : '🔊 SOUND ON';
AudioEngine.setMuted(muted);
});
/* ============ RENDER LOOP ============ */
let lastTime=0;
function frame(now){
const dt = Math.min(0.05, (now-lastTime)/1000);
lastTime = now;
State.time += dt;
update(dt);
render();
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
function update(dt){
// Smooth interpolation
const lerp = (a,b,t)=>a+(b-a)*t;
const ease = t=>1-Math.pow(1-t,3);
const k = ease(Math.min(1, dt*6));
State.spinSpeed = lerp(State.spinSpeed, State.targetSpinSpeed, k);
State.lift = lerp(State.lift, State.targetLift, k);
State.scale = lerp(State.scale, State.targetScale, k);
State.roomRot = lerp(State.roomRot, State.roomTargetRot, k);
State.roomScale = lerp(State.roomScale, State.roomTargetScale, k);
State.rotY += State.spinSpeed * dt;
// Shake decay
State.shake *= 0.9;
// Stage 4 effects
if(State.stage===4){
State.hueShift += dt * 120;
State.saturation = 1 + Math.sin(State.time*8)*0.5;
State.brightness = 1 + Math.sin(State.time*12)*0.3;
State.invert = Math.sin(State.time*20)*0.15;
State.glitchAmount = Math.sin(State.time*30)*0.08;
// Duplicate cats orbit
State.duplicateCats.forEach(dc=>{
dc.angle += dt * (30 + dc.phase*10);
dc.radius += Math.sin(State.time*2+dc.phase)*0.5;
});
}else if(State.stage===3){
State.hueShift += dt * 30;
State.saturation = 1.2;
State.brightness = 1.1;
}else{
State.hueShift *= 0.95;
State.saturation = lerp(State.saturation, 1, dt*2);
State.brightness = lerp(State.brightness, 1, dt*2);
State.invert *= 0.9;
State.glitchAmount *= 0.9;
}
// Audio rate follows spin speed
const baseRate = 1;
const maxRate = 4;
const audioRate = baseRate + (maxRate-baseRate) * Math.min(1, State.spinSpeed/140);
AudioEngine.setRate(audioRate);
AudioEngine.update(dt);
updateParticles(dt);
// Cat position
State.cx = innerWidth/2 + (Math.random()-0.5)*State.shake;
State.cy = innerHeight*0.65 + (Math.random()-0.5)*State.shake;
}
function render(){
const ctx = CTX;
const cw = innerWidth, ch = innerHeight;
// Clear
ctx.setTransform(DPR,0,0,DPR,0,0);
ctx.fillStyle='#0a0a0c';
ctx.fillRect(0,0,cw,ch);
// Room transform
ctx.save();
ctx.translate(cw/2, ch/2);
ctx.rotate(State.roomRot);
ctx.scale(State.roomScale, State.roomScale);
ctx.translate(-cw/2, -ch/2);
// Draw room
drawRoom(ctx);
ctx.restore();
// Draw cat(s)
if(State.stage===4){
// Main cat
drawCat(ctx, State.cx, State.cy, 0, 1, 0);
// Duplicates
State.duplicateCats.forEach((dc,i)=>{
const x = State.cx + Math.cos(dc.angle)*dc.radius;
const y = State.cy - State.lift + Math.sin(dc.angle)*dc.radius*0.3;
drawCat(ctx, x, y, dc.hueShift, dc.scale, i);
});
}else{
drawCat(ctx, State.cx, State.cy, 0, 1, 0);
}
// Particles
drawParticles(ctx);
// Screen effects
if(State.stage>=3){
applyScreenEffects(ctx);
}
}
function drawRoom(ctx){
const cw=innerWidth, ch=innerHeight;
const fy = room.floorY;
// Back wall
ctx.fillStyle = room.wallTexture;
ctx.fillRect(0,0,cw,fy);
// Baseboard
ctx.fillStyle='#2a2622';
ctx.fillRect(0,fy-12,cw,12);
ctx.fillStyle='rgba(255,255,255,0.03)';
ctx.fillRect(0,fy-12,cw,2);
// Floor with perspective
ctx.save();
ctx.translate(0, fy);
// Perspective transform for floor
const perspective = 400;
for(let y=0; y<ch-fy; y+=64){
const scale = perspective / (perspective + y);
const rowY = y * scale;
const rowH = 64 * scale;
ctx.save();
ctx.scale(scale, scale);
ctx.fillStyle = room.floorPattern;
ctx.fillRect(-cw*2, y, cw*5, 64);
ctx.restore();
}
ctx.restore();
// Window light shafts
ctx.save();
ctx.globalAlpha=0.08;
const grad = ctx.createLinearGradient(cw*0.1, 0, cw*0.1, fy);
grad.addColorStop(0,'rgba(255,245,220,0.4)');
grad.addColorStop(1,'rgba(255,245,220,0)');
ctx.fillStyle=grad;
ctx.fillRect(cw*0.05, 0, cw*0.25, fy);
ctx.globalAlpha=1;
ctx.restore();
}
function drawCat(ctx, cx, cy, hueShift, scaleMult, dupIndex){
ctx.save();
ctx.translate(cx, cy - State.lift);
// Blur for high speed
const blurAmount = Math.min(30, State.spinSpeed * 0.3);
if(blurAmount > 1){
ctx.filter = `blur(${blurAmount}px)`;
}
// Hue shift for stage 4
if(hueShift){
ctx.filter = (ctx.filter||'') + ` hue-rotate(${hueShift}deg)`;
}
Cat.drawFull(ctx, {
cx:0, cy:0,
scale: State.scale * scaleMult,
rotY: State.rotY + (dupIndex?dupIndex*1.2:0),
lift: State.lift,
spinPhase: State.time * State.spinSpeed * 0.1,
stage: State.stage,
blur: blurAmount
});
ctx.filter='none';
ctx.restore();
}
function applyScreenEffects(ctx){
const cw=innerWidth, ch=innerHeight;
ctx.save();
ctx.globalCompositeOperation = State.stage===4 ? 'difference' : 'overlay';
ctx.globalAlpha = 0.15;
// Scanlines
for(let y=0;y<ch;y+=4){
ctx.fillStyle = `hsl(${State.hueShift},80%,50%)`;
ctx.fillRect(0,y,cw,1);
}
ctx.globalAlpha = 0.08;
// Vignette pulse
const vg = ctx.createRadialGradient(cw/2,ch/2,0,cw/2,ch/2,Math.max(cw,ch));
vg.addColorStop(0,'transparent');
vg.addColorStop(1,`hsl(${State.hueShift},60%,30%)`);
ctx.fillStyle=vg;
ctx.fillRect(0,0,cw,ch);
ctx.restore();
// Glitch slices
if(State.glitchAmount > 0.01){
ctx.save();
const slices = 5 + Math.floor(State.glitchAmount*50);
for(let i=0;i<slices;i++){
const y = Math.random()*ch;
const h = 2 + Math.random()*8;
const dx = (Math.random()-0.5)*State.glitchAmount*cw;
ctx.drawImage(C, 0,y,cw,h, dx,y,cw,h);
}
ctx.restore();
}
}
/* ============ INIT ============ */
// Ensure audio context starts on first interaction
document.body.addEventListener('click',()=>{AudioEngine.ensureContext();},{once:true});
document.body.addEventListener('keydown',e=>{if(e.code==='Space'){e.preventDefault();advanceStage();}});
</script>
</body>
</html>
Opening realism: The room uses a hand-drawn wood floor with perspective-correct plank scaling, a textured wallpaper back wall with subtle noise, a baseboard with highlight/shadow, and volumetric window light shafts. The cat sits on a contact shadow (radial gradient) that matches the floor perspective. Fur is built from 6 layered ellipses with varying opacity/scale for depth, irises use radial gradients, catch lights are multi-lobed. Realism gives out on close inspection: fur is procedural ellipses not strands, whiskers are quadratic curves, the cat has no true 3D geometry — rotation is faked by horizontal scaling of drawn parts.
Oiia specificity: The cat faces dead-center with zero head tilt, pupils dilated to near-iris diameter, eyes wide (not squinting), stare unbroken by blink or glance. The "oiia" vocal is synthesized as a formant sequence (o→i→i→a…) not a generic pitch sweep. Rotation is strictly vertical-axis (Y), no tumbling. The lift-off is straight up, not a jump arc. The mouth stays shut — the sound comes from nowhere, like the meme.
Four stages: 1) Liftoff — cat rises ~80px, spins at 8 rad/s, room stable, gentle fur particles. 2) Windup — 180px up, 25 rad/s, room rotates 0.15rad and scales 1.1×, more particles, audio rate ~1.8×. 3) Blur — 300px, 60 rad/s, cat motion-blurred, room 0.5rad/1.3×, hue shift begins, glitch particles, scanlines, audio ~2.8×. 4) Singularity — 450px, 140 rad/s, 2.2× scale, room spins 2.5rad/2×, six orbiting duplicate cats with individual hue rotations, full-screen hue cycling, saturation/brightness/invert pulsing, glitch slices tearing the frame, audio at 4× — the cat becomes a strobing ring of fur that reads as a single entity only because the brain refuses to let go.
Voice synthesis: A 2-second loop rendered offline into an AudioBuffer at 180Hz fundamental. Each vowel (o, i, a) has 5 fixed formant frequencies; the loop steps through "oiia oiia oiiaiooooiai" segments with per-segment raised-cosine envelopes. Glottal pulse + additive formant sines + breath noise. PlaybackRate is driven 1→4× by spin speed, so pitch and tempo rise together. A single GainNode ties to the mute button.
Would fix: The cat is a 2D cutout — at stage 4 the horizontal-scale fake-3D breaks visibly when the cat approaches 90° rotation. With more time I'd build a true 3D mesh (even low-poly) with UV-mapped fur texture and render it to an offscreen canvas at multiple angles, then sprite-sheet it for perfect rotation at any speed.