window.sketch = (runtime) => {
  const { THREE, canvas, startFrame, width, height } = runtime;

  // Scene setup
  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
  camera.position.set(0, 0, 5);

  // Renderer
  const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
  renderer.setSize(width, height, false);
  renderer.setClearColor(0x000000);

  // Clock for time-based animation
  const clock = new THREE.Clock();

  // Lighting
  const ambientLight = new THREE.AmbientLight(0x404040, 0.5);
  scene.add(ambientLight);
  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
  directionalLight.position.set(1, 1, 1);
  scene.add(directionalLight);

  // Vibrant color palette
  const colors = [0xff0066, 0x00ffcc, 0xffcc00, 0xcc00ff, 0x00ccff, 0xff6600];

  // Dynamic floating shapes (mixed geometry)
  const shapes = [];
  const shapeCount = 20;
  const geometries = [
    new THREE.BoxGeometry(0.5, 0.5, 0.5),
    new THREE.SphereGeometry(0.3, 16, 16),
    new THREE.TorusGeometry(0.3, 0.1, 8, 16),
    new THREE.ConeGeometry(0.3, 0.6, 16),
    new THREE.DodecahedronGeometry(0.3),
    new THREE.IcosahedronGeometry(0.3)
  ];

  for (let i = 0; i < shapeCount; i++) {
    const geometry = geometries[Math.floor(Math.random() * geometries.length)];
    const material = new THREE.MeshStandardMaterial({
      color: colors[Math.floor(Math.random() * colors.length)],
      roughness: 0.3,
      metalness: 0.2,
      wireframe: Math.random() > 0.7 ? true : false
    });
    const shape = new THREE.Mesh(geometry, material);

    // Random initial position (-10 to 10 in all axes)
    shape.position.set(
      (Math.random() - 0.5) * 20,
      (Math.random() - 0.5) * 20,
      (Math.random() - 0.5) * 20
    );

    // Random rotation
    shape.rotation.set(
      Math.random() * Math.PI,
      Math.random() * Math.PI,
      Math.random() * Math.PI
    );

    // Random scale
    shape.scale.set(
      0.5 + Math.random() * 1.5,
      0.5 + Math.random() * 1.5,
      0.5 + Math.random() * 1.5
    );

    // Store phase and speed for animation
    shape.userData = {
      phase: Math.random() * Math.PI * 2,
      speed: 0.1 + Math.random() * 0.5,
      rotationSpeed: new THREE.Vector3(
        (Math.random() - 0.5) * 0.02,
        (Math.random() - 0.5) * 0.02,
        (Math.random() - 0.5) * 0.02
      )
    };

    shapes.push(shape);
    scene.add(shape);
  }

  // Textured background plane (chaotic gradient)
  const bgGeometry = new THREE.PlaneGeometry(100, 100);
  const bgMaterial = new THREE.MeshBasicMaterial({
    color: 0x0a0a1a
  });
  const bgPlane = new THREE.Mesh(bgGeometry, bgMaterial);
  bgPlane.position.z = -50;
  scene.add(bgPlane);

  // Particle system for texture
  const particleCount = 500;
  const particlesGeometry = new THREE.BufferGeometry();
  const particlesMaterial = new THREE.PointsMaterial({
    color: 0xffffff,
    size: 0.05,
    transparent: true,
    opacity: 0.8
  });

  const particlePositions = new Float32Array(particleCount * 3);
  const particleColors = new Float32Array(particleCount * 3);

  for (let i = 0; i < particleCount; i++) {
    particlePositions[i * 3] = (Math.random() - 0.5) * 100;
    particlePositions[i * 3 + 1] = (Math.random() - 0.5) * 100;
    particlePositions[i * 3 + 2] = (Math.random() - 0.5) * 100;

    const color = new THREE.Color(colors[Math.floor(Math.random() * colors.length)]);
    particleColors[i * 3] = color.r;
    particleColors[i * 3 + 1] = color.g;
    particleColors[i * 3 + 2] = color.b;
  }

  particlesGeometry.setAttribute('position', new THREE.BufferAttribute(particlePositions, 3));
  particlesGeometry.setAttribute('color', new THREE.BufferAttribute(particleColors, 3));
  particlesMaterial.vertexColors = true;

  const particles = new THREE.Points(particlesGeometry, particlesMaterial);
  scene.add(particles);

  // Animation loop
  startFrame(() => {
    const elapsedTime = clock.getElapsedTime();

    // Animate shapes
    shapes.forEach((shape, index) => {
      // Floating motion
      shape.position.y += Math.sin(elapsedTime * shape.userData.speed + shape.userData.phase) * 0.01;
      shape.position.x += Math.cos(elapsedTime * shape.userData.speed * 0.7 + shape.userData.phase) * 0.005;
      shape.position.z += Math.sin(elapsedTime * shape.userData.speed * 0.5 + shape.userData.phase) * 0.003;

      // Rotation
      shape.rotation.x += shape.userData.rotationSpeed.x;
      shape.rotation.y += shape.userData.rotationSpeed.y;
      shape.rotation.z += shape.userData.rotationSpeed.z;

      // Pulsing scale
      const scalePulse = 1 + Math.sin(elapsedTime * 2 + index) * 0.1;
      shape.scale.setScalar(shape.scale.length() * scalePulse);
    });

    // Animate particles
    const particlePositions = particles.geometry.attributes.position.array;
    for (let i = 0; i < particleCount; i++) {
      const i3 = i * 3;
      particlePositions[i3 + 1] += Math.sin(elapsedTime * 0.5 + i) * 0.01;
      particlePositions[i3] += Math.cos(elapsedTime * 0.3 + i) * 0.005;
    }
    particles.geometry.attributes.position.needsUpdate = true;

    // Camera subtle movement
    camera.position.x += Math.sin(elapsedTime * 0.1) * 0.01;
    camera.position.y += Math.cos(elapsedTime * 0.15) * 0.005;
    camera.lookAt(scene.position);

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

  // Cleanup
  return () => {
    renderer.dispose();
    shapes.forEach(shape => {
      shape.geometry.dispose();
      shape.material.dispose();
    });
    bgGeometry.dispose();
    bgMaterial.dispose();
    particlesGeometry.dispose();
    particlesMaterial.dispose();
  };
};
