Models 44

MiMo-V2.6-Pro

by Xiaomireasoning defaultClean
Open in new window

Running live in a sandboxed frame. Click inside it before using the keyboard.

How it went

Total time
1 min 43 s
Cost
$0.010
Output tokens
12,805
Spent thinking
5,007 tokens
Speed
125.2 tok/s
Console errors
0
First token after
796 ms
First visible text after
56.1 s
Prompt tokens
567
Code size
23.8 KB
Finish reason
stop
Served by
DeepInfra
Model id
xiaomi/mimo-v2.6-pro
Reasoning sent
model default
Max output
131,072 tokens
Generated
Nov 13, 2026

What it was asked

The prompt
Build a low-poly 3D scene of a campfire in a forest clearing at night, with Three.js in a single HTML file. Load Three.js only through this import map (do not use any other URL or version): <script type="importmap">{"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js","three/addons/":"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"}}</script> Requirements: - A ground with a few low-poly rocks and logs around a campfire in the center. - At least 30 low-poly trees placed randomly around the clearing (not on the fire). - The campfire has animated flames and a warm point light that flickers and casts shadows. - Sparks rising from the fire as a simple particle system. - A dark night sky with stars and a moon, plus fog that fades the distant trees. - OrbitControls to look around, with limits so the camera stays above the ground. - The renderer fills the window and handles resizing correctly.
System prompt, sent with every prompt
You are generating a self-contained web demo. It will be rendered automatically in a sandboxed iframe and compared side by side with the output of other AI models given the exact same task.

Output rules:
- Reply with exactly ONE fenced code block containing the complete file: ```html (or ```svg when the task asks for an SVG). No text before or after the code block.
- Everything must be inline: CSS in <style>, JavaScript in <script>. No external files, images, fonts or network requests, except the CDN URLs explicitly allowed by the task.
- Do not use localStorage, sessionStorage, cookies, IndexedDB, alert(), confirm(), prompt() or window.open(): they are blocked in the sandbox and will throw.
- The page must look right in a 1280×800 viewport and adapt gracefully down to 375px wide. No horizontal scrollbar.
- Something meaningful must be visible on first paint: a screenshot is taken automatically about 3 seconds after load, without any interaction.
- Everything that makes the demo interesting must be visible within the first seconds: nothing hidden behind a high score, a later level or a long play session.
- Games must start in a self-playing demo mode (a simple AI plays) behind a "Click or press a key to start" message, so the game can be judged in action without playing.
- The iframe only receives keyboard events after the user clicks it: if the demo uses the keyboard, display a clear "Click or press a key to start" message.
- The code must run with zero errors in the console of the latest Chrome.

Code run-1.html · 916 lines

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Night Campfire — Low Poly Forest</title>
  <style>
    :root {
      color-scheme: dark;
      --glass: rgba(8, 18, 31, 0.58);
      --line: rgba(174, 211, 255, 0.18);
      --text: #e8f2ff;
      --muted: #9db4ce;
      --warm: #ffbd68;
    }

    * {
      box-sizing: border-box;
    }

    html,
    body {
      width: 100%;
      height: 100%;
      margin: 0;
      overflow: hidden;
      background: #050b16;
      font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    }

    canvas {
      display: block;
      width: 100%;
      height: 100%;
    }

    .hud {
      position: fixed;
      inset: 0;
      pointer-events: none;
      user-select: none;
    }

    .title-card {
      position: absolute;
      top: 22px;
      left: 22px;
      padding: 15px 18px 14px;
      min-width: 220px;
      border: 1px solid var(--line);
      border-radius: 15px;
      background: linear-gradient(135deg, rgba(11, 28, 48, 0.78), rgba(8, 17, 30, 0.46));
      box-shadow: 0 18px 50px rgba(0, 0, 0, 0.24);
      backdrop-filter: blur(12px);
      -webkit-backdrop-filter: blur(12px);
    }

    .eyebrow {
      display: flex;
      align-items: center;
      gap: 8px;
      color: var(--warm);
      font-size: 10px;
      font-weight: 800;
      letter-spacing: 0.18em;
      text-transform: uppercase;
    }

    .eyebrow::before {
      content: "";
      width: 7px;
      height: 7px;
      border-radius: 50%;
      background: var(--warm);
      box-shadow: 0 0 14px rgba(255, 189, 104, 0.9);
    }

    h1 {
      margin: 8px 0 4px;
      color: var(--text);
      font-size: clamp(22px, 3vw, 31px);
      font-weight: 700;
      letter-spacing: -0.04em;
    }

    .subtitle {
      margin: 0;
      color: var(--muted);
      font-size: 12px;
      line-height: 1.5;
    }

    .control-hint {
      position: absolute;
      right: 22px;
      bottom: 22px;
      padding: 11px 14px;
      border: 1px solid var(--line);
      border-radius: 12px;
      color: var(--muted);
      background: var(--glass);
      font-size: 11px;
      letter-spacing: 0.02em;
      box-shadow: 0 12px 36px rgba(0, 0, 0, 0.22);
      backdrop-filter: blur(12px);
      -webkit-backdrop-filter: blur(12px);
    }

    .control-hint strong {
      color: var(--text);
      font-weight: 650;
    }

    .loading {
      position: fixed;
      inset: 0;
      display: grid;
      place-items: center;
      background: #050b16;
      color: var(--muted);
      font-size: 12px;
      letter-spacing: 0.16em;
      text-transform: uppercase;
      transition: opacity 700ms ease, visibility 700ms ease;
    }

    .loading.hidden {
      opacity: 0;
      visibility: hidden;
    }

    @media (max-width: 560px) {
      .title-card {
        top: 14px;
        left: 14px;
        right: 14px;
        min-width: 0;
        padding: 12px 14px 11px;
      }

      h1 {
        margin-top: 6px;
        font-size: 23px;
      }

      .subtitle {
        font-size: 11px;
      }

      .control-hint {
        right: 14px;
        bottom: 14px;
        left: 14px;
        text-align: center;
        font-size: 10px;
      }
    }
  </style>

  <script type="importmap">
    {"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js","three/addons/":"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"}}
  </script>
</head>
<body>
  <div id="loading" class="loading">Entering the clearing</div>

  <div class="hud">
    <div class="title-card">
      <div class="eyebrow">Low-poly night scene</div>
      <h1>Forest Campfire</h1>
      <p class="subtitle">A quiet clearing beneath a moonlit sky.</p>
    </div>
    <div class="control-hint">
      <strong>Drag</strong> to orbit &nbsp;·&nbsp; <strong>Scroll</strong> to zoom &nbsp;·&nbsp; <strong>Right drag</strong> to pan
    </div>
  </div>

  <script type="module">
    import * as THREE from "three";
    import { OrbitControls } from "three/addons/controls/OrbitControls.js";

    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0x050b16);
    scene.fog = new THREE.FogExp2(0x081522, 0.0125);

    const camera = new THREE.PerspectiveCamera(
      55,
      window.innerWidth / window.innerHeight,
      0.1,
      180
    );
    camera.position.set(12, 7, 16);

    const renderer = new THREE.WebGLRenderer({
      antialias: true,
      powerPreference: "high-performance"
    });
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.type = THREE.PCFSoftShadowMap;
    renderer.outputColorSpace = THREE.SRGBColorSpace;
    renderer.toneMapping = THREE.ACESFilmicToneMapping;
    renderer.toneMappingExposure = 1.12;
    document.body.appendChild(renderer.domElement);

    const controls = new OrbitControls(camera, renderer.domElement);
    controls.target.set(0, 2.25, 0);
    controls.enableDamping = true;
    controls.dampingFactor = 0.055;
    controls.minDistance = 6;
    controls.maxDistance = 42;
    controls.minPolarAngle = 0.24;
    controls.maxPolarAngle = Math.PI / 2 - 0.12;
    controls.enablePan = true;
    controls.screenSpacePanning = true;

    const clock = new THREE.Clock();
    const flameMeshes = [];
    const sparkCount = 130;
    const sparkPositions = new Float32Array(sparkCount * 3);
    const sparkVelocities = new Float32Array(sparkCount * 3);
    const sparkLife = new Float32Array(sparkCount);
    const sparkMaxLife = new Float32Array(sparkCount);
    const sparkColors = new Float32Array(sparkCount * 3);

    const rand = (min, max) => min + Math.random() * (max - min);
    const pick = (items) => items[Math.floor(Math.random() * items.length)];

    function setShadow(mesh, cast = true, receive = true) {
      mesh.castShadow = cast;
      mesh.receiveShadow = receive;
      return mesh;
    }

    function makeRock(x, z, scale = 1, tint = 0) {
      const geometry = new THREE.DodecahedronGeometry(1, 0);
      const colors = [0x4b5b63, 0x56636b, 0x3e4d57, 0x657078];
      const material = new THREE.MeshStandardMaterial({
        color: colors[tint % colors.length],
        roughness: 1,
        metalness: 0,
        flatShading: true
      });

      const rock = new THREE.Mesh(geometry, material);
      rock.position.set(x, 0.52 * scale, z);
      rock.scale.set(
        scale * rand(0.8, 1.35),
        scale * rand(0.58, 1.02),
        scale * rand(0.78, 1.32)
      );
      rock.rotation.set(rand(-0.25, 0.25), rand(0, Math.PI * 2), rand(-0.22, 0.22));
      setShadow(rock);
      scene.add(rock);
      return rock;
    }

    function makeLog(x, z, length, rotationY, tilt = 0, dark = false) {
      const geometry = new THREE.CylinderGeometry(
        0.3,
        0.38,
        length,
        7,
        1
      );
      const material = new THREE.MeshStandardMaterial({
        color: dark ? 0x211b1b : 0x4b2c20,
        roughness: 1,
        metalness: 0,
        flatShading: true
      });

      const log = new THREE.Mesh(geometry, material);
      log.position.set(x, 0.42, z);
      log.rotation.z = Math.PI / 2 + tilt;
      log.rotation.y = rotationY;
      setShadow(log);
      scene.add(log);

      const capMaterial = new THREE.MeshStandardMaterial({
        color: dark ? 0x3b2920 : 0x71432b,
        roughness: 1,
        flatShading: true
      });

      const cap = new THREE.Mesh(
        new THREE.CircleGeometry(0.31, 7),
        capMaterial
      );
      cap.position.set(
        x + Math.cos(rotationY) * length * 0.5,
        0.42 + Math.sin(tilt) * length * 0.5,
        z - Math.sin(rotationY) * length * 0.5
      );
      cap.rotation.set(0, rotationY + Math.PI / 2, tilt);
      setShadow(cap);
      scene.add(cap);
    }

    // Sky dome
    const sky = new THREE.Mesh(
      new THREE.SphereGeometry(130, 32, 18),
      new THREE.MeshBasicMaterial({
        color: 0x071326,
        side: THREE.BackSide,
        fog: false,
        depthWrite: false
      })
    );
    scene.add(sky);

    // Stars
    const starCount = 520;
    const starPositions = new Float32Array(starCount * 3);

    for (let i = 0; i < starCount; i++) {
      const radius = rand(55, 115);
      const angle = rand(0, Math.PI * 2);
      const height = rand(18, 92);
      const horizontalRadius = Math.sqrt(Math.max(1, radius * radius - height * height));

      starPositions[i * 3] = Math.cos(angle) * horizontalRadius;
      starPositions[i * 3 + 1] = height;
      starPositions[i * 3 + 2] = Math.sin(angle) * horizontalRadius;
    }

    const starGeometry = new THREE.BufferGeometry();
    starGeometry.setAttribute(
      "position",
      new THREE.BufferAttribute(starPositions, 3)
    );

    const stars = new THREE.Points(
      starGeometry,
      new THREE.PointsMaterial({
        color: 0xd8e7ff,
        size: 1.15,
        sizeAttenuation: false,
        transparent: true,
        opacity: 0.82,
        depthWrite: false,
        fog: false
      })
    );
    stars.frustumCulled = false;
    scene.add(stars);

    // Moon and halo
    const moonGroup = new THREE.Group();
    moonGroup.position.set(-18, 27, -25);

    const moon = new THREE.Mesh(
      new THREE.SphereGeometry(3.8, 16, 8),
      new THREE.MeshBasicMaterial({
        color: 0xdbe8f5,
        fog: false
      })
    );
    moonGroup.add(moon);

    const halo = new THREE.Mesh(
      new THREE.SphereGeometry(5.4, 16, 8),
      new THREE.MeshBasicMaterial({
        color: 0x8bb9e5,
        transparent: true,
        opacity: 0.075,
        blending: THREE.AdditiveBlending,
        depthWrite: false,
        side: THREE.BackSide,
        fog: false
      })
    );
    moonGroup.add(halo);

    const craterMaterial = new THREE.MeshBasicMaterial({
      color: 0xb9c9d9,
      transparent: true,
      opacity: 0.52,
      fog: false
    });

    [
      [-1.25, 0.9, 3.25, 0.62],
      [1.15, -0.45, 3.35, 0.46],
      [0.15, 1.65, 3.3, 0.34]
    ].forEach(([x, y, z, size]) => {
      const crater = new THREE.Mesh(
        new THREE.CircleGeometry(size, 8),
        craterMaterial
      );
      crater.position.set(x, y, z);
      moonGroup.add(crater);
    });

    scene.add(moonGroup);

    // Ground
    const groundGeometry = new THREE.PlaneGeometry(130, 130, 32, 32);
    const groundPositions = groundGeometry.attributes.position;

    for (let i = 0; i < groundPositions.count; i++) {
      const x = groundPositions.getX(i);
      const y = groundPositions.getY(i);
      const distance = Math.sqrt(x * x + y * y);
      const variation =
        Math.sin(x * 0.17) * 0.12 +
        Math.cos(y * 0.14) * 0.1 +
        Math.sin((x + y) * 0.08) * 0.16;

      groundPositions.setZ(i, variation * Math.min(1, distance / 9));
    }

    groundGeometry.computeVertexNormals();

    const ground = new THREE.Mesh(
      groundGeometry,
      new THREE.MeshStandardMaterial({
        color: 0x172b22,
        roughness: 1,
        metalness: 0,
        flatShading: true
      })
    );
    ground.rotation.x = -Math.PI / 2;
    ground.receiveShadow = true;
    scene.add(ground);

    const clearing = new THREE.Mesh(
      new THREE.CircleGeometry(16, 48),
      new THREE.MeshStandardMaterial({
        color: 0x20392a,
        roughness: 1,
        metalness: 0,
        flatShading: true
      })
    );
    clearing.rotation.x = -Math.PI / 2;
    clearing.position.y = 0.018;
    clearing.receiveShadow = true;
    scene.add(clearing);

    // Fire pit stones and firewood
    for (let i = 0; i < 13; i++) {
      const angle = (i / 13) * Math.PI * 2 + rand(-0.12, 0.12);
      const radius = rand(1.75, 2.05);
      makeRock(
        Math.cos(angle) * radius,
        Math.sin(angle) * radius,
        rand(0.32, 0.52),
        i
      );
    }

    makeLog(-0.35, 0.15, 3.0, 0.22, -0.05, true);
    makeLog(0.25, -0.32, 2.65, 1.78, 0.08, true);
    makeLog(-0.15, -0.05, 2.4, 0.82, -0.18, true);

    // Logs and rocks scattered around the clearing
    makeLog(-4.6, 1.5, 3.2, 0.22, 0.02);
    makeLog(3.8, -3.4, 3.8, 1.1, -0.04);
    makeLog(4.6, 2.6, 2.7, -0.55, 0.08);
    makeLog(-3.5, -4.1, 2.4, 0.85, -0.1);
    makeLog(-6.1, -1.4, 2.2, -0.4, 0.12);

    for (let i = 0; i < 17; i++) {
      const angle = rand(0, Math.PI * 2);
      const radius = rand(3.3, 8.2);
      makeRock(
        Math.cos(angle) * radius,
        Math.sin(angle) * radius,
        rand(0.38, 0.9),
        i + 4
      );
    }

    // Trees around the clearing
    const trunkColors = [0x3c2922, 0x493026, 0x2e221e];
    const foliageColors = [0x1d4a3c, 0x245642, 0x2d6249, 0x183e35, 0x32634a];

    function createTree(x, z, scale, index) {
      const group = new THREE.Group();
      group.position.set(x, 0, z);
      group.rotation.y = rand(0, Math.PI * 2);

      const trunkHeight = rand(2.25, 3.45) * scale;
      const trunk = new THREE.Mesh(
        new THREE.CylinderGeometry(
          0.22 * scale,
          0.36 * scale,
          trunkHeight,
          6,
          1
        ),
        new THREE.MeshStandardMaterial({
          color: pick(trunkColors),
          roughness: 1,
          metalness: 0,
          flatShading: true
        })
      );
      trunk.position.y = trunkHeight * 0.5;
      setShadow(trunk);
      group.add(trunk);

      const foliageColor = pick(foliageColors);
      const foliageMaterial = new THREE.MeshStandardMaterial({
        color: foliageColor,
        roughness: 1,
        metalness: 0,
        flatShading: true
      });

      const layers = [
        { radius: 1.62, height: 2.25, y: trunkHeight * 0.54 },
        { radius: 1.28, height: 1.95, y: trunkHeight * 0.93 },
        { radius: 0.91, height: 1.58, y: trunkHeight * 1.31 }
      ];

      layers.forEach((layer, layerIndex) => {
        const cone = new THREE.Mesh(
          new THREE.ConeGeometry(
            layer.radius * scale,
            layer.height * scale,
            7,
            1
          ),
          layerIndex === 2
            ? new THREE.MeshStandardMaterial({
                color: foliageColor,
                roughness: 1,
                flatShading: true
              })
            : foliageMaterial
        );

        cone.position.y = layer.y;
        cone.rotation.y = rand(-0.2, 0.2);
        setShadow(cone);
        group.add(cone);
      });

      group.userData.sway = rand(0.6, 1.4);
      group.userData.phase = rand(0, Math.PI * 2);
      scene.add(group);
      return group;
    }

    const trees = [];
    for (let i = 0; i < 46; i++) {
      const angle = rand(0, Math.PI * 2);
      const radius = 10 + Math.pow(Math.random(), 0.72) * 34;
      const x = Math.cos(angle) * radius + rand(-2.4, 2.4);
      const z = Math.sin(angle) * radius + rand(-2.4, 2.4);
      trees.push(createTree(x, z, rand(0.82, 1.32), i));
    }

    // Low-poly grass tufts around the clearing edge
    const grassMaterial = new THREE.MeshStandardMaterial({
      color: 0x315d43,
      roughness: 1,
      flatShading: true
    });

    for (let i = 0; i < 34; i++) {
      const angle = rand(0, Math.PI * 2);
      const radius = rand(6.5, 13);
      const tuft = new THREE.Group();
      tuft.position.set(Math.cos(angle) * radius, 0, Math.sin(angle) * radius);

      for (let j = 0; j < 3; j++) {
        const blade = new THREE.Mesh(
          new THREE.ConeGeometry(0.11, rand(0.5, 1.05), 4, 1),
          grassMaterial
        );
        blade.position.set(rand(-0.18, 0.18), 0.3, rand(-0.18, 0.18));
        blade.rotation.z = rand(-0.35, 0.35);
        blade.rotation.x = rand(-0.35, 0.35);
        setShadow(blade);
        tuft.add(blade);
      }

      scene.add(tuft);
    }

    // Fire flames
    const flameMaterials = [
      new THREE.MeshBasicMaterial({
        color: 0xff6a18,
        transparent: true,
        opacity: 0.5,
        blending: THREE.AdditiveBlending,
        depthWrite: false,
        side: THREE.DoubleSide
      }),
      new THREE.MeshBasicMaterial({
        color: 0xff9e21,
        transparent: true,
        opacity: 0.72,
        blending: THREE.AdditiveBlending,
        depthWrite: false,
        side: THREE.DoubleSide
      }),
      new THREE.MeshBasicMaterial({
        color: 0xffe27a,
        transparent: true,
        opacity: 0.82,
        blending: THREE.AdditiveBlending,
        depthWrite: false,
        side: THREE.DoubleSide
      })
    ];

    function addFlame({
      radius,
      height,
      y,
      material,
      x = 0,
      z = 0,
      phase,
      speed,
      sway,
      scale = 1
    }) {
      const flame = new THREE.Mesh(
        new THREE.ConeGeometry(radius, height, 8, 3),
        material
      );

      flame.position.set(x, y, z);
      flame.scale.setScalar(scale);
      flame.rotation.y = phase;
      flame.userData = {
        baseY: y,
        baseScale: scale,
        phase,
        speed,
        sway
      };

      flameMeshes.push(flame);
      scene.add(flame);
    }

    addFlame({
      radius: 1.38,
      height: 3.15,
      y: 1.78,
      material: flameMaterials[0],
      phase: 0.2,
      speed: 3.4,
      sway: 0.12
    });

    addFlame({
      radius: 1.05,
      height: 2.65,
      y: 1.52,
      x: -0.18,
      z: 0.1,
      material: flameMaterials[1],
      phase: 1.4,
      speed: 4.1,
      sway: 0.16
    });

    addFlame({
      radius: 0.72,
      height: 2.05,
      y: 1.25,
      x: 0.16,
      z: -0.12,
      material: flameMaterials[2],
      phase: 2.8,
      speed: 5.2,
      sway: 0.19
    });

    addFlame({
      radius: 0.38,
      height: 1.15,
      y: 2.4,
      x: -0.42,
      z: 0.05,
      material: flameMaterials[1],
      phase: 0.8,
      speed: 6.2,
      sway: 0.22
    });

    addFlame({
      radius: 0.32,
      height: 1.05,
      y: 2.18,
      x: 0.42,
      z: -0.18,
      material: flameMaterials[2],
      phase: 3.7,
      speed: 5.6,
      sway: 0.25
    });

    const fireCore = new THREE.Mesh(
      new THREE.IcosahedronGeometry(0.72, 1),
      new THREE.MeshBasicMaterial({
        color: 0xffc24d,
        transparent: true,
        opacity: 0.34,
        blending: THREE.AdditiveBlending,
        depthWrite: false
      })
    );
    fireCore.position.y = 0.93;
    scene.add(fireCore);

    // Fire lighting
    const fireLight = new THREE.PointLight(0xff762d, 3.2, 24, 1.8);
    fireLight.position.set(0, 2.1, 0);
    fireLight.castShadow = true;
    fireLight.shadow.mapSize.set(1024, 1024);
    fireLight.shadow.camera.near = 0.5;
    fireLight.shadow.camera.far = 32;
    fireLight.shadow.bias = -0.0025;
    scene.add(fireLight);

    const emberLight = new THREE.PointLight(0xffad48, 0.65, 9, 2);
    emberLight.position.set(0, 1.15, 0);
    scene.add(emberLight);

    const moonLight = new THREE.DirectionalLight(0x7ca7d6, 0.48);
    moonLight.position.set(-28, 42, -34);
    moonLight.target.position.set(0, 0, 0);
    scene.add(moonLight, moonLight.target);

    const hemisphere = new THREE.HemisphereLight(
      0x284a70,
      0x0b1712,
      0.46
    );
    scene.add(hemisphere);

    const ambient = new THREE.AmbientLight(0x10233a, 0.2);
    scene.add(ambient);

    // Rising sparks
    const sparkGeometry = new THREE.BufferGeometry();
    sparkGeometry.setAttribute(
      "position",
      new THREE.BufferAttribute(sparkPositions, 3)
    );
    sparkGeometry.setAttribute(
      "color",
      new THREE.BufferAttribute(sparkColors, 3)
    );

    const sparkMaterial = new THREE.PointsMaterial({
      size: 0.14,
      sizeAttenuation: true,
      transparent: true,
      opacity: 0.95,
      vertexColors: true,
      blending: THREE.AdditiveBlending,
      depthWrite: false
    });

    const sparks = new THREE.Points(sparkGeometry, sparkMaterial);
    sparks.frustumCulled = false;
    scene.add(sparks);

    function resetSpark(i, initial = false) {
      const angle = Math.random() * Math.PI * 2;
      const radius = Math.random() * 1.2;

      sparkPositions[i * 3] = Math.cos(angle) * radius;
      sparkPositions[i * 3 + 1] = initial ? rand(0.75, 3.8) : rand(0.8, 1.6);
      sparkPositions[i * 3 + 2] = Math.sin(angle) * radius;

      sparkVelocities[i * 3] = rand(-0.25, 0.25);
      sparkVelocities[i * 3 + 1] = rand(1.35, 3.1);
      sparkVelocities[i * 3 + 2] = rand(-0.25, 0.25);

      sparkLife[i] = rand(0.65, 2.25);
      sparkMaxLife[i] = sparkLife[i];

      const warm = Math.random();
      sparkColors[i * 3] = 1;
      sparkColors[i * 3 + 1] = 0.3 + warm * 0.55;
      sparkColors[i * 3 + 2] = 0.04 + warm * 0.2;
    }

    for (let i = 0; i < sparkCount; i++) {
      resetSpark(i, true);
    }

    function updateSparks(dt, time) {
      for (let i = 0; i < sparkCount; i++) {
        const index = i * 3;

        if (sparkLife[i] <= 0) {
          resetSpark(i);
          continue;
        }

        sparkLife[i] -= dt;

        const drift = Math.sin(time * 1.7 + i * 0.37) * 0.17;
        sparkVelocities[index] += drift * dt;
        sparkVelocities[index + 1] += 0.3 * dt;
        sparkVelocities[index + 2] += Math.cos(time * 1.3 + i) * 0.12 * dt;

        sparkPositions[index] += sparkVelocities[index] * dt;
        sparkPositions[index + 1] += sparkVelocities[index + 1] * dt;
        sparkPositions[index + 2] += sparkVelocities[index + 2] * dt;

        const fade = Math.max(0, sparkLife[i] / sparkMaxLife[i]);
        sparkColors[index + 1] *= 0.999;
        sparkColors[index + 2] *= 0.999;
        sparkColors[index] = Math.min(1, 0.62 + fade * 0.38);
      }

      sparkGeometry.attributes.position.needsUpdate = true;
      sparkGeometry.attributes.color.needsUpdate = true;
    }

    function resize() {
      const width = window.innerWidth;
      const height = window.innerHeight;

      camera.aspect = width / height;
      camera.updateProjectionMatrix();
      renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
      renderer.setSize(width, height, false);
    }

    window.addEventListener("resize", resize);

    function animate() {
      requestAnimationFrame(animate);

      const dt = Math.min(clock.getDelta(), 0.05);
      const time = performance.now() * 0.001;

      controls.update();

      flameMeshes.forEach((flame, index) => {
        const data = flame.userData;
        const pulse =
          Math.sin(time * data.speed + data.phase) * 0.08 +
          Math.sin(time * (data.speed * 1.71) + data.phase * 1.4) * 0.045;

        flame.scale.set(
          data.baseScale * (1 + pulse),
          data.baseScale * (1 - pulse * 0.7),
          data.baseScale * (1 + pulse)
        );

        flame.position.y =
          data.baseY +
          Math.sin(time * data.speed * 0.72 + data.phase) * 0.08;

        flame.position.x =
          (index % 2 === 0 ? 1 : -1) *
          Math.sin(time * data.speed * 0.43 + data.phase) *
          data.sway;

        flame.position.z =
          Math.cos(time * data.speed * 0.52 + data.phase) *
          data.sway *
          0.65;

        flame.rotation.y += dt * (0.12 + index * 0.012);
        flame.rotation.z =
          Math.sin(time * data.speed * 0.31 + data.phase) * 0.11;
      });

      fireCore.rotation.y += dt * 0.35;
      fireCore.rotation.x = Math.sin(time * 1.6) * 0.12;
      fireCore.scale.setScalar(
        1 + Math.sin(time * 5.1) * 0.07 + Math.sin(time * 8.2) * 0.035
      );

      const flicker =
        2.72 +
        Math.sin(time * 11.5) * 0.22 +
        Math.sin(time * 19.7) * 0.13 +
        Math.sin(time * 31.2) * 0.07;

      fireLight.intensity = flicker;
      fireLight.position.x = Math.sin(time * 4.8) * 0.12;
      fireLight.position.z = Math.cos(time * 3.7) * 0.1;
      fireLight.position.y = 2.1 + Math.sin(time * 6.4) * 0.12;

      emberLight.intensity = 0.58 + Math.sin(time * 8.4) * 0.12;

      trees.forEach((tree) => {
        tree.rotation.z =
          Math.sin(time * 0.42 + tree.userData.phase) *
          0.006 *
          tree.userData.sway;
      });

      updateSparks(dt, time);

      renderer.render(scene, camera);
    }

    resize();
    animate();

    requestAnimationFrame(() => {
      document.getElementById("loading").classList.add("hidden");
    });
  </script>
</body>
</html>
Reasoning trace (5,007 tokens)
We need output only HTML code. Need build robust scene. Need importmap exact. Three 0.170. Use OrbitControls. Need self-contained. Need visible first paint. Need maybe UI overlay but minimal. Requirements: ground, rocks, logs, 30 trees, flames animated, warm point light flicker shadows, sparks particles, night sky stars moon fog, OrbitControls limits, resize.

Need consider CDN import map and module script. All inline. We can create shapes with BufferGeometry low-poly. Use MeshStandardMaterial flatShading.

Sky: scene background dark, stars as Points with positions on dome; moon sphere with emissive material + point/ambient? Fog exponential. Ground large circle/plane with vertices noise, maybe CircleGeometry rotated. Fire center with logs, stones, flame meshes (cones/icosahedrons) animated scale/rotation, point light.

Camera initial position maybe (10, 8, 12) looking at (0,1,0). Orbit controls maxPolarAngle Math.PI/2 - 0.08, minDistance 5 maxDistance 38, target y 1.5. Disable pan? fine.

Shadows: renderer shadowMap enabled, directional moonlight maybe low intensity, fire point light castShadow. PointLight shadows expensive but okay. Use PCFSoftShadowMap, shadow map 1024.

Fog: scene.fog = new THREE.FogExp2(0x07101c, 0.018) but stars should not fog? Points material fog false maybe stars in scene with fog false. Moon fog false. Distant trees fade.

Ground with a circular clearing maybe large plane 100. Use CircleGeometry(60, 64) rotated. Could be flat with slight vertex noise via geometry position y. Make low-poly color dark green.

Trees: 40 around clearing using deterministic random. Need not on fire: radius from 8 to 42. Tree group: trunk cylinder radius 0.28-0.45 height 2.2-3.4; foliage cones stacked, colors greens. Low-poly geometry 6-8 radial segments, heightSegments 1. Use MeshStandard flatShading. Random scale/rotation. Place y. Maybe use cone geometry with 7 segments.

Rocks: dodecahedron geometry with random scaling/rotation; 12 around fire radius 2-5. Logs: cylinders lying around fire, 5 with rotation.

Fire: ring of stones maybe rocks around. Logs at fire center crossed. Flames: multiple cone / icosahedron meshes. Use transparent materials with colors orange/yellow, emissive, depthWrite false, additive? For visible layered. Animate via sin. Add inner glowing core sphere. Maybe make flame using custom lathe? Low-poly cones enough. Could use ConeGeometry with radius, height, 7 segments, translated? Put base at y 0.35. Rotated varying.

Sparks: BufferGeometry positions, velocities, life, color attribute? PointsMaterial size .12, vertexColors, transparent, additive, depthWrite false. Update each frame. Need initial visible. 90 sparks, y range. Use Float32Array positions and colors. To update color maybe no need. Points with orange.

Sky stars: Points with sphere-ish positions radius 120, only upper hemisphere. PointsMaterial size 0.7 sizeAttenuation false? size 1.2, color white, transparent, opacity 0.85, fog:false. Moon: sphere radius 4 at (35,45,-55) maybe visible in camera? Camera at (11,7,13) looking center; moon at (28,36,-42) might be behind? Need it visible. Sky dome perhaps moon positioned far with scene coordinates. Camera default looking at origin from positive z. Moon at (-30,30,-45) is behind origin along -z, likely visible when looking at center? Direction from camera to moon is (-41,23,-58) vs to origin (-11,-7,-13). Camera view cone maybe moon could be out. But user can orbit. Better moon at (22,32,-30) maybe visible upper right? Camera at (12,8,16), looking toward origin; vector to moon (10,24,-46), angle? Camera forward (-0.55,-0.36,-0.75); moon dir normalized (0.2,0.46,-0.87), angle maybe 50 deg, probably out of 45 FOV. Put moon at (-10, 32, -18)? Vector from camera (-22,24,-34) direction (-0.45,0.49,-0.7), dot with forward ~0.2+... maybe 0.76 -> visible. Actually camera default pos (12,8,16) target (0,2,0). moon at (-10,32,-18) likely in frame upper left. But stars dome.

Could add a large sky dome with MeshBasicMaterial dark blue, side BackSide, fog false? Fog applies to basic? material fog true default. Set fog false. But scene background enough. Night sky with gradient? Use background Color and stars. Maybe add "sky dome" SphereGeometry 120, material color #050b17, side BackSide, fog:false. Since camera inside. Fog on scene affects meshes; basic material fog false. Good.

Moon emissive sphere with a couple of craters (small dark circles) maybe low-poly. Use SphereGeometry 4, 20, 12, MeshStandard? MeshBasic with color pale, plus glow via sprite? No external. Add point light moon directional? DirectionalLight cool blue low intensity, no shadow. Ambient hemisphere.

Ground maybe use MeshStandard.

Need maybe control hints overlay, small badge "NIGHT CAMPFIRE • DRAG TO ORBIT". No extra requirement. Make scene visually rich. Need no network except three import map. All code inline. Ensure no errors in latest Chrome.

Need think about import map module script. Use `<script type="importmap">... exact`. Then `<script type="module"> import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js';`.

Potential issue `THREE.Color` with `MeshStandardMaterial({ color, flatShading: true })`. Fine.

Need perhaps terrain low-poly with vertex displacement. CircleGeometry vertex positions; after rotate -PI/2, if modifying y before rotate? CircleGeometry positions x,y plane; set z noise then rotate -> y = -z. Simpler create PlaneGeometry(120,120,32,32), positions z noise, rotate x -PI/2. Use `computeVertexNormals()`. But plane 32x32 not low poly? okay. Add clearing ring maybe subtle lighter disc? Ground with `MeshStandardMaterial color 0x182b20 roughness 1`. To create clearing, maybe `CircleGeometry(16,32)` with slightly green, y=0.02.

Fog: FogExp2 density 0.014. Distant trees fade at 50.

Renderer: outputColorSpace = SRGBColorSpace, toneMapping = ACESFilmicToneMapping, toneMappingExposure = 1.1. shadows.

Resize: on window resize set camera aspect, renderer.setSize, setPixelRatio(Math.min(devicePixelRatio, 2)). Need renderer fills window.

Fire light flicker: intensity = 2.2 + sin(time*13)*0.35 + sin(time*23)*0.2 + random? Use smooth noise. `pointLight.position.set(0, 2.2, 0)`.

Fire flame animation: each mesh with `userData.baseY`, `baseScale`, `phase`, `speed`, `sway`. Position x/z slight. `mesh.rotation.z = Math.sin(t*speed+phase)*0.15`, scale x etc. Use `mesh.position.y = baseY + sin...`. Need use `mesh.scale.set(1 + ...)`.

Ember glow: PointLight? One fire point light. Maybe add small orange `PointLight` near fire low intensity no shadows.

Sparks: `const sparkCount=120`, arrays positions velocities life maxLife. On reset random radial radius 0.1-1.1, y .6-1.6, upward velocity 1.2-3, x/z drift. update with dt clamped. `life -= dt; if <=0 reset`. positions update. Points material size 0.13, sizeAttenuation true. `colors` set orange. Points may be visible.

Stars: generate 500 using spherical coordinate, keep y positive. `const r = 90; y = Math.random()*70 + 5;` place all around; but dome radius 120. Could generate `phi` etc with y = 20 + random*80 and horizontal radius sqrt(r^2-y^2). Need stars above horizon. Simple loop random x/z within radius 110 and y 18-100, not close. Camera within. Use `PointsMaterial({size:0.9, sizeAttenuation:false, transparent:true, opacity:.85, color:0xd8e7ff, fog:false, depthWrite:false})`. `frustumCulled=false`.

Moon craters: `SphereGeometry(3.8, 16, 8)` and small `CircleGeometry`? A `Mesh` sphere with `MeshStandardMaterial({color:0xc7d5e6, emissive:0x7189a8, emissiveIntensity:.4, flatShading:true})`. Add point light? A `DirectionalLight` from moon. Add glow using `Sprite` needs texture. Can use transparent sphere larger with MeshBasicMaterial transparent opacity .08, side BackSide, maybe atmospheric halo. `SphereGeometry(5.2,16,8)` with material transparent opacity .06, blending AdditiveBlending, depthWrite false. Fine.

Trees at 40: use deterministic `rand()` function to avoid layout changes? Fine. Ensure not on fire by radial. `for i=0; i<42; i++` angle, radius = 9 + Math.pow(Math.random(),.65)*36; plus jitter. But clearing is radius 8. Fine. Trees can overlap. Add `tree.castShadow=true`, `receiveShadow=true`. For cones castShadow.

Need maybe forest floor with small grass/ferns? Not necessary but visual richness. Could add low-poly grass tufts around clearing? Optional. Keep enough.

Camera initial: `camera.position.set(13,8,15)`, `controls.target.set(0,1.8,0)`. With maxPolarAngle Math.PI/2 - .12 (camera above ground), minPolarAngle .25. `controls.enableDamping = true`, dampingFactor .05, `controls.minDistance=6, maxDistance=42`, `controls.maxPolarAngle = Math.PI/2 - 0.12`. `controls.target` y 1.8.

Could make scene animate even if OrbitControls. `requestAnimationFrame`.

Need perhaps initial paint before JS? Since module loads, but can include loading overlay in HTML with CSS and hide after scene initialized. Requirement meaningful visible on first paint; screenshot 3 sec, likely loaded. Add overlay `#loading` with text "Preparing the clearing..." but if script load slow maybe visible. But screenshot after 3s, fine. However if module fails, no. We can include a `#ui` panel visible with title etc. Need not use alerts.

Need maybe no window `addEventListener` errors. Good.

Potential issue dynamic geometry normals with `flatShading` and `computeVertexNormals` works.

Need use `MathUtils.lerp`. Fine.

Need not use external images.

Need ensure "trees placed randomly around clearing (not on the fire)" visibly 30. Use 46.

Let's write complete HTML. Need code only fenced. Consider HTML style: body margin 0 overflow hidden background. Canvas. UI top-left with subtle glass, bottom hint. `pointer-events:none` except maybe. Maybe no overlay obstructing. Use `.hud`. Make top left title. Bottom center control hints. In 375px width, hud small.

Use CSS `font-family: Inter, ui-sans-serif, system-ui` no external fonts. Good.

Let's craft.

Detailed JS:

```
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x050b16);
scene.fog = new THREE.FogExp2(0x081422, 0.0125);
```
Sky dome with `MeshBasicMaterial({color:0x071326, side:THREE.BackSide, fog:false, depthWrite:false})`; sphere radius 130. If background color and dome, fine.

Ground plane 130. Add clearing disc with `CircleGeometry(16, 48)` rotated -PI/2 at y=.015, material 0x1c3325. Maybe it doesn't show as clearing due to ground green.

Rocks: `new THREE.DodecahedronGeometry(1,0)` scale x/y/z. Position around fire; rock y = scale.y*.65. Use `rock.rotation.set`. Use `MeshStandardMaterial` colors variations.

Logs around fire: `CylinderGeometry(0.32,0.38,3.4,7)` rotated z PI/2 (axis along x), position y .42, rotation y. Add ends? Cylinder with flat. 4 logs at different angles. Firewood in center: 3 logs smaller crossed at y .45. Add blackened char? dark logs.

Fire stones ring: maybe 10 rocks radius 1.75 with random scales .4.

Flame geometry:
- outer `ConeGeometry(1.35, 3.1, 8, 3)` position y=1.75. But cone tip at top; base at y=0.2? Cone default centered, height 3.1 -> bottom 0.2. Good.
- mid cone height 2.4 radius .9 pos y 1.4, color 0xff7a1c.
- inner cone height 1.8 radius .55 pos y 1.1, color 0xffd257.
- top flame lobes: `IcosahedronGeometry`? Maybe 3 smaller cones with tilt.
Use `flatShading`, `transparent` true opacity .88, `emissive`, `emissiveIntensity` 1.2, `blending: AdditiveBlending`? With additive, colors bright and layering; but need no weird black. Standard material emissive. `depthWrite:false`. Better `MeshBasicMaterial({ color, transparent:true, opacity:.85, blending: THREE.AdditiveBlending, depthWrite:false, side: THREE.DoubleSide })`; no lighting required and vibrant. Add outer slightly transparent orange. `flameMeshes.push`.

Inner glowing core `IcosahedronGeometry(0.75, 1)` at y=0.9 with MeshBasicMaterial color 0xffb229 opacity .35 additive.

Fire light `PointLight(0xff7a28, 3.2, 22, 1.8)`. `castShadow=true`, `shadow.mapSize.set(1024,1024)`, `shadow.bias=-0.002`, `shadow.camera.near=.5`, `far=30`. PointLight shadow camera fov maybe default 90.

Lighting: `HemisphereLight(0x24456c, 0x08120c, 0.48)`, `DirectionalLight(0x86a8d2, .55)` position (-25,35,18) maybe moon. `DirectionalLight` shadow maybe no need. Set `castShadow=false` to reduce.

Ambient? hemisphere enough.

Maybe `scene.add(new THREE.AmbientLight(0x0c1828, .25))`. Fine.

Trees: build geometry once per tree? 46*3 geometries okay. `makeTree(x,z,scale,tint)`:
```
const group = new THREE.Group();
const trunkH=2.2+Math.random()*1.8;
const trunk = new Mesh(new CylinderGeometry(.22*s,.32*s,trunkH,6), trunkMat);
trunk.position.y=trunkH/2;
...
for (let j=0;j<3;j++) {
 const cone = new Mesh(new ConeGeometry((1.55 - j*.32)*s, (2.2 - j*.18)*s, 7, 1), foliageMat)
 cone.position.y = trunkH*.72 + j*(1.05*s);
}
```
Need total foliage not too tall. Use 3 layers with positions. Base cone at trunkH*0.55? Example trunkH=2.8, layer y=1.55, 2.4, 3.25. Good. Cone height 2.2,1.9,1.6, radius 1.6,1.25,.9. Overall top 4.0. Fine.

Scale variation `s=.85+Math.random()*.55`. Place base y=0.

Rocks 18 maybe.

Grass: maybe add 20 tiny cones in clearing edges in dark green; could add visual detail. Not needed.

Stars and moon: place moon as `moonGroup.position.set(-26,36,-32)`, maybe. Need visibility from default. Let's compute camera default view. Camera position (13,8.5,15), target (0,2,0). forward = normalize(-13,-6.5,-15) = (-.63,-.31,-.72). Moon center vector (-39,27.5,-47), normalized (-.58,.41,-.70). dot = .365 -.127 + .504 = .742; angle 42deg. FOV 55 vertical, horizontal maybe 80; likely near upper edge. Set moon at (-16, 28, -22): vector (-29,19.5,-37) normalized (-.55,.37,-.70), dot .35-.115+.504=.74 still. Because camera looks down, moon above requires angle. Move moon further direction aligned with camera forward but above: from camera, direction forward + vertical. E.g position camera + 70 * normalized(forward + (0,0.45,0)) = (13,8,15)+70*(-.61,.13,-.70) = (-30,17,-34) not high. Need moon appear upper area: at pos (-22,30,-28) vector (-35,22,-43), dot ~.7. It's okay within ~42°, vertical FOV 55 means 27.5 half. Actually camera fov 55 vertical, horizontal ~80 for aspect 1.6 => 40 half. 42 slightly out. Set moon at (-18, 26, -24): vector (-31,18,-39), normalized (-.58,.34,-.73), dot .365-.105+.526=.786 -> angle 38.2, still at edge. Maybe default camera position less extreme and target higher. Set camera at (12,7,16), target (0,3,0). forward (-12,-4,-16) normalized(-.58,-.19,-.78). Moon at (-18,26,-24): vector (-30,19,-40), normalized (-.56,.35,-.75); dot .325-.067+.585=.843 angle 32.5, visible near top. Good. Target y=2.5 maybe. OrbitControls target (0,2.5,0). Camera above.

Moon `MeshBasicMaterial` so no lighting. Halo.

Sky stars could use a `Points` geometry. Fine.

Need maybe directional moon light position from moon. `moonLight.position.copy(moonGroup.position)` but directional light direction from position to target (0,0,0) so set `moonLight.position.set(-30,45,-35)`. Great.

Animation:
```
const clock = new THREE.Clock();
function animate(){
 const dt = Math.min(clock.getDelta(), .05);
 const t = clock.elapsedTime;
 controls.update();
 flameMeshes.forEach(...)
 fireLight.intensity = 2.8 + ...
 ...
 renderer.render(scene,camera);
 requestAnimationFrame(animate);
}
```
`clock.elapsedTime` in Three Clock after getDelta is updated. Use `const t = performance.now()*0.001`.

Spark update:
```
for i:
 if (life <= 0) { resetSpark(i, true) }
 else {
   life -= dt;
   velocity.y += 0.25*dt; // buoyancy
   velocity.x += Math.sin(t*1.4 + i)*.12*dt
   positions[i*3] += vel.x*dt ...
 }
```
Need store velocities in array of objects or Float32Array. Use `sparkVel = new Float32Array(count*3); sparkLife`, `sparkMaxLife`.
Reset:
```
const a=Math.random()*Math.PI*2, r=Math.random()*1.2;
positions[i*3]=Math.cos(a)*r;
positions[i*3+1]=.6+Math.random()*1.2;
positions[i*3+2]=Math.sin(a)*r;
vel = [.., 1.3+Math.random()*2.5, ..];
life=.8+Math.random()*1.8;
```
Colors maybe random yellow/orange. `colorAttr` with values.

Sparks `PointsMaterial` `vertexColors: true`.

Need perhaps stars twinkle? animate material opacity? not necessary but can vary a few via time? Points material opacity global.

Add small fireflies? no.

Potential issue `THREE.CylinderGeometry` default with `radialSegments=6` gives low-poly. Fine.

Potential issue `MeshStandardMaterial` `flatShading` and `color` are okay.

Need include `aria`? no.

Need ensure exact import map string required. Use exactly given.

Need maybe OrbitControls import from "three/addons/controls/OrbitControls.js" allowed by map. Fine.

No other URL. Great.

Need output only code block. Let's formulate complete code.