[object Object]

← back to Model Arena

roster: remove Claude Fable 5 (Anthropic account has no credit) — 7 live models, no dead option erroring every battle

341ac47e78edcf180c06c19a33fe101acebf0dc5 · 2026-07-23 06:29:10 -0700 · Steve

Files touched

Diff

commit 341ac47e78edcf180c06c19a33fe101acebf0dc5
Author: Steve <steve@designerwallcoverings.com>
Date:   Thu Jul 23 06:29:10 2026 -0700

    roster: remove Claude Fable 5 (Anthropic account has no credit) — 7 live models, no dead option erroring every battle
---
 data/artifacts/02a362bd0b06/gpt.html       | 528 +++++++++++++++++++++++++++++
 data/artifacts/02a362bd0b06/gpt.png        | Bin 0 -> 120804 bytes
 data/artifacts/02a362bd0b06/qwen25-7b.html | 119 +++++++
 data/artifacts/02a362bd0b06/qwen25-7b.png  | Bin 0 -> 4919 bytes
 data/challenges.json                       |  77 +++++
 data/costlog.jsonl                         |   1 +
 server.js                                  |   2 +-
 7 files changed, 726 insertions(+), 1 deletion(-)

diff --git a/data/artifacts/02a362bd0b06/gpt.html b/data/artifacts/02a362bd0b06/gpt.html
new file mode 100644
index 0000000..c74014c
--- /dev/null
+++ b/data/artifacts/02a362bd0b06/gpt.html
@@ -0,0 +1,528 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8" />
+<title>Dragon Realm</title>
+<style>
+  html, body {
+    margin: 0;
+    padding: 0;
+    overflow: hidden;
+    background: #050816;
+    font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
+    color: #eee;
+  }
+  canvas {
+    display: block;
+  }
+
+  /* Simple overlay UI */
+  #ui {
+    position: absolute;
+    top: 12px;
+    left: 50%;
+    transform: translateX(-50%);
+    text-align: center;
+    color: #eee;
+    text-shadow: 0 0 6px #000;
+    pointer-events: none;
+    font-size: 14px;
+  }
+  #ui h1 {
+    margin: 0 0 4px;
+    font-size: 18px;
+    letter-spacing: 0.08em;
+    text-transform: uppercase;
+  }
+  #ui p {
+    margin: 0;
+  }
+  #hint {
+    margin-top: 6px;
+    font-size: 13px;
+    opacity: 0.9;
+  }
+  #hint span {
+    padding: 3px 8px;
+    border-radius: 999px;
+    border: 1px solid rgba(255,255,255,0.3);
+    background: radial-gradient(circle at 30% 20%, rgba(255,255,255,0.12), rgba(0,0,0,0.6));
+    backdrop-filter: blur(2px);
+    pointer-events: auto;
+  }
+</style>
+</head>
+<body>
+<div id="ui">
+  <h1>Dragon Realm</h1>
+  <p>Winter skies over ancient mountains</p>
+  <div id="hint">
+    <span>Click anywhere to make the dragon breathe fire</span>
+  </div>
+</div>
+<canvas id="c"></canvas>
+<script>
+(function () {
+  const canvas = document.getElementById("c");
+  const ctx = canvas.getContext("2d");
+  let w, h, dpr;
+
+  function resize() {
+    dpr = window.devicePixelRatio || 1;
+    w = window.innerWidth;
+    h = window.innerHeight;
+    canvas.width = w * dpr;
+    canvas.height = h * dpr;
+    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
+  }
+  window.addEventListener("resize", resize);
+  resize();
+
+  // Scene parameters
+  let time = 0;
+  let last = performance.now();
+
+  // Snow particles
+  const snowCount = 400;
+  const snows = [];
+  function initSnow() {
+    snows.length = 0;
+    for (let i = 0; i < snowCount; i++) {
+      snows.push({
+        x: Math.random() * w,
+        y: Math.random() * h,
+        r: Math.random() * 2 + 0.4,
+        vy: 0.3 + Math.random() * 0.7,
+        vx: -0.2 + Math.random() * 0.4,
+        phase: Math.random() * Math.PI * 2
+      });
+    }
+  }
+  initSnow();
+
+  // Mountain layers (procedural)
+  const mountainLayers = [
+    { color: "#050618", base: 0.68, amp: 80, detail: 0.0025, offset: 0 },
+    { color: "#0a0d26", base: 0.70, amp: 100, detail: 0.003, offset: 500 },
+    { color: "#111633", base: 0.77, amp: 130, detail: 0.004, offset: 1000 }
+  ];
+
+  function noise1D(x) {
+    // Simple hash-based smooth noise
+    const i = Math.floor(x);
+    const f = x - i;
+    const u = f * f * (3 - 2 * f);
+    function hash(n) {
+      const s = Math.sin(n * 127.1) * 43758.5453123;
+      return s - Math.floor(s);
+    }
+    return (1 - u) * hash(i) + u * hash(i + 1);
+  }
+
+  // Dragon state
+  const dragon = {
+    baseY: 0.32,
+    amp: 0.05,
+    speed: 0.015,
+    xNorm: 0.2,
+    wobble: 0,
+    fire: {
+      active: false,
+      t: 0
+    }
+  };
+
+  let fireCooldown = 0;
+  canvas.addEventListener("click", () => {
+    if (!dragon.fire.active && fireCooldown <= 0) {
+      dragon.fire.active = true;
+      dragon.fire.t = 0;
+      fireCooldown = 0.5;
+    }
+  });
+
+  function update(dt) {
+    time += dt;
+    fireCooldown -= dt;
+    if (dragon.fire.active) {
+      dragon.fire.t += dt;
+      if (dragon.fire.t > 0.75) {
+        dragon.fire.active = false;
+      }
+    }
+
+    // Snow update
+    for (let p of snows) {
+      p.phase += dt * 0.7;
+      p.x += (p.vx + Math.sin(p.phase) * 0.15);
+      p.y += p.vy * (0.8 + Math.sin(time * 0.5) * 0.2);
+      if (p.y > h + 5) {
+        p.y = -5;
+        p.x = Math.random() * w;
+      }
+      if (p.x < -5) p.x = w + 5;
+      if (p.x > w + 5) p.x = -5;
+    }
+  }
+
+  function drawGradientSky() {
+    const g = ctx.createLinearGradient(0, 0, 0, h);
+    g.addColorStop(0, "#050516");
+    g.addColorStop(0.35, "#080b24");
+    g.addColorStop(0.7, "#141c3a");
+    g.addColorStop(1, "#161828");
+    ctx.fillStyle = g;
+    ctx.fillRect(0, 0, w, h);
+  }
+
+  function drawMoonAndGlow() {
+    const cx = w * 0.72;
+    const cy = h * 0.22;
+    const r = Math.min(w, h) * 0.09;
+
+    // Glow
+    let glowGrad = ctx.createRadialGradient(cx, cy, 0, cx, cy, r * 2.8);
+    glowGrad.addColorStop(0, "rgba(230,240,255,0.6)");
+    glowGrad.addColorStop(0.2, "rgba(210,230,255,0.4)");
+    glowGrad.addColorStop(0.5, "rgba(120,160,255,0.08)");
+    glowGrad.addColorStop(1, "rgba(0,0,0,0)");
+    ctx.fillStyle = glowGrad;
+    ctx.beginPath();
+    ctx.arc(cx, cy, r * 2.8, 0, Math.PI * 2);
+    ctx.fill();
+
+    // Moon body
+    let g = ctx.createRadialGradient(cx - r * 0.25, cy - r * 0.2, r * 0.1, cx, cy, r);
+    g.addColorStop(0, "#ffffff");
+    g.addColorStop(0.4, "#f5f7ff");
+    g.addColorStop(1, "#cfd4ff");
+    ctx.fillStyle = g;
+    ctx.beginPath();
+    ctx.arc(cx, cy, r, 0, Math.PI * 2);
+    ctx.fill();
+
+    // Subtle craters
+    ctx.fillStyle = "rgba(180,190,225,0.6)";
+    const craters = [
+      { x: -0.25, y: -0.18, rr: 0.16 },
+      { x: 0.2, y: 0.05, rr: 0.12 },
+      { x: -0.05, y: 0.25, rr: 0.1 }
+    ];
+    for (let c of craters) {
+      ctx.beginPath();
+      ctx.arc(cx + c.x * r, cy + c.y * r, c.rr * r, 0, Math.PI * 2);
+      ctx.fill();
+    }
+  }
+
+  function drawStars() {
+    const seed = 42;
+    function rand(i) {
+      const s = Math.sin(i * 12.9898 + seed * 78.233) * 43758.5453;
+      return s - Math.floor(s);
+    }
+    const count = 220;
+    ctx.save();
+    for (let i = 0; i < count; i++) {
+      const rx = rand(i * 1.2);
+      const ry = rand(i * 2.3);
+      const r = rand(i * 3.4) * 1.3 + 0.4;
+      const tw = (Math.sin(time * 2 + i) + 1) * 0.5;
+      const alpha = 0.25 + tw * 0.5;
+      ctx.fillStyle = `rgba(230,240,255,${alpha.toFixed(3)})`;
+      ctx.fillRect(rx * w, ry * h * 0.55, r, r);
+    }
+    ctx.restore();
+  }
+
+  function drawMountains() {
+    for (let layer of mountainLayers) {
+      ctx.fillStyle = layer.color;
+      ctx.beginPath();
+      ctx.moveTo(0, h);
+      const baseY = h * layer.base;
+      const freq = layer.detail;
+      const amp = layer.amp;
+      for (let x = 0; x <= w; x += 3) {
+        const n = noise1D((x + layer.offset) * freq);
+        const y = baseY - n * amp;
+        ctx.lineTo(x, y);
+      }
+      ctx.lineTo(w, h);
+      ctx.closePath();
+      ctx.fill();
+
+      // Subtle rim light from moon
+      const moonX = w * 0.72;
+      const moonY = h * 0.22;
+      const grad = ctx.createLinearGradient(moonX, moonY, moonX, h);
+      grad.addColorStop(0, "rgba(180,200,255,0.22)");
+      grad.addColorStop(0.3, "rgba(120,150,220,0.16)");
+      grad.addColorStop(0.8, "rgba(60,80,120,0.02)");
+      grad.addColorStop(1, "rgba(0,0,0,0)");
+      ctx.fillStyle = grad;
+      ctx.globalCompositeOperation = "screen";
+      ctx.fill();
+      ctx.globalCompositeOperation = "source-over";
+    }
+  }
+
+  function drawDragon() {
+    const scale = Math.min(w, h) * 0.0012;
+    const bob = Math.sin(time * 2) * dragon.amp * h;
+    const flap = Math.sin(time * 8);
+    const twist = Math.sin(time * 1.6) * 0.2;
+    const cx = w * dragon.xNorm + Math.cos(time * dragon.speed * 60) * 8;
+    const cy = h * dragon.baseY + bob;
+
+    ctx.save();
+    ctx.translate(cx, cy);
+    ctx.rotate(-0.1 + twist * 0.1);
+
+    // Body gradient
+    const bodyGrad = ctx.createLinearGradient(-40 * scale, 0, 120 * scale, 0);
+    bodyGrad.addColorStop(0, "#1b1d3c");
+    bodyGrad.addColorStop(0.4, "#282c5a");
+    bodyGrad.addColorStop(0.8, "#3e456d");
+    bodyGrad.addColorStop(1, "#cbc9ff");
+
+    // Body
+    ctx.lineWidth = 10 * scale;
+    ctx.lineCap = "round";
+    ctx.strokeStyle = bodyGrad;
+    ctx.beginPath();
+    ctx.moveTo(-40 * scale, 10 * scale);
+    ctx.quadraticCurveTo(10 * scale, -10 * scale, 90 * scale, 0);
+    ctx.stroke();
+
+    // Tail
+    ctx.lineWidth = 7 * scale;
+    ctx.strokeStyle = "#2b3055";
+    ctx.beginPath();
+    ctx.moveTo(70 * scale, 0);
+    ctx.quadraticCurveTo(110 * scale, 15 * scale, 140 * scale, 0);
+    ctx.stroke();
+    ctx.fillStyle = "#cfd3ff";
+    ctx.beginPath();
+    ctx.moveTo(140 * scale, 0);
+    ctx.lineTo(150 * scale, -10 * scale);
+    ctx.lineTo(150 * scale, 10 * scale);
+    ctx.closePath();
+    ctx.fill();
+
+    // Wings
+    ctx.save();
+    const wingFlap = flap * 0.6;
+    const wingSpan = 120 * scale;
+    const wingHeight = 55 * scale;
+
+    function drawWing(side) {
+      ctx.save();
+      ctx.scale(side, 1);
+      ctx.rotate(wingFlap * 0.5);
+      const wingGrad = ctx.createLinearGradient(0, -wingHeight, 0, 20 * scale);
+      wingGrad.addColorStop(0, "rgba(220,230,255,0.9)");
+      wingGrad.addColorStop(0.4, "rgba(140,150,220,0.9)");
+      wingGrad.addColorStop(1, "rgba(50,60,120,0.95)");
+
+      ctx.fillStyle = wingGrad;
+      ctx.strokeStyle = "rgba(240,250,255,0.8)";
+      ctx.lineWidth = 2 * scale;
+
+      ctx.beginPath();
+      ctx.moveTo(-5 * scale, -5 * scale);
+      ctx.quadraticCurveTo(wingSpan * 0.4, -wingHeight * 1.4, wingSpan, -5 * scale);
+      ctx.quadraticCurveTo(wingSpan * 0.4, -wingHeight * 0.7, -5 * scale, -5 * scale);
+      ctx.closePath();
+      ctx.fill();
+      ctx.stroke();
+
+      // Wing veins
+      ctx.lineWidth = 1.4 * scale;
+      ctx.strokeStyle = "rgba(230,240,255,0.8)";
+      ctx.beginPath();
+      ctx.moveTo(-5 * scale, -5 * scale);
+      ctx.lineTo(wingSpan * 0.55, -wingHeight * 1.0);
+      ctx.stroke();
+
+      ctx.beginPath();
+      ctx.moveTo(wingSpan * 0.3, -wingHeight * 1.2);
+      ctx.lineTo(wingSpan * 0.8, -wingHeight * 0.5);
+      ctx.stroke();
+
+      ctx.restore();
+    }
+
+    ctx.translate(-10 * scale, -5 * scale);
+    ctx.globalAlpha = 0.9;
+    drawWing(-1);
+    drawWing(1);
+    ctx.restore();
+
+    // Head
+    ctx.save();
+    ctx.translate(-40 * scale, 10 * scale);
+    ctx.rotate(-0.15);
+
+    // Neck
+    ctx.strokeStyle = bodyGrad;
+    ctx.lineWidth = 7 * scale;
+    ctx.beginPath();
+    ctx.moveTo(0, 0);
+    ctx.quadraticCurveTo(-25 * scale, -10 * scale, -45 * scale, -5 * scale);
+    ctx.stroke();
+
+    // Head shape
+    const headGrad = ctx.createLinearGradient(-55 * scale, -20 * scale, 5 * scale, 10 * scale);
+    headGrad.addColorStop(0, "#c9d0ff");
+    headGrad.addColorStop(0.5, "#8f97e0");
+    headGrad.addColorStop(1, "#3b3f73");
+    ctx.fillStyle = headGrad;
+    ctx.beginPath();
+    ctx.moveTo(-55 * scale, -5 * scale);
+    ctx.quadraticCurveTo(-30 * scale, -18 * scale, -5 * scale, -6 * scale);
+    ctx.quadraticCurveTo(-10 * scale, 0, -5 * scale, 6 * scale);
+    ctx.quadraticCurveTo(-30 * scale, 15 * scale, -55 * scale, 2 * scale);
+    ctx.closePath();
+    ctx.fill();
+
+    // Jaw underside highlight
+    ctx.strokeStyle = "rgba(245,250,255,0.85)";
+    ctx.lineWidth = 2 * scale;
+    ctx.beginPath();
+    ctx.moveTo(-48 * scale, 2 * scale);
+    ctx.quadraticCurveTo(-30 * scale, 10 * scale, -10 * scale, 5 * scale);
+    ctx.stroke();
+
+    // Horns
+    ctx.strokeStyle = "#f5f5ff";
+    ctx.lineWidth = 2 * scale;
+    ctx.beginPath();
+    ctx.moveTo(-40 * scale, -16 * scale);
+    ctx.lineTo(-30 * scale, -30 * scale);
+    ctx.stroke();
+    ctx.beginPath();
+    ctx.moveTo(-33 * scale, -15 * scale);
+    ctx.lineTo(-20 * scale, -25 * scale);
+    ctx.stroke();
+
+    // Eye glow
+    ctx.fillStyle = "#ffeb8a";
+    ctx.beginPath();
+    ctx.arc(-18 * scale, -4 * scale, 2.4 * scale, 0, Math.PI * 2);
+    ctx.fill();
+    ctx.fillStyle = "rgba(255,255,255,0.8)";
+    ctx.beginPath();
+    ctx.arc(-17.5 * scale, -4.5 * scale, 1 * scale, 0, Math.PI * 2);
+    ctx.fill();
+
+    // Nostrils
+    ctx.fillStyle = "rgba(40,40,80,0.8)";
+    ctx.beginPath();
+    ctx.arc(-8 * scale, -1 * scale, 0.9 * scale, 0, Math.PI * 2);
+    ctx.fill();
+
+    // Fire breath
+    if (dragon.fire.active) {
+      const ft = dragon.fire.t;
+      const intensity = Math.sin(Math.min(ft * Math.PI * 1.6, Math.PI));
+      const len = 200 * scale * (0.3 + intensity * 1.6);
+      const spread = 30 * scale * (0.4 + intensity * 0.8);
+      const flicker = (Math.sin(time * 40) * 0.2 + Math.sin(time * 23.4) * 0.1) * spread;
+
+      // Composite glow
+      ctx.save();
+      ctx.globalCompositeOperation = "lighter";
+
+      // Outer glow
+      let g = ctx.createLinearGradient(0, 0, -len, 0);
+      g.addColorStop(0, "rgba(255,220,150,0.6)");
+      g.addColorStop(0.3, "rgba(255,140,80,0.7)");
+      g.addColorStop(0.7, "rgba(255,80,40,0.5)");
+      g.addColorStop(1, "rgba(255,40,10,0.0)");
+      ctx.fillStyle = g;
+
+      ctx.beginPath();
+      ctx.moveTo(-8 * scale, -1 * scale);
+      ctx.quadraticCurveTo(-len * 0.4, -spread - flicker, -len, -4 * scale);
+      ctx.quadraticCurveTo(-len * 0.5, spread + flicker, -8 * scale, 4 * scale);
+      ctx.closePath();
+      ctx.fill();
+
+      // Inner hot core
+      let g2 = ctx.createLinearGradient(0, 0, -len * 0.8, 0);
+      g2.addColorStop(0, "rgba(255,255,255,0.98)");
+      g2.addColorStop(0.35, "rgba(255,245,150,0.95)");
+      g2.addColorStop(0.8, "rgba(255,120,40,0.0)");
+      ctx.fillStyle = g2;
+
+      ctx.beginPath();
+      ctx.moveTo(-8 * scale, -1 * scale);
+      ctx.quadraticCurveTo(-len * 0.35, -spread * 0.4 - flicker * 0.3, -len * 0.8, -1.5 * scale);
+      ctx.quadraticCurveTo(-len * 0.45, spread * 0.3 + flicker * 0.2, -8 * scale, 2 * scale);
+      ctx.closePath();
+      ctx.fill();
+
+      // Sparks
+      ctx.fillStyle = "rgba(255,240,200,0.9)";
+      for (let i = 0; i < 18; i++) {
+        const t = Math.random();
+        const x = -t * len * (0.5 + Math.random() * 0.5);
+        const y = (Math.random() - 0.5) * (spread * 0.8 + 4 * scale);
+        const r = (1 - t) * 2.2 * scale + 0.4 * scale;
+        ctx.beginPath();
+        ctx.arc(x, y, r, 0, Math.PI * 2);
+        ctx.fill();
+      }
+
+      ctx.restore();
+    }
+
+    ctx.restore(); // head
+    ctx.restore(); // dragon transform
+  }
+
+  function drawSnow() {
+    ctx.save();
+    ctx.globalCompositeOperation = "screen";
+    for (let p of snows) {
+      const twinkle = (Math.sin(time * 3 + p.phase * 3) + 1) * 0.5;
+      const alpha = 0.25 + twinkle * 0.4;
+      const size = p.r * (0.8 + twinkle * 0.6);
+      ctx.fillStyle = `rgba(230,240,255,${alpha.toFixed(3)})`;
+      ctx.beginPath();
+      ctx.arc(p.x, p.y, size, 0, Math.PI * 2);
+      ctx.fill();
+    }
+    ctx.restore();
+  }
+
+  function drawAtmosphericFog() {
+    const g = ctx.createLinearGradient(0, h * 0.4, 0, h);
+    g.addColorStop(0, "rgba(200,220,255,0.0)");
+    g.addColorStop(0.5, "rgba(160,180,220,0.12)");
+    g.addColorStop(1, "rgba(140,170,210,0.25)");
+    ctx.fillStyle = g;
+    ctx.fillRect(0, h * 0.4, w, h * 0.6);
+  }
+
+  function frame(t) {
+    const dt = Math.min((t - last) / 1000, 0.033);
+    last = t;
+    update(dt);
+
+    drawGradientSky();
+    drawStars();
+    drawMoonAndGlow();
+    drawMountains();
+    drawAtmosphericFog();
+    drawDragon();
+    drawSnow();
+
+    requestAnimationFrame(frame);
+  }
+  requestAnimationFrame(frame);
+})();
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/02a362bd0b06/gpt.png b/data/artifacts/02a362bd0b06/gpt.png
new file mode 100644
index 0000000..a4d1aab
Binary files /dev/null and b/data/artifacts/02a362bd0b06/gpt.png differ
diff --git a/data/artifacts/02a362bd0b06/qwen25-7b.html b/data/artifacts/02a362bd0b06/qwen25-7b.html
new file mode 100644
index 0000000..14c6f61
--- /dev/null
+++ b/data/artifacts/02a362bd0b06/qwen25-7b.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Dragon Realm</title>
+    <style>
+        body {
+            margin: 0;
+            overflow: hidden;
+            background-color: #000;
+        }
+        canvas {
+            display: block;
+        }
+    </style>
+</head>
+<body>
+<canvas id="dragonCanvas"></canvas>
+<script>
+    const canvas = document.getElementById('dragonCanvas');
+    canvas.width = window.innerWidth;
+    canvas.height = window.innerHeight;
+    const ctx = canvas.getContext('2d');
+
+    class Dragon {
+        constructor(x, y) {
+            this.x = x;
+            this.y = y;
+            this.scale = 1;
+            this.fire = false;
+        }
+        draw() {
+            ctx.save();
+            ctx.translate(this.x + (this.scale * 30), this.y - (this.scale * 20));
+            ctx.scale(this.scale, this.scale);
+            ctx.fillStyle = 'red';
+            ctx.beginPath();
+            ctx.moveTo(0, 0);
+            ctx.lineTo(-15, -20);
+            ctx.lineTo(-20, -40);
+            ctx.lineTo(30, -60);
+            ctx.lineTo(40, -80);
+            ctx.lineTo(70, -90);
+            ctx.lineTo(90, -110);
+            ctx.lineTo(120, -120);
+            ctx.closePath();
+            ctx.fill();
+            ctx.restore();
+        }
+        update() {
+            if (this.fire) {
+                this.breatheFire();
+            }
+        }
+        breatheFire() {
+            const fireX = this.x + 30;
+            const fireY = this.y - 15;
+            ctx.save();
+            ctx.translate(fireX, fireY);
+            ctx.scale(1, 1);
+            ctx.fillStyle = 'orange';
+            ctx.beginPath();
+            ctx.moveTo(-20, 0);
+            ctx.lineTo(20, -40);
+            ctx.lineTo(30, -50);
+            ctx.lineTo(60, -70);
+            ctx.closePath();
+            ctx.fill();
+            ctx.restore();
+        }
+    }
+
+    const dragon = new Dragon(canvas.width / 2, canvas.height * 0.8);
+
+    function draw() {
+        ctx.fillStyle = 'rgba(255, 255, 255, 0.1)';
+        ctx.fillRect(0, 0, canvas.width, canvas.height);
+        ctx.globalAlpha = 0.3;
+        ctx.beginPath();
+        for (let i = 0; i < canvas.width * 4; i++) {
+            const x = (Math.random() - 0.5) * 2 * Math.PI;
+            const y = Math.random() * canvas.height * 1.2 + 10;
+            ctx.moveTo(Math.sin(x) * y, Math.cos(x) * y);
+        }
+        ctx.strokeStyle = 'white';
+        ctx.stroke();
+        ctx.globalAlpha = 1;
+
+        dragon.draw();
+        dragon.update();
+
+        requestAnimationFrame(draw);
+    }
+
+    function animate() {
+        if (canvas.width < canvas.height / 2) {
+            dragon.x -= 3;
+        } else {
+            dragon.y += 3;
+        }
+        dragon.scale *= 0.99;
+        dragon.fire = false;
+
+        if (Math.random() > 0.95) {
+            dragon.fire = true;
+        }
+
+        draw();
+    }
+
+    canvas.addEventListener('click', () => {
+        dragon.fire = !dragon.fire;
+    });
+
+    animate();
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/02a362bd0b06/qwen25-7b.png b/data/artifacts/02a362bd0b06/qwen25-7b.png
new file mode 100644
index 0000000..d083ebd
Binary files /dev/null and b/data/artifacts/02a362bd0b06/qwen25-7b.png differ
diff --git a/data/challenges.json b/data/challenges.json
index a911fea..640ddb3 100644
--- a/data/challenges.json
+++ b/data/challenges.json
@@ -1044,5 +1044,82 @@
     "judging": false,
     "aiPick": "gemma3-12b",
     "judged_at": "2026-07-23T07:59:01.251Z"
+  },
+  {
+    "id": "02a362bd0b06",
+    "title": "Dragon Realm",
+    "prompt": "Build an animated dragon realm scene: a dragon flying over mountains with snowfall, dynamic lighting, and at least one interactive element (click to make the dragon breathe fire). Visual quality matters most.",
+    "category": "Games",
+    "created_at": "2026-07-23T13:26:11.715Z",
+    "winner": null,
+    "runs": [
+      {
+        "model": "qwen3-14b",
+        "status": "error",
+        "error": "server restarted mid-run",
+        "seconds": 0,
+        "cost": null,
+        "started_at": "2026-07-23T13:27:17.303Z",
+        "finished_at": null
+      },
+      {
+        "model": "gemma3-12b",
+        "status": "error",
+        "error": "server restarted mid-run",
+        "seconds": 0,
+        "cost": null,
+        "started_at": null,
+        "finished_at": null
+      },
+      {
+        "model": "hermes3-8b",
+        "status": "error",
+        "error": "server restarted mid-run",
+        "seconds": 0,
+        "cost": null,
+        "started_at": null,
+        "finished_at": null
+      },
+      {
+        "model": "qwen25-7b",
+        "status": "done",
+        "error": null,
+        "seconds": 19,
+        "cost": 0,
+        "started_at": "2026-07-23T13:27:22.967Z",
+        "finished_at": "2026-07-23T13:27:42.192Z",
+        "bytes": 3090,
+        "thumb": true
+      },
+      {
+        "model": "kimi",
+        "status": "error",
+        "error": "server restarted mid-run",
+        "seconds": 0,
+        "cost": null,
+        "started_at": "2026-07-23T13:27:26.287Z",
+        "finished_at": null
+      },
+      {
+        "model": "gpt",
+        "status": "done",
+        "error": null,
+        "seconds": 59,
+        "cost": 0.0716,
+        "started_at": "2026-07-23T13:27:27.604Z",
+        "finished_at": "2026-07-23T13:28:26.797Z",
+        "bytes": 14774,
+        "thumb": true
+      },
+      {
+        "model": "grok",
+        "status": "error",
+        "error": "server restarted mid-run",
+        "seconds": 0,
+        "cost": null,
+        "started_at": "2026-07-23T13:27:30.361Z",
+        "finished_at": null
+      }
+    ]
   }
 ]
\ No newline at end of file
diff --git a/data/costlog.jsonl b/data/costlog.jsonl
index 2a685d4..e95d3ca 100644
--- a/data/costlog.jsonl
+++ b/data/costlog.jsonl
@@ -13,3 +13,4 @@
 {"ts":"2026-07-23T06:26:04.181Z","provider":"openai","model":"gpt-5.1","task":"model-arena","input_tokens":558,"output_tokens":4703,"cost_usd":0.066819}
 {"ts":"2026-07-23T06:26:33.965Z","provider":"xai","model":"grok-4.5","task":"model-arena","input_tokens":650,"output_tokens":10696,"cost_usd":0.16239}
 {"ts":"2026-07-23T06:28:09.638Z","provider":"moonshot","model":"kimi-k2.5","task":"model-arena","input_tokens":459,"output_tokens":10016,"cost_usd":0.025315}
+{"ts":"2026-07-23T13:28:26.793Z","provider":"openai","model":"gpt-5.1","task":"model-arena","input_tokens":119,"output_tokens":5102,"cost_usd":0.071636}
diff --git a/server.js b/server.js
index 5fca6cf..a31f9c0 100644
--- a/server.js
+++ b/server.js
@@ -46,7 +46,7 @@ const MODELS = [
   // was Mac1 (192.168.1.133) — that Ollama host wedges (model pinned in VRAM, generations hang);
   // repointed to Mac2-local qwen2.5 for reliable liveness. Set OLLAMA_MAC1=1 to use Mac1 again.
   { id: 'qwen25-7b',  label: 'Qwen2.5 (local)', kind: 'local', host: process.env.OLLAMA_MAC1 ? 'http://192.168.1.133:11434' : 'http://localhost:11434', model: process.env.OLLAMA_MAC1 ? 'qwen2.5:7b' : 'qwen2.5:latest', estCost: 0 },
-  { id: 'claude',     label: 'Claude Fable 5', kind: 'metered', provider: 'anthropic', model: 'claude-fable-5',   envKey: 'ANTHROPIC_API_KEY', estCost: 0.15 },
+  // { id: 'claude',     label: 'Claude Fable 5', kind: 'metered', provider: 'anthropic', model: 'claude-fable-5',   envKey: 'ANTHROPIC_API_KEY', estCost: 0.15 },
   { id: 'kimi',       label: 'Kimi K2.5',      kind: 'metered', provider: 'moonshot',  model: 'kimi-k2.5',        envKey: 'MOONSHOT_API_KEY',  estCost: 0.03 },
   { id: 'gpt',        label: 'GPT-5.1',        kind: 'metered', provider: 'openai',    model: process.env.OPENAI_MODEL || 'gpt-5.1', envKey: 'OPENAI_API_KEY', estCost: 0.10 },
   { id: 'grok',       label: 'Grok 4.5',       kind: 'metered', provider: 'xai',       model: process.env.GROK_MODEL || 'grok-4.5', envKey: 'XAI_API_KEY', estCost: 0.10 },

← ffc65a2 auto-save: 2026-07-23T06:19:01 (2 files) — data/challenges.j  ·  back to Model Arena  ·  arena: Claude via Max plan (Claude Code CLI adapter, $0 subs e93e641 →