← Back to Articles Directory
AI Models • August 14, 2026 • 5 min read

GLM 5.3: A Great Model, With a Possible Dealbreaker

Z.ai has finally released GLM 5.3, an incredible model accessible on ZCode. We test its SVG origami crane, procedural 3D globe, wizard floating isles game, and neon runner code generations.

Mohid Mirza

Co-Founder & Lead Programmer of AcceleratedLogic AI

Z.ai has finally released GLM 5.3, which is honestly, an incredible model. So, let me tell you its specs before we dive into benchmarking.
First off, the API for it hasn’t been released, so the only way to access it is through a GLM subscription. However, you can try it for free on their ZCode platform, which is how I got access to it. It performs similarly to Kimi K3 and lags just behind American frontier AI models in benchmarks, so I wonder what the pricing will be, as that will be a major deciding factor.
So, here are its generations for each benchmark

Crane:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Glass Sphere with Origami Crane</title>
<style>
  html,body{margin:0;height:100%;display:flex;align-items:center;justify-content:center;background:radial-gradient(ellipse at 50% 35%,#3a4a5f 0%,#1a2230 55%,#0c1018 100%);}
</style>
</head>
<body>
<svg width="800" height="800" viewBox="0 0 800 800" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <!-- Glass body -->
    <radialGradient id="glass" cx="38%" cy="32%" r="75%">
      <stop offset="0%" stop-color="#ffffff" stop-opacity="0.35"/>
      <stop offset="55%" stop-color="#bcd8ee" stop-opacity="0.16"/>
      <stop offset="85%" stop-color="#7aa8cc" stop-opacity="0.28"/>
      <stop offset="100%" stop-color="#e8f6ff" stop-opacity="0.65"/>
    </radialGradient>
    <radialGradient id="innerShadow" cx="50%" cy="50%" r="50%">
      <stop offset="80%" stop-color="#000" stop-opacity="0"/>
      <stop offset="100%" stop-color="#0a2035" stop-opacity="0.55"/>
    </radialGradient>
    <linearGradient id="rim" x1="0" y1="0" x2="1" y2="1">
      <stop offset="0%" stop-color="#ffffff" stop-opacity="0.9"/>
      <stop offset="40%" stop-color="#9cc4e0" stop-opacity="0.15"/>
      <stop offset="75%" stop-color="#ffffff" stop-opacity="0.55"/>
      <stop offset="100%" stop-color="#6d94b8" stop-opacity="0.3"/>
    </linearGradient>
    <linearGradient id="specular" x1="0" y1="0" x2="0" y2="1">
      <stop offset="0%" stop-color="#ffffff" stop-opacity="0.95"/>
      <stop offset="100%" stop-color="#ffffff" stop-opacity="0"/>
    </linearGradient>
    <!-- Origami paper folds -->
    <linearGradient id="fold1" x1="0" y1="0" x2="1" y2="1">
      <stop offset="0%" stop-color="#ff9db8"/><stop offset="100%" stop-color="#d9557f"/>
    </linearGradient>
    <linearGradient id="fold2" x1="1" y1="0" x2="0" y2="1">
      <stop offset="0%" stop-color="#ffc2d4"/><stop offset="100%" stop-color="#e8749a"/>
    </linearGradient>
    <linearGradient id="fold3" x1="0" y1="1" x2="1" y2="0">
      <stop offset="0%" stop-color="#f77fa5"/><stop offset="100%" stop-color="#c34a72"/>
    </linearGradient>
    <linearGradient id="fold4" x1="0" y1="0" x2="0" y2="1">
      <stop offset="0%" stop-color="#ffd3e0"/><stop offset="100%" stop-color="#ea87a6"/>
    </linearGradient>
    <filter id="softShadow" x="-40%" y="-40%" width="180%" height="180%">
      <feDropShadow dx="0" dy="14" stdDeviation="18" flood-color="#04101d" flood-opacity="0.6"/>
    </filter>
    <filter id="craneShadow" x="-40%" y="-40%" width="180%" height="180%">
      <feDropShadow dx="-8" dy="10" stdDeviation="6" flood-color="#2a0f1c" flood-opacity="0.45"/>
    </filter>
    <clipPath id="sphereClip"><circle cx="400" cy="400" r="290"/></clipPath>
    <!-- Caustic light patch under the crane -->
    <radialGradient id="caustic" cx="50%" cy="50%" r="50%">
      <stop offset="0%" stop-color="#fff0f5" stop-opacity="0.55"/>
      <stop offset="100%" stop-color="#fff0f5" stop-opacity="0"/>
    </radialGradient>
    <radialGradient id="floorGlow" cx="50%" cy="50%" r="50%">
      <stop offset="0%" stop-color="#8fc4ee" stop-opacity="0.35"/>
      <stop offset="100%" stop-color="#8fc4ee" stop-opacity="0"/>
    </radialGradient>
  </defs>

  <!-- Ground shadow -->
  <ellipse cx="400" cy="715" rx="230" ry="42" fill="#020810" opacity="0.7" filter="url(#softShadow)"/>
  <ellipse cx="400" cy="705" rx="150" ry="24" fill="url(#floorGlow)"/>

  <!-- Glass sphere base -->
  <circle cx="400" cy="400" r="290" fill="url(#glass)" filter="url(#softShadow)"/>

  <!-- Interior: refraction environment -->
  <g clip-path="url(#sphereClip)">
    <!-- refracted light band -->
    <ellipse cx="300" cy="220" rx="180" ry="90" fill="#dff2ff" opacity="0.25" transform="rotate(-25 300 220)"/>
    <ellipse cx="520" cy="600" rx="200" ry="80" fill="#aee0ff" opacity="0.18" transform="rotate(20 520 600)"/>
    <!-- caustic from crane -->
    <ellipse cx="430" cy="590" rx="130" ry="45" fill="url(#caustic)" transform="rotate(-8 430 590)"/>

    <!-- ===== ORIGAMI CRANE ===== -->
    <g filter="url(#craneShadow)" transform="translate(400,395) rotate(-6) scale(1.05)">
      <!-- tail feathers -->
      <path d="M0,0 L175,-95 L60,-18 Z" fill="url(#fold1)" stroke="#a63d63" stroke-width="1.2"/>
      <path d="M0,0 L170,-55 L55,-8 Z" fill="url(#fold2)" stroke="#a63d63" stroke-width="0.8" opacity="0.9"/>
      <!-- back wing (raised) -->
      <path d="M-5,-15 L-70,-150 L-125,-185 L-60,-95 L-10,-25 Z" fill="url(#fold3)" stroke="#9c3a60" stroke-width="1.4"/>
      <path d="M-8,-18 L-78,-120 L-115,-170" fill="none" stroke="#8d2f54" stroke-width="1" opacity="0.7"/>
      <!-- body -->
      <path d="M10,10 L-15,-10 L-60,15 L-20,32 L25,25 Z" fill="url(#fold1)" stroke="#a63d63" stroke-width="1.3"/>
      <!-- neck -->
      <path d="M20,15 L95,-60 L112,-118 L100,-58 L38,28 Z" fill="url(#fold2)" stroke="#a63d63" stroke-width="1.2"/>
      <!-- head + beak -->
      <path d="M108,-122 q14,-8 12,4 q-2,10 -14,10 Z" fill="#d9557f" stroke="#a63d63" stroke-width="1"/>
      <path d="M118,-118 L152,-112 L119,-108 Z" fill="#f2b23f" stroke="#b57a17" stroke-width="0.8"/>
      <circle cx="110" cy="-116" r="2.4" fill="#3a1020"/>
      <!-- front wing (raised, nearer viewer) -->
      <path d="M5,-8 L55,-145 L95,-195 L45,-90 L12,-15 Z" fill="url(#fold4)" stroke="#a63d63" stroke-width="1.4"/>
      <path d="M8,-10 L60,-120 L90,-185" fill="none" stroke="#c95e85" stroke-width="1" opacity="0.7"/>
      <!-- fold creases on body -->
      <path d="M10,10 L-20,-2 M-15,-10 L-20,32" fill="none" stroke="#a63d63" stroke-width="0.7" opacity="0.6"/>
      <!-- inner glass reflection sweeping over the crane -->
      <path d="M-140,-200 Q0,-260 140,-180 L60,180 Q0,220 -60,180 Z" fill="#eaf7ff" opacity="0.10"/>
    </g>
  </g>

  <!-- Inner rim shadow for depth -->
  <circle cx="400" cy="400" r="290" fill="url(#innerShadow)"/>

  <!-- Outer rim / edge highlight -->
  <circle cx="400" cy="400" r="290" fill="none" stroke="url(#rim)" stroke-width="5"/>
  <circle cx="400" cy="400" r="286" fill="none" stroke="#ffffff" stroke-width="1.2" opacity="0.35"/>

  <!-- Specular highlights -->
  <ellipse cx="300" cy="215" rx="95" ry="55" fill="url(#specular)" transform="rotate(-32 300 215)"/>
  <ellipse cx="270" cy="190" rx="45" ry="22" fill="#ffffff" opacity="0.85" transform="rotate(-32 270 190)"/>
  <!-- refracted bright crescent bottom-right -->
  <path d="M560,560 A250,250 0 0 0 640,440 A270,270 0 0 1 560,560 Z" fill="#ffffff" opacity="0.28"/>
  <path d="M590,540 A220,220 0 0 0 630,470 A235,235 0 0 1 590,540 Z" fill="#dff2ff" opacity="0.4"/>
  <!-- small bounce light -->
  <ellipse cx="505" cy="200" rx="26" ry="14" fill="#ffffff" opacity="0.35" transform="rotate(30 505 200)"/>

  <!-- Top touch highlight -->
  <ellipse cx="400" cy="128" rx="60" ry="18" fill="#ffffff" opacity="0.25" transform="rotate(-8 400 128)"/>
</svg>
</body>
</html>
Not the best, but I see what it’s trying to do.

Globe:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Procedural 3D Globe</title>
<style>
  html,body{margin:0;height:100%;overflow:hidden;background:#04060d;font-family:system-ui,sans-serif}
  #ui{position:fixed;bottom:24px;left:50%;transform:translateX(-50%);background:rgba(10,18,32,.75);padding:14px 22px;border-radius:12px;color:#cfe6ff;backdrop-filter:blur(6px);border:1px solid rgba(120,180,255,.25)}
  #ui label{display:flex;align-items:center;gap:12px;font-size:14px}
  input[type=range]{width:240px;accent-color:#5aa2ff}
  #val{min-width:52px;text-align:right;font-variant-numeric:tabular-nums}
</style>
</head>
<body>
<div id="ui">
  <label>Rotation Speed <input id="speed" type="range" min="0" max="2" step="0.01" value="0.4"> <span id="val">0.40</span></label>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
<script>
(function(){
  // ---- Scene ----
  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(45, innerWidth/innerHeight, 0.1, 100);
  camera.position.set(0, 1.2, 4.2);
  const renderer = new THREE.WebGLRenderer({antialias:true});
  renderer.setSize(innerWidth, innerHeight);
  renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
  document.body.appendChild(renderer.domElement);

  scene.add(new THREE.AmbientLight(0x334466, 1.2));
  const sun = new THREE.DirectionalLight(0xfff2e0, 2.2);
  sun.position.set(5, 2, 3);
  scene.add(sun);

  const R = 1;

  // ---- Procedural continent texture (value-noise on canvas) ----
  function makeEarthTexture(size){
    const cv = document.createElement('canvas'); cv.width = cv.height = size;
    const ctx = cv.getContext('2d');
    const g = ctx.createLinearGradient(0,0,0,size);
    g.addColorStop(0,'#0b2d55'); g.addColorStop(.5,'#10508f'); g.addColorStop(1,'#0b2d55');
    ctx.fillStyle = g; ctx.fillRect(0,0,size,size);

    // deterministic hash-based value noise with fBm
    const P = new Uint8Array(512);
    let seed = 1337;
    const rand = () => (seed = (seed*16807)%2147483647)/2147483647;
    for(let i=0;i<256;i++) P[i]=i;
    for(let i=255;i>0;i--){const j=(rand()*(i+1))|0;const t=P[i];P[i]=P[j];P[j]=t;}
    for(let i=256;i<256;i++) P[256+i]=P[i];
    const fade = t => t*t*(3-2*t);
    const grad2 = (h,x,y) => ((h&1)?-x:x) + ((h&2)?-y:y);
    function noise(x,y){
      const X=Math.floor(x)&255, Y=Math.floor(y)&255;
      x-=Math.floor(x); y-=Math.floor(y);
      const u=fade(x), v=fade(y);
      const a=P[X]+Y, b=P[X+1]+Y;
      return THREE.MathUtils.lerp(
        THREE.MathUtils.lerp(grad2(P[a],x,y),   grad2(P[b],x-1,y), u),
        THREE.MathUtils.lerp(grad2(P[a+1],x,y-1),grad2(P[b+1],x-1,y-1), u), v);
    }
    function fbm(x,y){
      let v=0,a=.5,f=1;
      for(let o=0;o<5;o++){ v+=a*noise(x*f,y*f); f*=2; a*=.5; }
      return v;
    }

    const img = ctx.getImageData(0,0,size,size);
    const d = img.data;
    const scale = 5.5;
    for(let py=0;py<size;py++){
      const lat = py/size*Math.PI;
      for(let px=0;px<size;px++){
        // sample noise on cylinder to avoid seam
        const ang = px/size*Math.PI*2;
        const nx = Math.cos(ang)*scale, ny = Math.sin(ang)*scale, nz = lat/Math.PI*scale*2;
        let h = fbm(nx+nz*1.7, ny+nz*0.9) + fbm(nz*2.3, nx+ny)*0.5;
        h += 0.15*Math.sin(lat*6+fbm(nx,ny)*3); // banding
        const i = (py*size+px)*4;
        if(h > 0.28){
          // land: green -> mountain -> snow by height & latitude
          const t = (h-0.28)/0.7;
          let r=42+90*t, gg=110-20*t, b=52+30*t;
          const polar = Math.abs(py/size-0.5)*2;
          if(polar>0.82 || t>0.75){ r=235;gg=240;b=245; }       // ice caps / peaks
          else if(t>0.5){ r=120+80*(t-.5)/.5; gg=105; b=70; }   // mountains
          d[i]=r; d[i+1]=gg; d[i+2]=b;
        } else if(h > 0.22){
          d[i]=218; d[i+1]=205; d[i+2]=160;                       // beach
        }
      }
    }
    ctx.putImageData(img,0,0);
    // subtle cloud speckle
    ctx.globalAlpha = 0.10;
    for(let i=0;i<900;i++){
      ctx.fillStyle = '#fff';
      const x=rand()*size, y=rand()*size;
      ctx.beginPath(); ctx.ellipse(x,y,rand()*30+8,rand()*8+3,rand()*3,0,7); ctx.fill();
    }
    ctx.globalAlpha = 1;
    const tex = new THREE.CanvasTexture(cv);
    return tex;
  }

  const earthTex = makeEarthTexture(1024);

  const globe = new THREE.Mesh(
    new THREE.SphereGeometry(R, 64, 64),
    new THREE.MeshStandardMaterial({map:earthTex, roughness:0.85, metalness:0.05})
  );
  scene.add(globe);

  // ---- Atmospheric glow ----
  const atmo = new THREE.Mesh(
    new THREE.SphereGeometry(R*1.18, 48, 48),
    new THREE.ShaderMaterial({
      transparent:true, side:THREE.BackSide, blending:THREE.AdditiveBlending, depthWrite:false,
      vertexShader:`varying vec3 vN; void main(){ vN = normalize(normalMatrix*normal); gl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0); }`,
      fragmentShader:`varying vec3 vN; void main(){ float i = pow(0.72 - dot(vN, vec3(0.,0.,1.)), 3.0); gl_FragColor = vec4(0.3,0.6,1.0,1.0)*i; }`
    })
  );
  scene.add(atmo);

  // ---- Orbiting particle ring ----
  const COUNT = 1500;
  const pos = new Float32Array(COUNT*3);
  const phases = new Float32Array(COUNT), radii = new Float32Array(COUNT), heights = new Float32Array(COUNT);
  for(let i=0;i<COUNT;i++){
    phases[i] = Math.random()*Math.PI*2;
    radii[i]  = R*1.35 + Math.random()*R*0.5;
    heights[i]= (Math.random()-0.5)*0.25;
  }
  const pGeo = new THREE.BufferGeometry();
  pGeo.setAttribute('position', new THREE.BufferAttribute(pos,3));
  const ring = new THREE.Points(pGeo, new THREE.PointsMaterial({
    color:0x9fd0ff, size:0.02, transparent:true, opacity:0.9, blending:THREE.AdditiveBlending, depthWrite:false
  }));
  ring.rotation.z = 0.35;
  scene.add(ring);

  // ---- Controls: drag rotate + wheel zoom ----
  let dragging=false, px=0, py=0;
  let rotX = 0.25, rotY = 0, spin = 0.4;
  const el = renderer.domElement;
  el.addEventListener('pointerdown', e=>{dragging=true;px=e.clientX;py=e.clientY;el.setPointerCapture(e.pointerId);});
  el.addEventListener('pointermove', e=>{
    if(!dragging) return;
    rotY += (e.clientX-px)*0.005;
    rotX = THREE.MathUtils.clamp(rotX + (e.clientY-py)*0.005, -1.3, 1.3);
    px=e.clientX; py=e.clientY;
  });
  el.addEventListener('pointerup', ()=>dragging=false);
  let zoom = 4.2;
  el.addEventListener('wheel', e=>{
    e.preventDefault();
    zoom = THREE.MathUtils.clamp(zoom + e.deltaY*0.002, 2.2, 8);
  }, {passive:false});

  const slider = document.getElementById('speed');
  const valEl = document.getElementById('val');
  slider.addEventListener('input', ()=>{ spin = +slider.value; valEl.textContent = spin.toFixed(2); });

  addEventListener('resize', ()=>{
    camera.aspect = innerWidth/innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(innerWidth, innerHeight);
  });

  // ---- Animate ----
  const clock = new THREE.Clock();
  function animate(){
    requestAnimationFrame(animate);
    const t = clock.getElapsedTime();
    globe.rotation.y += spin*0.01;
    globe.rotation.x = rotX*0.4;
    // particles orbit
    for(let i=0;i<COUNT;i++){
      const a = phases[i] + t*(0.25 + 0.35/radii[i]);
      pos[i*3]   = Math.cos(a)*radii[i];
      pos[i*3+1] = heights[i]*Math.sin(a*2+phases[i]);
      pos[i*3+2] = Math.sin(a)*radii[i];
    }
    pGeo.attributes.position.needsUpdate = true;
    camera.position.x = Math.sin(rotY)*zoom*Math.cos(rotX);
    camera.position.y = Math.sin(rotX)*zoom;
    camera.position.z = Math.cos(rotY)*zoom*Math.cos(rotX);
    camera.lookAt(0,0,0);
    renderer.render(scene, camera);
  }
  animate();
})();
</script>
</body>
</html>
Probably the best one I’ve seen so far.

Wizard:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Wizard of the Floating Isles</title>
<style>
  html,body{margin:0;height:100%;overflow:hidden;background:#aee7ff;font-family:system-ui,sans-serif;user-select:none}
  canvas{display:block}
  #hud{position:fixed;top:16px;left:16px;color:#fff;text-shadow:0 2px 4px rgba(0,0,0,.4);font-size:18px;line-height:1.5}
  #hpbar{width:220px;height:14px;background:rgba(0,0,0,.35);border-radius:8px;overflow:hidden;margin-top:4px}
  #hpfill{height:100%;width:100%;background:linear-gradient(90deg,#7dffa0,#2ecc71);transition:width .2s}
  #msg{position:fixed;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;background:rgba(10,20,40,.55);color:#fff;text-align:center}
  #msg h1{font-size:44px;margin:0 0 12px}
  #msg p{font-size:18px;margin:6px}
  button{font-size:20px;padding:12px 32px;border-radius:10px;border:none;cursor:pointer;background:#ffd166;color:#4a3000;margin-top:16px}
  .hidden{display:none!important}
</style>
</head>
<body>
<div id="hud">
  Score: <span id="score">0</span> / 10<br>
  Health
  <div id="hpbar"><div id="hpfill"></div></div>
</div>
<div id="msg">
  <h1 id="title">Wizard of the Floating Isles</h1>
  <p id="subtitle">WASD to move · SPACE to jump · drag mouse to look<br>Collect 10 crystal artifacts — dodge the elemental turrets!</p>
  <button id="startBtn">Start</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
<script>
(function(){
  const W = () => innerWidth, H = () => innerHeight;
  const scene = new THREE.Scene();
  scene.background = new THREE.Color(0x9fd8f5);
  scene.fog = new THREE.Fog(0x9fd8f5, 30, 120);
  const camera = new THREE.PerspectiveCamera(60, W()/H(), .1, 300);
  const renderer = new THREE.WebGLRenderer({antialias:true});
  renderer.setSize(W(), H());
  renderer.setPixelRatio(Math.min(devicePixelRatio,2));
  renderer.shadowMap.enabled = true;
  document.body.appendChild(renderer.domElement);

  // ---------- Lights / day-night ----------
  const hemi = new THREE.HemisphereLight(0xbfe8ff, 0xffd9e8, 0.8); scene.add(hemi);
  const sun = new THREE.DirectionalLight(0xfff3d6, 1.6);
  sun.castShadow = true;
  sun.shadow.mapSize.set(1024,1024);
  Object.assign(sun.shadow.camera,{left:-40,right:40,top:40,bottom:-40,far:120});
  scene.add(sun);

  // ---------- World: floating islands ----------
  const islands = []; // {mesh, x,z,r} for collision
  const pastel = [0xffc1d9, 0xc7b8ff, 0xbaf0c4, 0xffe3a3, 0xa8dced, 0xf8b7d4];
  function makeIsland(x, y, z, r){
    const g = new THREE.Group();
    const top = new THREE.Mesh(new THREE.CylinderGeometry(r, r*0.75, 1.6, 12),
      new THREE.MeshStandardMaterial({color: pastel[(Math.random()*pastel.length)|0], flatShading:true, roughness:.9}));
    top.position.y = -0.8;
    top.castShadow = top.receiveShadow = true;
    g.add(top);
    const rock = new THREE.Mesh(new THREE.ConeGeometry(r*0.75, r*1.6, 8),
      new THREE.MeshStandardMaterial({color:0x9c8fb5, flatShading:true}));
    rock.position.y = -2.2; rock.rotation.x = Math.PI;
    g.add(rock);
    // decorative trees
    const nT = 1 + (Math.random()*3|0);
    for(let i=0;i<nT;i++){
      const tr = new THREE.Group();
      const a = Math.random()*Math.PI*2, d = Math.random()*r*0.6;
      tr.position.set(Math.cos(a)*d, 0, Math.sin(a)*d);
      const trunk = new THREE.Mesh(new THREE.CylinderGeometry(.12,.16,.7,6), new THREE.MeshStandardMaterial({color:0xb5836b}));
      trunk.position.y=.35; tr.add(trunk);
      const leaf = new THREE.Mesh(new THREE.ConeGeometry(.55,1.2,7), new THREE.MeshStandardMaterial({color: pastel[(Math.random()*pastel.length)|0], flatShading:true}));
      leaf.position.y=1.2; leaf.castShadow=true; tr.add(leaf);
      g.add(tr);
    }
    g.position.set(x,y,z);
    scene.add(g);
    islands.push({x, y, z, r, group:g});
    return g;
  }
  const layout = [[0,0,7],[14,-1,5],[-13,-2,5],[8,-8,4.5],[-8,-9,4.5],[22,-4,4],[-21,-6,4],[3,-16,4],[-4,-18,3.5]];
  layout.forEach(l=>makeIsland(l[0],l[1],l[2],l[1+0]===undefined?0:l[1]));
  // fix y usage: layout is [x, y, z] already handled above? ensure:
  islands.length = 0; scene.clear(); scene.add(hemi); scene.add(sun);
  layout.forEach(l=>makeIsland(l[0], l[1], l[2]));
  // bridges (visual)
  layout.slice(1).forEach(l=>{
    const from = layout[0];
    const mid = new THREE.Mesh(new THREE.BoxGeometry(Math.hypot(l[0]-from[0],l[2]-from[2])*0.5, .3, 1.4),
      new THREE.MeshStandardMaterial({color:0xf5d9b8}));
    mid.position.set((l[0]+from[0])/2, Math.min(l[1],from[1])+0.1, (l[2]+from[2])/2);
    mid.rotation.y = -Math.atan2(l[2]-from[2], l[0]-from[0]);
    scene.add(mid);
  });

  // ---------- Wizard ----------
  const wiz = new THREE.Group();
  const robe = new THREE.Mesh(new THREE.ConeGeometry(.45,1.1,8), new THREE.MeshStandardMaterial({color:0x8f7bff, flatShading:true}));
  robe.position.y=.55; robe.castShadow=true; wiz.add(robe);
  const head = new THREE.Mesh(new THREE.SphereGeometry(.24,10,10), new THREE.MeshStandardMaterial({color:0xffe0c2}));
  head.position.y=1.3; wiz.add(head);
  const hat = new THREE.Mesh(new THREE.ConeGeometry(.34,.75,8), new THREE.MeshStandardMaterial({color:0x5b48d8, flatShading:true}));
  hat.position.y=1.75; hat.castShadow=true; wiz.add(hat);
  const staff = new THREE.Mesh(new THREE.CylinderGeometry(.05,.05,1.6,6), new THREE.MeshStandardMaterial({color:0x8a5a3a}));
  staff.position.set(.5,.8,0); wiz.add(staff);
  const orb = new THREE.Mesh(new THREE.SphereGeometry(.11,8,8), new THREE.MeshStandardMaterial({color:0x7dffe0, emissive:0x35ffc0, emissiveIntensity:2}));
  orb.position.set(.5,1.62,0); wiz.add(orb);
  scene.add(wiz);
  const player = {pos:new THREE.Vector3(0,1.5,0), vel:new THREE.Vector3(), onGround:false, hp:100, score:0, yaw:0};

  // ---------- Crystals ----------
  const crystals = [];
  layout.forEach((l,i)=>{
    const c = new THREE.Mesh(new THREE.OctahedronGeometry(.45),
      new THREE.MeshStandardMaterial({color:0xff7de9, emissive:0xff4fd0, emissiveIntensity:1.4, metalness:.3, roughness:.2}));
    const a = Math.random()*Math.PI*2, d = Math.random()*l[2]*0.4;
    c.position.set(l[0]+Math.cos(a)*d, l[1]+1.4, l[2]+Math.sin(a)*d);
    scene.add(c); crystals.push(c);
  });

  // ---------- Turrets ----------
  const turrets = [];
  [[14,-1,5],[8,-8,4.5],[22,-4,4],[-4,-18,3.5]].forEach(l=>{
    const t = new THREE.Group();
    const base = new THREE.Mesh(new THREE.CylinderGeometry(.5,.65,.8,8), new THREE.MeshStandardMaterial({color:0xff9a6b, flatShading:true}));
    base.position.y=.4; t.add(base);
    const eye = new THREE.Mesh(new THREE.SphereGeometry(.22,8,8), new THREE.MeshStandardMaterial({color:0xff3b3b, emissive:0xff2222, emissiveIntensity:1.5}));
    eye.position.y=.95; t.add(eye);
    t.position.set(l[0], l[1], l[2]);
    scene.add(t);
    turrets.push({group:t, eye, cd:Math.random()*2, isle:l});
  });
  const projectiles = [];

  // ---------- Particles (ambient sparkles) ----------
  const pCount = 300, pPos = new Float32Array(pCount*3);
  for(let i=0;i<pCount;i++){ pPos[i*3]=(Math.random()-.5)*60; pPos[i*3+1]=Math.random()*20-5; pPos[i*3+2]=(Math.random()-.5)*60; }
  const pGeo = new THREE.BufferGeometry();
  pGeo.setAttribute('position', new THREE.BufferAttribute(pPos,3));
  scene.add(new THREE.Points(pGeo, new THREE.PointsMaterial({color:0xffffff, size:.12, transparent:true, opacity:.7})));

  // ---------- Clouds ----------
  for(let i=0;i<14;i++){
    const cl = new THREE.Mesh(new THREE.SphereGeometry(2+Math.random()*2,8,8),
      new THREE.MeshStandardMaterial({color:0xffffff, transparent:true, opacity:.85, flatShading:true}));
    cl.scale.y=.4;
    cl.position.set((Math.random()-.5)*90, 6+Math.random()*8, (Math.random()-.5)*90);
    scene.add(cl);
  }

  // ---------- Audio ----------
  let AC=null;
  function audio(){ if(!AC) AC = new (window.AudioContext||window.webkitAudioContext)(); return AC; }
  function beep(f, dur, type, vol){
    try{
      const ac = audio(), o = ac.createOscillator(), g = ac.createGain();
      o.type = type||'sine'; o.frequency.value = f;
      g.gain.setValueAtTime(vol||.2, ac.currentTime);
      g.gain.exponentialRampToValueAtTime(.001, ac.currentTime+dur);
      o.connect(g); g.connect(ac.destination);
      o.start(); o.stop(ac.currentTime+dur);
    }catch(e){ /* audio init not supported; ignore */ }
  }

  // ---------- Input ----------
  const keys = {};
  addEventListener('keydown', e=>{ keys[e.code]=true; if(e.code==='Space') e.preventDefault(); });
  addEventListener('keyup', e=>keys[e.code]=false);
  let camYaw=0, camPitch=.35, dragging=false, mx=0, my=0;
  renderer.domElement.addEventListener('pointerdown', e=>{dragging=true;mx=e.clientX;my=e.clientY;});
  addEventListener('pointerup', ()=>dragging=false);
  addEventListener('pointermove', e=>{
    if(!dragging) return;
    camYaw -= (e.clientX-mx)*.005;
    camPitch = THREE.MathUtils.clamp(camPitch+(e.clientY-my)*.004, -.1, 1.2);
    mx=e.clientX; my=e.clientY;
  });

  // ---------- Game state ----------
  const msg=document.getElementById('msg'), title=document.getElementById('title'),
        sub=document.getElementById('subtitle'), btn=document.getElementById('startBtn'),
        scoreEl=document.getElementById('score'), hpfill=document.getElementById('hpfill');
  let running=false, gameOver=false;
  const clock = new THREE.Clock();

  function endGame(win){
    running=false; gameOver=true;
    title.textContent = win ? 'You Win! 🪄' : 'Game Over';
    sub.textContent = `Final score: ${player.score} artifacts`;
    btn.textContent = 'Restart';
    msg.classList.remove('hidden');
    beep(win?880:140, .5, win?'triangle':'sawtooth', .25);
  }
  function reset(){
    player.pos.set(0,1.5,0); player.vel.set(0,0,0); player.hp=100; player.score=0;
    projectiles.forEach(p=>scene.remove(p.mesh)); projectiles.length=0;
    crystals.forEach(c=>c.visible=true);
    scoreEl.textContent=0; hpfill.style.width='100%';
    gameOver=false;
  }
  btn.addEventListener('click', ()=>{
    audio();
    if(gameOver) reset();
    msg.classList.add('hidden');
    running=true;
  });

  function groundAt(x, z){
    // returns island surface y if standing on one, else -Infinity
    let best = -Infinity;
    for(const isl of islands){
      const d = Math.hypot(x-isl.x, z-isl.z);
      if(d < isl.r) best = Math.max(best, isl.y + 0.05);
    }
    return best;
  }

  function animate(){
    requestAnimationFrame(animate);
    const dt = Math.min(clock.getDelta(), .05);
    const t = clock.elapsedTime;

    // day-night cycle
    const dayPhase = (Math.sin(t*.08)+1)/2;
    sun.intensity = .4 + 1.4*dayPhase;
    sun.position.set(Math.cos(t*.08)*40, 20+20*dayPhase, 20);
    const skyDay = new THREE.Color(0x9fd8f5), skyNight = new THREE.Color(0x1a2550);
    scene.background.copy(skyNight).lerp(skyDay, dayPhase);
    scene.fog.color.copy(scene.background);
    hemi.intensity = .3 + .6*dayPhase;

    crystals.forEach(c=>{ c.rotation.y += dt*2; c.position.y += Math.sin(t*3+c.id)*.002; });
    pGeo.attributes.position.needsUpdate = true;

    if(running){
      // movement
      const fwd = new THREE.Vector3(-Math.sin(camYaw),0,-Math.cos(camYaw));
      const right = new THREE.Vector3(-fwd.z,0,fwd.x);
      const mv = new THREE.Vector3();
      if(keys.KeyW) mv.add(fwd); if(keys.KeyS) mv.sub(fwd);
      if(keys.KeyD) mv.add(right); if(keys.KeyA) mv.sub(right);
      if(mv.lengthSq()>0){ mv.normalize(); player.yaw = Math.atan2(mv.x,mv.z); }
      player.pos.addScaledVector(mv, 6*dt);
      if(keys.Space && player.onGround){ player.vel.y = 8; player.onGround=false; beep(500,.15,'square',.12); }

      // gravity + landing
      player.vel.y -= 22*dt;
      player.pos.y += player.vel.y*dt;
      const gy = groundAt(player.pos.x, player.pos.z);
      if(player.pos.y <= gy+1.4 && gy > -Infinity && player.vel.y<=0){
        player.pos.y = gy+1.4; player.vel.y=0; player.onGround=true;
      } else player.onGround=false;
      // fell off
      if(player.pos.y < -25){ player.hp = 0; }

      wiz.position.copy(player.pos);
      wiz.rotation.y = player.yaw;

      // crystals pickup
      crystals.forEach(c=>{
        if(c.visible && c.position.distanceTo(player.pos) < 1.2){
          c.visible=false; player.score++;
          scoreEl.textContent = player.score;
          beep(880+player.score*60,.2,'triangle',.2);
          if(player.score>=10) endGame(true);
        }
      });

      // turrets shoot
      turrets.forEach(tr=>{
        tr.group.rotation.y = t;
        tr.cd -= dt;
        const d = tr.group.position.distanceTo(player.pos);
        if(d < 18 && tr.cd<=0){
          tr.cd = 2.2;
          const m = new THREE.Mesh(new THREE.SphereGeometry(.18,8,8),
            new THREE.MeshStandardMaterial({color:0xff6b4b, emissive:0xff4422, emissiveIntensity:2}));
          m.position.copy(tr.eye.getWorldPosition(new THREE.Vector3()));
          const dir = player.pos.clone().add(new THREE.Vector3(0,1,0)).sub(m.position).normalize();
          scene.add(m);
          projectiles.push({mesh:m, vel:dir.multiplyScalar(11), life:4});
          beep(180,.12,'sawtooth',.08);
        }
      });
      for(let i=projectiles.length-1;i>=0;i--){
        const p = projectiles[i];
        p.mesh.position.addScaledVector(p.vel, dt);
        p.life -= dt;
        if(p.mesh.position.distanceTo(player.pos) < .9){
          player.hp -= 15; hpfill.style.width = Math.max(0,player.hp)+'%';
          beep(120,.25,'sawtooth',.2);
          scene.remove(p.mesh); projectiles.splice(i,1);
          if(player.hp<=0) endGame(false);
        } else if(p.life<=0){ scene.remove(p.mesh); projectiles.splice(i,1); }
      }
    } else {
      wiz.position.copy(player.pos);
    }

    // camera follow with damping
    const camTarget = new THREE.Vector3(
      player.pos.x + Math.sin(camYaw)*7*Math.cos(camPitch),
      player.pos.y + 2 + 7*Math.sin(camPitch),
      player.pos.z + Math.cos(camYaw)*7*Math.cos(camPitch));
    camera.position.lerp(camTarget, .08);
    camera.lookAt(player.pos.x, player.pos.y+1.2, player.pos.z);

    renderer.render(scene, camera);
  }
  animate();

  addEventListener('resize', ()=>{
    camera.aspect=W()/H(); camera.updateProjectionMatrix();
    renderer.setSize(W(),H());
  });
})();
</script>
</body>
</html>
One glitch really ruins the whole thing

Neon Runner:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>NEON RUNNER</title>
<style>
  html,body{margin:0;height:100%;overflow:hidden;background:#07030f;font-family:'Segoe UI',system-ui,sans-serif;user-select:none}
  canvas{display:block}
  .ui{position:fixed;color:#fff;text-shadow:0 0 12px #ff2fd6}
  #hud{top:16px;left:16px;font-size:20px;line-height:1.6}
  #mult{top:16px;right:16px;font-size:28px;color:#2ffcff;text-shadow:0 0 14px #2ffcff}
  #menu{inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;background:rgba(5,0,15,.82);backdrop-filter:blur(4px)}
  #menu h1{font-size:64px;margin:0;letter-spacing:8px;background:linear-gradient(90deg,#ff2fd6,#2ffcff);-webkit-background-clip:text;-webkit-text-fill-color:transparent}
  #menu p{color:#b9a8e8;margin:8px 0 2px;font-size:16px}
  #board{margin-top:18px;color:#2ffcff;font-size:15px;text-align:center;line-height:1.7}
  button{font-size:22px;padding:14px 44px;border-radius:999px;border:2px solid #2ffcff;background:transparent;color:#2ffcff;cursor:pointer;letter-spacing:4px;margin-top:22px;box-shadow:0 0 18px #2ffcff66, inset 0 0 18px #2ffcff33;transition:.2s}
  button:hover{background:#2ffcff22;box-shadow:0 0 30px #2ffcff}
  .hidden{display:none!important}
  #touch{bottom:0;left:0;right:0;height:35%;display:none}
</style>
</head>
<body>
<div id="hud" class="ui">Score <span id="score">0</span><br>Speed <span id="spd">0</span></div>
<div id="mult" class="ui">x1</div>
<div id="menu" class="ui">
  <h1>NEON RUNNER</h1>
  <p>A / D or ← / → or touch to steer · dodge lasers &amp; rocks · grab boosts</p>
  <div id="board">HIGH SCORES</div>
  <button id="start">START</button>
</div>
<div id="touch" class="ui"></div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
<script>
(function(){
  const scene = new THREE.Scene();
  scene.background = new THREE.Color(0x0a0418);
  scene.fog = new THREE.Fog(0x0a0418, 30, 140);
  const camera = new THREE.PerspectiveCamera(70, innerWidth/innerHeight, .1, 300);
  const renderer = new THREE.WebGLRenderer({antialias:true});
  renderer.setSize(innerWidth, innerHeight);
  renderer.setPixelRatio(Math.min(devicePixelRatio,2));
  document.body.appendChild(renderer.domElement);

  scene.add(new THREE.AmbientLight(0x331166, 1.4));
  const magenta = new THREE.PointLight(0xff2fd6, 3, 60); scene.add(magenta);
  const cyan = new THREE.PointLight(0x2ffcff, 3, 60); scene.add(cyan);

  // ---------- Canyon walls ----------
  const wallMatA = new THREE.MeshStandardMaterial({color:0x1a0b33, emissive:0x330066, roughness:.6});
  const neonMatA = new THREE.MeshBasicMaterial({color:0xff2fd6});
  const neonMatB = new THREE.MeshBasicMaterial({color:0x2ffcff});
  const WALL_X = 11, SEG_LEN = 20, SEG_COUNT = 12;
  const walls = [];
  function buildSegment(z){
    const g = new THREE.Group();
    for(const side of [-1,1]){
      const h = 6 + Math.random()*8;
      const w = new THREE.Mesh(new THREE.BoxGeometry(3, h, SEG_LEN*.96), wallMatA);
      w.position.set(side*(WALL_X+1.5), h/2-2, 0);
      g.add(w);
      // neon strips
      for(let i=0;i<3;i++){
        const s = new THREE.Mesh(new THREE.BoxGeometry(.2,.2,SEG_LEN*.9), Math.random()<.5?neonMatA:neonMatB);
        s.position.set(side*(WALL_X-.35), .5+Math.random()*7, 0);
        g.add(s);
      }
      // pylons
      const p = new THREE.Mesh(new THREE.BoxGeometry(.6,10+Math.random()*6,.6), neonMatA);
      p.position.set(side*(WALL_X+2), 3, -SEG_LEN/2);
      g.add(p);
    }
    // floor glow grid
    for(let i=0;i<6;i++){
      const f = new THREE.Mesh(new THREE.BoxGeometry(WALL_X*2,.05,.15), neonMatB);
      f.position.set(0,-1.4, -SEG_LEN/2 + i*SEG_LEN/6);
      g.add(f);
    }
    g.position.z = z;
    scene.add(g);
    return g;
  }
  for(let i=0;i<SEG_COUNT;i++) walls.push(buildSegment(-i*SEG_LEN));

  // ---------- Player hover-car ----------
  const car = new THREE.Group();
  const bodyMat = new THREE.MeshStandardMaterial({color:0x2ffcff, emissive:0x0e6677, metalness:.7, roughness:.3});
  const body = new THREE.Mesh(new THREE.BoxGeometry(1.6,.5,3), bodyMat);
  body.position.y=.2; car.add(body);
  const nose = new THREE.Mesh(new THREE.ConeGeometry(.7,1.4,4), bodyMat);
  nose.rotation.x = -Math.PI/2; nose.rotation.y = Math.PI/4; nose.position.set(0,.2,2); car.add(nose);
  for(const s of [-1,1]){
    const wing = new THREE.Mesh(new THREE.BoxGeometry(1,.12,.9), new THREE.MeshStandardMaterial({color:0xff2fd6, emissive:0x880066}));
    wing.position.set(s*1.2,.5,-1.2); wing.rotation.z = s*.3; car.add(wing);
  }
  const jet = new THREE.Mesh(new THREE.ConeGeometry(.4,1.2,8), new THREE.MeshBasicMaterial({color:0x2ffcff, transparent:true, opacity:.8}));
  jet.rotation.x = Math.PI/2; jet.position.set(0,.2,-2); car.add(jet);
  scene.add(car);

  // ---------- Obstacles / pickups / lasers ----------
  const obstacles = []; // {mesh, type, x}
  function spawnRow(){
    const z = car.position.z - 130;
    const roll = Math.random();
    if(roll < .4){
      // rock
      const m = new THREE.Mesh(new THREE.DodecahedronGeometry(1+Math.random()),
        new THREE.MeshStandardMaterial({color:0x552299, emissive:0x220066, flatShading:true}));
      m.position.set((Math.random()*2-1)*(WALL_X-2), -0.2, z);
      scene.add(m); obstacles.push({mesh:m, type:'rock', vz:0});
    } else if(roll < .7){
      // moving drone
      const m = new THREE.Mesh(new THREE.OctahedronGeometry(.9),
        new THREE.MeshStandardMaterial({color:0xff2fd6, emissive:0xaa0088, flatShading:true}));
      m.position.set(0, .6, z);
      scene.add(m); obstacles.push({mesh:m, type:'drone', dir:Math.random()<.5?1:-1, vz:0});
    } else if(roll < .85){
      // laser barrier
      const m = new THREE.Mesh(new THREE.BoxGeometry(WALL_X*2-2,.25,.25),
        new THREE.MeshBasicMaterial({color:0xff2233}));
      m.position.set(0, .4+Math.random()*2, z);
      scene.add(m); obstacles.push({mesh:m, type:'laser', phase:Math.random()*7, vz:0, baseY:m.position.y});
    } else {
      // energy boost
      const m = new THREE.Mesh(new THREE.TorusGeometry(.6,.18,8,16),
        new THREE.MeshStandardMaterial({color:0x9dff2f, emissive:0x55aa00, emissiveIntensity:1.5}));
      m.position.set((Math.random()*2-1)*(WALL_X-3), .8, z);
      scene.add(m); obstacles.push({mesh:m, type:'boost', vz:0});
    }
  }

  // ---------- Floating score text (CSS) ----------
  const floats = [];
  function floatText(txt, x, y, color){
    const el = document.createElement('div');
    el.textContent = txt;
    el.style.cssText = `position:fixed;left:${x}px;top:${y}px;color:${color};font-size:26px;font-weight:bold;text-shadow:0 0 12px ${color};pointer-events:none;transition:all .9s ease-out`;
    document.body.appendChild(el);
    requestAnimationFrame(()=>{ el.style.top = (y-90)+'px'; el.style.opacity = '0'; });
    setTimeout(()=>el.remove(), 1000);
  }

  // ---------- Audio ----------
  let AC=null, musicTimer=null, musicStep=0;
  function audio(){ if(!AC) AC = new (window.AudioContext||window.webkitAudioContext)(); return AC; }
  function tone(f, dur, type, vol, when){
    const ac = audio();
    const o = ac.createOscillator(), g = ac.createGain();
    o.type = type||'sine'; o.frequency.value = f;
    const t0 = ac.currentTime + (when||0);
    g.gain.setValueAtTime(vol||.15, t0);
    g.gain.exponentialRampToValueAtTime(.001, t0+dur);
    o.connect(g); g.connect(ac.destination);
    o.start(t0); o.stop(t0+dur);
  }
  const BASS = [55,55,65.4,49], LEAD = [440,523,659,523,392,440,349,392];
  function startMusic(){
    stopMusic();
    musicTimer = setInterval(()=>{
      tone(BASS[musicStep%4], .28, 'sawtooth', .1);
      tone(BASS[musicStep%4]*2, .14, 'square', .04);
      if(musicStep%2===0) tone(LEAD[(musicStep/2)%8], .22, 'triangle', .05);
      musicStep++;
    }, 300);
  }
  function stopMusic(){ if(musicTimer){clearInterval(musicTimer); musicTimer=null;} }

  // ---------- UI ----------
  const menu=document.getElementById('menu'), startBtn=document.getElementById('start'),
        scoreEl=document.getElementById('score'), spdEl=document.getElementById('spd'),
        multEl=document.getElementById('mult'), board=document.getElementById('board');
  let running=false, score=0, mult=1, multTimer=0, speed=30;
  function loadScores(){
    try{ return JSON.parse(localStorage.getItem('neonRunnerScores')||'[]'); }catch(e){ return []; }
  }
  function showBoard(){
    const s = loadScores();
    board.innerHTML = 'HIGH SCORES<br>' + (s.length? s.slice(0,5).map((v,i)=>`${i+1}. ${v}`).join('<br>') : '— none yet —');
  }
  function saveScore(v){
    const s = loadScores(); s.push(v); s.sort((a,b)=>b-a);
    localStorage.setItem('neonRunnerScores', JSON.stringify(s.slice(0,10)));
    showBoard();
  }
  showBoard();

  // ---------- Input ----------
  const keys = {};
  let steer = 0, touchX = null;
  addEventListener('keydown', e=>{ keys[e.code]=true; if(e.code.startsWith('Arrow')) e.preventDefault(); });
  addEventListener('keyup', e=>keys[e.code]=false);
  const touchZone = document.getElementById('touch');
  touchZone.style.display = 'block'; touchZone.style.pointerEvents='none';
  addEventListener('touchstart', e=>touchX = e.touches[0].clientX, {passive:true});
  addEventListener('touchmove', e=>touchX = e.touches[0].clientX, {passive:true});
  addEventListener('touchend', ()=>touchX=null, {passive:true});

  // ---------- Game loop ----------
  const clock = new THREE.Clock();
  let travel = 0;
  function reset(){
    obstacles.forEach(o=>scene.remove(o.mesh)); obstacles.length=0;
    score=0; mult=1; speed=30; travel=0;
    car.position.set(0,0,0);
    scoreEl.textContent=0; multEl.textContent='x1';
  }
  startBtn.addEventListener('click', ()=>{
    audio(); reset();
    menu.classList.add('hidden');
    running=true;
    startMusic();
    tone(880,.2,'triangle',.15); tone(1320,.3,'triangle',.1,.1);
  });
  function crash(){
    running=false; stopMusic();
    tone(110,.6,'sawtooth',.3); tone(55,.9,'square',.2,.1);
    saveScore(Math.floor(score));
    menu.classList.remove('hidden');
    document.getElementById('menu').querySelector('p').textContent = `CRASHED — Score: ${Math.floor(score)}`;
  }

  function animate(){
    requestAnimationFrame(animate);
    const dt = Math.min(clock.getDelta(), .05);
    const t = clock.elapsedTime;

    // always animate visuals
    car.rotation.z = -steer*.4;
    car.rotation.y = steer*.15;
    jet.scale.setScalar(.8 + Math.sin(t*30)*.2 + speed/200);
    magenta.position.set(Math.sin(t)*8, 5, car.position.z-10);
    cyan.position.set(Math.cos(t*1.3)*8, 5, car.position.z-20);

    if(running){
      speed += dt*1.2; // ramp up
      score += speed*dt*.1*mult;
      scoreEl.textContent = Math.floor(score);
      spdEl.textContent = Math.floor(speed*3.6);
      multTimer -= dt;
      if(multTimer<=0 && mult>1){ mult=Math.max(1,mult-1); multEl.textContent='x'+mult; }

      // steering
      let s = 0;
      if(keys.KeyA||keys.ArrowLeft) s-=1;
      if(keys.KeyD||keys.ArrowRight) s+=1;
      if(touchX!==null) s = THREE.MathUtils.clamp((touchX-innerWidth/2)/(innerWidth/4), -1, 1);
      steer = THREE.MathUtils.lerp(steer, s, .15);
      car.position.x = THREE.MathUtils.clamp(car.position.x + steer*14*dt, -WALL_X+1.5, WALL_X-1.5);
      car.position.y = Math.sin(t*3)*.15;
      car.position.z -= speed*dt;
      travel += speed*dt;

      // recycle canyon segments
      walls.forEach(w=>{
        if(w.position.z > car.position.z + SEG_LEN) w.position.z -= SEG_COUNT*SEG_LEN;
      });

      // spawn
      if(travel > 14){ travel=0; spawnRow(); }

      // move/update obstacles
      for(let i=obstacles.length-1;i>=0;i--){
        const o = obstacles[i];
        if(o.type==='drone'){
          o.mesh.position.x += o.dir*6*dt;
          if(Math.abs(o.mesh.position.x)>WALL_X-2) o.dir*=-1;
          o.mesh.rotation.y += dt*3;
        }
        if(o.type==='laser'){
          o.mesh.position.y = o.baseY + Math.sin(t*2+o.phase)*1.2;
        }
        if(o.type==='boost') o.mesh.rotation.y += dt*4;
        // despawn behind
        if(o.mesh.position.z > car.position.z + 10){ scene.remove(o.mesh); obstacles.splice(i,1); continue; }
        // collision
        const dz = Math.abs(o.mesh.position.z - car.position.z);
        const dx = Math.abs(o.mesh.position.x - car.position.x);
        if(dz < 1.6 && dx < 1.8){
          if(o.type==='boost'){
            scene.remove(o.mesh); obstacles.splice(i,1);
            mult = Math.min(8, mult+1); multTimer = 6;
            multEl.textContent = 'x'+mult;
            floatText('x'+mult+' BOOST!', innerWidth/2, innerHeight/2, '#9dff2f');
            tone(700+mult*100,.2,'triangle',.2);
          } else {
            const dy = Math.abs(o.mesh.position.y - car.position.y);
            if(dy < (o.type==='laser'?1.1:1.6)){ crash(); }
          }
        }
      }
    }

    // camera: damped follow, speed-based FOV
    const camT = new THREE.Vector3(car.position.x*.55, 3.4, car.position.z + 8.5);
    camera.position.lerp(camT, .12);
    camera.lookAt(car.position.x*.3, 1, car.position.z - 12);
    camera.fov = THREE.MathUtils.lerp(camera.fov, 68 + speed*.35, .05);
    camera.updateProjectionMatrix();

    renderer.render(scene, camera);
  }
  animate();

  addEventListener('resize', ()=>{
    camera.aspect = innerWidth/innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(innerWidth, innerHeight);
  });
})();
</script>
</body>
</html>
A pretty decent start for the game.
Overall, it’s a pretty good model, and in my use of it, I found it to be pretty strong for large repository work. However, until we can get an actual price per token for it, I’ll refrain from rating it, but if it keeps the same pricing as its predecessor, I’ll give it an easy 8/10.