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">
<title>Oiia Cat — living room edition</title>
<style>
* { box-sizing: border-box; }
html, body { margin: 0; width: 100%; height: 100%; overflow: hidden; }
body {
background: #b9a994;
color: #fff8eb;
font: 14px/1.4 system-ui, sans-serif;
user-select: none;
}
#room {
position: relative; width: 100%; height: 100%; overflow: hidden;
isolation: isolate; perspective: 1000px;
background: linear-gradient(#d8d0c2 0 60%, #9d8064 60%);
}
#room::after {
content: ""; position: absolute; inset: 0; z-index: 5; pointer-events: none;
opacity: .13; mix-blend-mode: multiply;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 180 180' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.24'/%3E%3C/svg%3E");
}
#room-art {
position: absolute; inset: -2%; width: 104%; height: 104%;
transform-origin: 50% 55%; transition: filter 1s ease;
}
.room-svg { width: 100%; height: 100%; display: block; }
#sunbeam {
position: absolute; z-index: 1; pointer-events: none; inset: -25% 30% 5% 4%;
background: linear-gradient(110deg, transparent 14%, rgba(255,232,174,.24) 45%, transparent 78%);
filter: blur(17px); transform: rotate(-4deg); opacity: .65;
}
#floor-shadow {
position: absolute; z-index: 2; left: 50%; bottom: 10.8%;
width: min(29vw, 300px); height: 36px; border-radius: 50%;
transform: translateX(-50%); background: rgba(35,25,17,.44);
filter: blur(13px); transition: width .4s, opacity .4s, filter .4s;
}
#cat-hit {
position: absolute; z-index: 3; left: 50%; bottom: 9.5%;
width: min(34vw, 350px); height: min(43vw, 418px);
min-width: 230px; min-height: 285px;
transform: translateX(-50%); cursor: pointer; perspective: 900px;
-webkit-tap-highlight-color: transparent;
}
#cat-shell {
position: absolute; inset: 0; transform-style: preserve-3d;
transform-origin: 50% 78%; will-change: transform, filter;
}
.cat-face {
position: absolute; inset: 0; width: 100%; height: 100%;
overflow: visible; backface-visibility: hidden;
filter: drop-shadow(0 7px 5px rgba(48,33,20,.14));
}
.cat-back { transform: rotateY(180deg); }
#cat-hit:focus-visible { outline: 2px solid white; outline-offset: 12px; border-radius: 50%; }
#cat-hit:hover #cat-shell { filter: drop-shadow(0 0 12px rgba(255,239,183,.3)); }
#stage-glow {
position: absolute; z-index: 2; inset: 0; pointer-events: none; opacity: 0;
background: radial-gradient(ellipse at 50% 54%, rgba(255,225,132,.22), transparent 53%);
transition: opacity .7s;
}
#orbiters { position: absolute; z-index: 4; inset: 0; pointer-events: none; }
.orb {
position: absolute; left: 50%; top: 48%; opacity: 0;
transform: translate(-50%,-50%) scale(.2); font-size: clamp(30px, 5vw, 62px);
filter: drop-shadow(0 8px 5px rgba(20,12,8,.24));
}
#status {
position: absolute; z-index: 8; left: 22px; bottom: 19px;
color: rgba(255,249,235,.78); text-shadow: 0 1px 5px #37291e;
letter-spacing: .03em; font-size: 12px;
}
#mute {
position: absolute; z-index: 10; top: 18px; right: 20px;
border: 1px solid rgba(255,255,255,.45); border-radius: 99px;
color: #fff8eb; background: rgba(39,31,25,.32); padding: 9px 13px;
font: inherit; cursor: pointer; backdrop-filter: blur(8px);
}
#mute:hover { background: rgba(39,31,25,.55); }
#hint {
position: absolute; z-index: 8; left: 50%; bottom: 20px; transform: translateX(-50%);
padding: 7px 12px; border-radius: 30px;
color: rgba(255,249,235,.82); background: rgba(39,31,25,.2);
font-size: 12px; letter-spacing: .04em; white-space: nowrap;
transition: opacity .5s;
}
.activated #hint { opacity: 0; }
.stage-1 #stage-glow { opacity: .12; }
.stage-2 #stage-glow { opacity: .26; }
.stage-3 #stage-glow { opacity: .44; }
.stage-4 #stage-glow { opacity: .75; }
.stage-1 #room-art { filter: saturate(1.02); }
.stage-2 #room-art { filter: saturate(1.14) hue-rotate(-4deg); }
.stage-3 #room-art { filter: saturate(1.3) hue-rotate(8deg); }
.stage-4 #room-art { filter: saturate(1.65) hue-rotate(-13deg) contrast(1.06); }
.stage-2 #floor-shadow { width: 210px; opacity: .62; filter: blur(17px); }
.stage-3 #floor-shadow { width: 120px; opacity: .34; filter: blur(23px); }
.stage-4 #floor-shadow { width: 65px; opacity: .18; filter: blur(28px); }
.stage-2 .orb { opacity: .7; }
.stage-3 .orb, .stage-4 .orb { opacity: 1; }
.stage-2 .orb { animation: orbit 4s linear infinite; }
.stage-3 .orb { animation: orbit 2.5s linear infinite; }
.stage-4 .orb { animation: orbit 1.35s linear infinite; }
@keyframes orbit {
0% { transform: translate(-50%,-50%) rotate(0deg) translateX(min(24vw,245px)) rotate(0deg) scale(1); }
100% { transform: translate(-50%,-50%) rotate(360deg) translateX(min(24vw,245px)) rotate(-360deg) scale(1); }
}
.stage-3 #room-art { animation: wobble 5s ease-in-out infinite; }
.stage-4 #room-art { animation: roomspin 16s ease-in-out infinite; }
@keyframes wobble { 0%,100% { transform: rotate(0) scale(1); } 50% { transform: rotate(1deg) scale(1.025); } }
@keyframes roomspin {
0%,100% { transform: rotate(0) scale(1); }
25% { transform: rotate(2deg) scale(1.06) translate(1%, -1%); }
50% { transform: rotate(-2deg) scale(1.08) translate(-1%, 1%); }
75% { transform: rotate(1deg) scale(1.04) translate(0, -1%); }
}
@media (max-width: 600px) {
#cat-hit { width: 68vw; height: 82vw; bottom: 10%; }
#floor-shadow { bottom: 10.5%; width: 44vw; }
}
@media (prefers-reduced-motion: reduce) {
.stage-3 #room-art, .stage-4 #room-art, .orb { animation-duration: 6s; }
}
</style>
</head>
<body>
<main id="room" aria-label="A living room with a cat">
<div id="room-art" aria-hidden="true">
<svg class="room-svg" viewBox="0 0 1000 650" preserveAspectRatio="xMidYMid slice" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="wall" x2="0" y2="1"><stop stop-color="#e8e0d3"/><stop offset="1" stop-color="#c9bca9"/></linearGradient>
<linearGradient id="floor" x2="0" y2="1"><stop stop-color="#b49775"/><stop offset="1" stop-color="#795a40"/></linearGradient>
<linearGradient id="window" x2="1" y2="1"><stop stop-color="#b8d3d5"/><stop offset=".45" stop-color="#e7e2ce"/><stop offset="1" stop-color="#9eb9b1"/></linearGradient>
<linearGradient id="sofa" x2="0" y2="1"><stop stop-color="#879087"/><stop offset="1" stop-color="#58635d"/></linearGradient>
<radialGradient id="lampglow"><stop stop-color="#fff2c8" stop-opacity=".7"/><stop offset="1" stop-color="#fff2c8" stop-opacity="0"/></radialGradient>
<filter id="soft"><feGaussianBlur stdDeviation="12"/></filter>
<filter id="grain"><feTurbulence type="fractalNoise" baseFrequency=".65" numOctaves="2" stitchTiles="stitch"/><feColorMatrix values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 .08 0"/></filter>
</defs>
<!-- plaster wall and warm corner shadows -->
<rect width="1000" height="650" fill="url(#wall)"/>
<path d="M0 0h1000v45H0z" fill="#f1eade" opacity=".4"/>
<path d="M0 0h54v430H0zM946 0h54v430h-54z" fill="#9c8872" opacity=".1"/>
<ellipse cx="250" cy="230" rx="320" ry="255" fill="#fff4d9" opacity=".23"/>
<!-- window -->
<rect x="92" y="64" width="300" height="242" rx="3" fill="#766c5d" opacity=".4"/>
<rect x="101" y="72" width="282" height="225" fill="url(#window)" stroke="#f4eee1" stroke-width="12"/>
<path d="M108 253c39-52 66-45 102-17 37-40 88-57 164-20v76H108z" fill="#718477" opacity=".55"/>
<path d="M108 263c70-26 144-17 270 5v24H108z" fill="#728a7d" opacity=".55"/>
<path d="M242 78v210M108 183h269" stroke="#f3eee3" stroke-width="9"/>
<path d="M79 67h328M82 304h324" stroke="#f4eee5" stroke-width="12" stroke-linecap="round"/>
<path d="M95 313h298l20 11H75z" fill="#887661"/>
<!-- sun patch -->
<path d="M110 308L404 308 663 535 167 535z" fill="#ffdf9f" opacity=".12"/>
<!-- framed picture -->
<rect x="568" y="75" width="154" height="118" fill="#8a765e" opacity=".18"/>
<rect x="577" y="68" width="146" height="116" fill="#f4eee2" stroke="#88775f" stroke-width="7"/>
<rect x="590" y="81" width="120" height="90" fill="#b5c0ad"/>
<path d="M590 153l40-43 24 23 20-34 36 54z" fill="#758371"/>
<circle cx="678" cy="101" r="12" fill="#e6c98c"/>
<!-- plant by the window -->
<path d="M70 407h90l-10 66H81z" fill="#a46f50"/>
<path d="M83 408h64" stroke="#d09b72" stroke-width="6"/>
<g fill="#596e50">
<path d="M113 407c-50-38-45-90-25-95 25 8 34 47 25 95z"/>
<path d="M115 408c-16-56 4-111 26-104 17 24 0 76-26 104z"/>
<path d="M112 405c-6-62 25-95 43-80 9 28-17 66-43 80z"/>
<path d="M112 409c-47-13-66-48-50-60 22 2 46 29 50 60z"/>
<path d="M114 411c1-44-29-76-44-63-8 23 19 52 44 63z"/>
</g>
<g stroke="#94a17d" stroke-width="2" opacity=".7"><path d="M112 410L89 321M113 410l25-85M112 410l34-73M112 410l-42-53"/></g>
<!-- couch -->
<ellipse cx="780" cy="447" rx="242" ry="37" fill="#514b41" opacity=".18" filter="url(#soft)"/>
<path d="M612 295q0-35 38-35h262q40 0 40 42v125H612z" fill="url(#sofa)"/>
<path d="M598 353q-18 0-18 24v93h474v-89q0-28-23-28z" fill="#68736b"/>
<path d="M601 369q9-20 27-20h413q21 0 24 22v77H601z" fill="#788279"/>
<path d="M605 373q12-16 32-16h105v111H605z" fill="#838b7e"/>
<path d="M756 357h126v111H756z" fill="#707a70"/>
<path d="M888 357h122q18 7 20 24v87H888z" fill="#68736b"/>
<path d="M610 425h416M743 362v103M875 362v103" stroke="#4e5a53" stroke-width="3" opacity=".45"/>
<path d="M625 468l-8 31m382-31 8 31" stroke="#544738" stroke-width="9" stroke-linecap="round"/>
<!-- sofa cushion -->
<path d="M791 329q12-13 28-2l40 29-38 49q-9 8-20 1l-40-29z" fill="#b77c5f"/>
<path d="M797 334l52 34" stroke="#d49b7a" stroke-width="3" opacity=".6"/>
<!-- floor -->
<path d="M0 421q500-26 1000 0v229H0z" fill="url(#floor)"/>
<path d="M0 423q500-26 1000 0" fill="none" stroke="#74634e" stroke-width="5" opacity=".45"/>
<g stroke="#5f4936" opacity=".29" fill="none">
<path d="M-20 476q510-18 1040 0M-20 535q510-12 1040 0M-20 599q510-8 1040 0"/>
<path d="M150 423l-60 227M335 423l-25 227M536 423l8 227M746 423l35 227M925 423l86 227"/>
</g>
<g stroke="#dfc09a" opacity=".2">
<path d="M-20 480q510-18 1040 0M-20 539q510-12 1040 0M-20 603q510-8 1040 0"/>
</g>
<!-- rug -->
<path d="M246 454q244-29 500 0l73 161q-283 35-644 0z" fill="#b9a184" opacity=".9"/>
<path d="M269 466q215-23 453 0l53 135q-260 26-558 0z" fill="none" stroke="#e3d2b8" stroke-width="3" opacity=".6"/>
<path d="M290 475q211-20 414 0l39 115q-238 22-493 0z" fill="none" stroke="#8e7961" stroke-width="2" opacity=".4"/>
<!-- side table and lamp -->
<path d="M848 273h106l-9 13H857z" fill="#785f46"/>
<path d="M861 286h8v89h-8zm73 0h8v89h-8z" fill="#6c533c"/>
<ellipse cx="892" cy="278" rx="75" ry="85" fill="url(#lampglow)"/>
<path d="M881 151h25l18 70h-61z" fill="#e1d2b4"/>
<path d="M877 221h34l8 9h-50z" fill="#8a765e"/>
<path d="M894 230v44" stroke="#79664f" stroke-width="5"/>
<ellipse cx="894" cy="274" rx="38" ry="6" fill="#765f46"/>
<rect x="868" y="245" width="54" height="29" rx="4" fill="#9c684f"/>
<!-- gentle vignette -->
<rect width="1000" height="650" filter="url(#grain)" opacity=".4"/>
<path d="M0 0h1000v650H0z" fill="none" stroke="#43392d" stroke-opacity=".16" stroke-width="28"/>
</svg>
</div>
<div id="sunbeam"></div>
<div id="stage-glow"></div>
<div id="floor-shadow"></div>
<div id="cat-hit" role="button" tabindex="0" aria-label="Click the cat to start the Oiia spin">
<div id="cat-shell">
<!-- front -->
<svg class="cat-face cat-front" viewBox="0 0 360 430" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<defs>
<radialGradient id="fur" cx=".36" cy=".22" r=".8"><stop stop-color="#fff8e9"/><stop offset=".58" stop-color="#e7d7bb"/><stop offset="1" stop-color="#b49b78"/></radialGradient>
<radialGradient id="whitefur" cx=".45" cy=".25" r=".8"><stop stop-color="#fffefa"/><stop offset="1" stop-color="#e7dfd2"/></radialGradient>
<linearGradient id="ear" x2="0" y2="1"><stop stop-color="#ad7868"/><stop offset="1" stop-color="#d8a99a"/></linearGradient>
<radialGradient id="iris"><stop stop-color="#b9b263"/><stop offset=".7" stop-color="#788451"/><stop offset="1" stop-color="#384a39"/></radialGradient>
</defs>
<!-- tail -->
<path d="M225 322q92 11 71 76-12 34-61 19" fill="none" stroke="#c5ad8b" stroke-width="31" stroke-linecap="round"/>
<path d="M226 322q92 11 71 76-12 34-61 19" fill="none" stroke="#eadcc4" stroke-width="21" stroke-linecap="round"/>
<!-- body -->
<path d="M89 393q-6-55 10-111 18-61 77-69 69-8 99 53 23 48 5 129-2 17-19 18H108q-17-1-19-20z" fill="url(#fur)" stroke="#b9a487" stroke-width="2"/>
<path d="M111 386q-5-84 30-132 14-19 37-25-10 65-3 165z" fill="#f7f0e4" opacity=".88"/>
<path d="M227 239q50 29 49 95-2 45-12 64h-36q15-81-1-159z" fill="#d2bea0" opacity=".7"/>
<!-- chest bib -->
<path d="M143 272q37 20 75-3 24 32 19 111H124q-1-68 19-108z" fill="url(#whitefur)"/>
<!-- paws -->
<path d="M112 358q-9 25-5 46 2 12 38 12 26 0 29-10 3-18-7-48z" fill="url(#whitefur)" stroke="#c7b9a4" stroke-width="2"/>
<path d="M187 358q-7 26-3 47 2 12 37 12 27 0 30-11 2-17-7-47z" fill="url(#whitefur)" stroke="#c7b9a4" stroke-width="2"/>
<!-- head and ears -->
<path d="M90 116Q83 31 105 17q25 0 70 57 41-14 73 1 43-52 67-47 24 20 9 94 15 27 9 67-10 86-93 103-71 15-125-29-43-36-39-94 1-29 14-53z" fill="url(#fur)" stroke="#b49f80" stroke-width="2"/>
<path d="M104 34q-6 22 1 60l47-25q-31-34-48-35z" fill="url(#ear)"/>
<path d="M301 39q-21 7-43 39l48 21q5-38-5-60z" fill="url(#ear)"/>
<!-- forehead markings -->
<path d="M174 76q-15 19-12 43m31-48q-7 22-3 38m22-33q10 18 10 34" fill="none" stroke="#b99c76" stroke-width="8" stroke-linecap="round" opacity=".76"/>
<!-- cheeks -->
<path d="M104 163q22-30 61-12 10 23 1 53-31 22-62 0-12-18 0-41z" fill="#f7f0e5" opacity=".94"/>
<path d="M225 151q38-20 62 10 13 24-3 46-31 20-61-3-8-27 2-53z" fill="#f7f0e5" opacity=".94"/>
<!-- eyes -->
<ellipse cx="145" cy="139" rx="24" ry="31" fill="#fffdf7"/>
<ellipse cx="239" cy="139" rx="24" ry="31" fill="#fffdf7"/>
<ellipse cx="148" cy="141" rx="14" ry="22" fill="url(#iris)"/>
<ellipse cx="236" cy="141" rx="14" ry="22" fill="url(#iris)"/>
<ellipse cx="150" cy="143" rx="6.5" ry="18" fill="#202721"/>
<ellipse cx="234" cy="143" rx="6.5" ry="18" fill="#202721"/>
<circle cx="144" cy="132" r="5" fill="white" opacity=".95"/>
<circle cx="230" cy="132" r="5" fill="white" opacity=".95"/>
<path d="M119 106q24-17 48-2m48 0q23-15 47 3" fill="none" stroke="#a58e70" stroke-width="5" stroke-linecap="round" opacity=".65"/>
<!-- muzzle -->
<ellipse cx="167" cy="184" rx="28" ry="21" fill="#fffdf7"/>
<ellipse cx="216" cy="184" rx="28" ry="21" fill="#fffdf7"/>
<path d="M181 174q10-8 20 0 1 11-10 13-12-2-10-13z" fill="#b97976"/>
<path d="M191 187v10m0 0q-11 14-23 4m23-4q11 14 24 3" fill="none" stroke="#6d5148" stroke-width="3" stroke-linecap="round"/>
<!-- whiskers -->
<g fill="none" stroke="#8e806e" stroke-width="2" opacity=".8">
<path d="M154 188q-42-10-67-4m70 12q-43 3-67 19m120-26q42-13 70-9m-69 18q44 1 68 17"/>
</g>
<!-- fur strokes -->
<g fill="none" stroke="#fffaf0" stroke-width="2" opacity=".66" stroke-linecap="round">
<path d="M106 101l-8 21m16-17-7 25m184-26 7 23m-16-17 8 24"/>
<path d="M97 235l-9 13m20 115-8 16m161-16 9 16m-10-76 10 13"/>
<path d="M129 286q-8 19-8 36m107-29q11 18 12 34M139 397l-2 12m64-11 2 12"/>
<path d="M119 160l-10 9m155-10 10 8m-121 55 7 7m48-2-5 9"/>
</g>
<g fill="none" stroke="#b49a76" stroke-width="2" opacity=".35">
<path d="M122 277l-8 21m27-32-8 19m116 0 8 18m-27-37 7 20"/>
<path d="M105 347l-5 21m156-21 7 22m-99 35v11m27-10v11"/>
</g>
</svg>
<!-- back side for a real-feeling full turn -->
<svg class="cat-face cat-back" viewBox="0 0 360 430" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<defs><radialGradient id="backfur" cx=".38" cy=".2" r=".9"><stop stop-color="#fff7e8"/><stop offset=".7" stop-color="#dbc9a9"/><stop offset="1" stop-color="#ad9270"/></radialGradient></defs>
<path d="M225 322q92 11 71 76-12 34-61 19" fill="none" stroke="#c5ad8b" stroke-width="31" stroke-linecap="round"/>
<path d="M226 322q92 11 71 76-12 34-61 19" fill="none" stroke="#eadcc4" stroke-width="21" stroke-linecap="round"/>
<path d="M89 393q-6-55 10-111 18-61 77-69 69-8 99 53 23 48 5 129-2 17-19 18H108q-17-1-19-20z" fill="url(#backfur)" stroke="#b9a487" stroke-width="2"/>
<path d="M111 386q-5-84 30-132 14-19 37-25-10 65-3 165z" fill="#f7f0e4" opacity=".7"/>
<path d="M227 242q45 22 49 88-2 45-12 64h-36q15-81-1-152z" fill="#c9b28f" opacity=".6"/>
<path d="M142 230q29 23 77 2m-91 31q34 29 92 8m-98 31q40 30 103 11m-99 26q42 26 99 12" fill="none" stroke="#b69770" stroke-width="8" opacity=".65" stroke-linecap="round"/>
<path d="M143 272q37 20 75-3 24 32 19 111H124q-1-68 19-108z" fill="#f7f0e4" opacity=".9"/>
<path d="M112 358q-9 25-5 46 2 12 38 12 26 0 29-10 3-18-7-48zm75 0q-7 26-3 47 2 12 37 12 27 0 30-11 2-17-7-47z" fill="#eee5d6" stroke="#c7b9a4" stroke-width="2"/>
<path d="M104 34q-6 22 1 60l47-25q-31-34-48-35zm197 5q-21 7-43 39l48 21q5-38-5-60z" fill="#d5a697"/>
<g fill="none" stroke="#fffaf0" stroke-width="2" opacity=".65">
<path d="M106 101l-8 21m16-17-7 25m184-26 7 23m-16-17 8 24"/>
<path d="M97 235l-9 13m20 115-8 16m161-16 9 16m-10-76 10 13"/>
<path d="M129 286q-8 19-8 36m107-29q11 18 12 34M139 397l-2 12m64-11 2 12"/>
</g>
</svg>
</div>
</div>
<div id="orbiters" aria-hidden="true">
<span class="orb" style="--delay:0s">🐟</span>
<span class="orb" style="--delay:-.5s; margin-left:10px; margin-top:15px">🛋️</span>
<span class="orb" style="--delay:-1s; margin-left:-8px; margin-top:-8px">🪴</span>
<span class="orb" style="--delay:-1.5s; margin-left:14px; margin-top:-12px">🫖</span>
</div>
<div id="status" aria-live="polite">A very ordinary afternoon.</div>
<div id="hint">click the cat</div>
<button id="mute" type="button" aria-pressed="false">♪ sound on</button>
</main>
<script>
(() => {
const room = document.getElementById('room');
const hit = document.getElementById('cat-hit');
const shell = document.getElementById('cat-shell');
const shadow = document.getElementById('floor-shadow');
const status = document.getElementById('status');
const mute = document.getElementById('mute');
let stage = 0, angle = 0, speed = 0, targetSpeed = 0, lift = 0, targetLift = 0;
let last = performance.now(), nextVoiceAngle = 0, muted = false;
let audio, master;
const captions = [
"A very ordinary afternoon.",
"oiia. The cat has noticed you.",
"The rug is no longer in charge.",
"The living room has entered the spin.",
"THE WHOLE HOUSE IS A CAT TOY."
];
function initAudio() {
if (audio) { if (audio.state === 'suspended') audio.resume(); return; }
const AC = window.AudioContext || window.webkitAudioContext;
if (!AC) return;
audio = new AC();
master = audio.createGain();
master.gain.value = muted ? 0 : .48;
master.connect(audio.destination);
}
// A tiny formant synth: voiced sawtooth plus moving vowel resonances.
function sayVowel(vowel, spinSpeed) {
if (!audio || muted) return;
const now = audio.currentTime;
const dur = Math.max(.105, Math.min(.28, .58 / (1 + spinSpeed * .1)));
const fundamental = Math.min(490, 145 + spinSpeed * 10 + stage * 22);
const vowels = {
o: [520, 900, 1250], i: [300, 2250, 3000],
a: [800, 1250, 2750]
};
const formants = vowels[vowel] || vowels.i;
const osc = audio.createOscillator();
osc.type = 'sawtooth';
osc.frequency.setValueAtTime(fundamental * .88, now);
osc.frequency.exponentialRampToValueAtTime(fundamental, now + dur * .65);
const voice = audio.createGain();
voice.gain.setValueAtTime(.0001, now);
voice.gain.linearRampToValueAtTime(.18, now + .018);
voice.gain.setValueAtTime(.14, now + dur * .55);
voice.gain.exponentialRampToValueAtTime(.0001, now + dur);
osc.connect(voice);
formants.forEach((f, i) => {
const filter = audio.createBiquadFilter();
filter.type = 'bandpass'; filter.frequency.value = f;
filter.Q.value = i === 0 ? 1.3 : 2.1;
const level = audio.createGain();
level.gain.value = [1, .58, .2][i];
voice.connect(filter); filter.connect(level); level.connect(master);
});
osc.start(now); osc.stop(now + dur + .015);
}
function activate() {
initAudio();
stage = Math.min(4, stage + 1);
room.className = 'stage-' + stage + ' activated';
status.textContent = captions[stage];
const speeds = [0, 5, 9, 14, 21];
const heights = [0, 24, 100, 165, 205];
targetSpeed = speeds[stage];
targetLift = heights[stage];
// Each further click at the top adds a little more ridiculous momentum.
if (stage === 4 && speed > 20) targetSpeed = Math.min(31, speed + 3.2);
sayVowel('o', Math.max(speed, 3));
nextVoiceAngle = angle + .6;
}
hit.addEventListener('click', activate);
hit.addEventListener('keydown', e => {
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); activate(); }
});
mute.addEventListener('click', () => {
muted = !muted;
mute.textContent = muted ? '♪ sound off' : '♪ sound on';
mute.setAttribute('aria-pressed', String(muted));
if (audio && master) {
master.gain.setTargetAtTime(muted ? 0 : .48, audio.currentTime, .035);
}
});
const phrase = 'oiiaiooooiai';
let syllable = 1;
function frame(now) {
const dt = Math.min(.04, (now - last) / 1000);
last = now;
speed += (targetSpeed - speed) * (1 - Math.exp(-dt * 1.5));
lift += (targetLift - lift) * (1 - Math.exp(-dt * 1.35));
angle += speed * dt;
if (stage > 0 && audio && !muted && angle >= nextVoiceAngle) {
sayVowel(phrase[syllable % phrase.length], speed);
syllable++;
nextVoiceAngle += Math.max(.38, .82 - stage * .07);
}
const bob = stage ? Math.sin(now * .004 + angle * .23) * (stage * 3.5) : 0;
const yaw = angle * 180 / Math.PI;
const blur = Math.min(7, Math.max(0, (speed - 8) * .27));
const scale = 1 + Math.min(.16, lift / 1500);
shell.style.transform =
`translate3d(0,${-lift + bob}px,0) rotateY(${yaw}deg) scale(${scale})`;
shell.style.filter = `blur(${blur}px) drop-shadow(0 9px 5px rgba(48,33,20,.14))`;
shadow.style.transform = `translateX(-50%) scale(${1 - Math.min(.7, lift/360)})`;
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
})();
</script>
</body>
</html>