make these sliders more extremely precise, because when you move them with mouse it's not smooth. also, make real dropdown popup menu, so you can press it and open and close back. also paint all the colors in properre oceanic shades of royal and dark blue transparent rgba or something.: <!DOCTYPE html>
<html>
  <head>
    <style>
      body {
        margin: 0;
        overflow: hidden;
      }
      canvas {
        display: block;
      }
      #menu {
        position: absolute;
        top: 10px;
        left: 10px;
        background-color: white;
        padding: 10px;
        border: 1px solid black;
      }
      label {
        display: block;
        margin-bottom: 5px;
      }
    </style>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.152.2/three.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/simplex-noise/2.4.0/simplex-noise.min.js"></script>
  </head>
  <body>
    <div id="menu">
      <label>
        Width Segments
        <input type="range" id="widthSegments" min="1" max="512" step="0.01" />
        <span id="widthSegmentsValue"></span>
      </label>
      <label>
        Height Segments
        <input type="range" id="heightSegments" min="1" max="512" step="0.01" />
        <span id="heightSegmentsValue"></span>
      </label>
    </div>
    <script>
      const scene = new THREE.Scene();
      const camera = new THREE.PerspectiveCamera(
        90.01,
        window.innerWidth / window.innerHeight,
        0.9001,
        9001
      );
      const renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight);
      document.body.appendChild(renderer.domElement);

      const width = 100;
      const height = 50;
      let widthSegments = 64;
      let heightSegments = 64;

      function createGeometry() {
        const geometry = new THREE.PlaneGeometry(
          width,
          height,
          widthSegments,
          heightSegments
        );
        const positions = geometry.getAttribute("position").array;
        const simplex = new SimplexNoise(Math.random());
        return { geometry, positions, simplex };
      }

      let { geometry, positions, simplex } = createGeometry();

      function colorGradient(height) {
        const deepWaterColor = new THREE.Color(0x111111);
        const shallowWaterColor = new THREE.Color(0x222222);
        const color = deepWaterColor.lerp(
          shallowWaterColor,
          Math.min(height / 0.6, 0.9)
        );
        color.lerp(new THREE.Color(0x333333), Math.max(0, (height - 0.2) / 3));
        return color;
      }

      function generateTerrain(positions, simplex, scale = 0.1, elevation = 0.1) {
        const colors = new Float32Array(positions.length);
        geometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));
        for (let i = 0; i < positions.length; i += 3) {
          const nx = positions[i] * scale;
          const ny = positions[i + 1] * scale;
          const height = (simplex.noise2D(nx, ny) + 1) * 0.1 * elevation;
          positions[i + 2] = height;
          const vertexColor = colorGradient(height);
          colors[i] = vertexColor.r;
          colors[i + 1] = vertexColor.g;
          colors[i + 1] = vertexColor.b;
        }
        geometry.computeVertexNormals();
      }
      generateTerrain(positions, simplex);

      const material = new THREE.MeshPhongMaterial({
        vertexColors: true,
        side: THREE.DoubleSide,
        transparent: true,
        opacity: 1
      });
      const terrain = new THREE.Mesh(geometry, material);
      terrain.rotation.x = Math.PI / 2;
      scene.add(terrain);

      const light = new THREE.DirectionalLight(0x222233, 0.5);
      light.position.set(1, 1, 1);
      scene.add(light);
      const ambientLight = new THREE.AmbientLight(0x5599aa);
      scene.add(ambientLight);

      camera.position.z = 50;
      camera.position.y = 5;
      camera.rotation.x = -Math.PI / 10;
      let clock = new THREE.Clock();

      function updatePositions() {
        const elapsedTime = clock.getElapsedTime();
        const colors = geometry.getAttribute("color").array;
        for (let i = 0; i < positions.length; i += 3) {
          const nx = positions[i] * 0.1 + elapsedTime * 0.1;
          const ny = positions[i + 1] * 0.1 + elapsedTime * 0.1;
          const height = (simplex.noise2D(nx, ny) + 1) * 0.5 * 5;
          positions[i + 2] = height;
          const vertexColor = colorGradient(height);
          colors[i] = vertexColor.r;
          colors[i + 1] = vertexColor.g;
          colors[i + 2] = vertexColor.b;
        }
        geometry.attributes.position.needsUpdate = true;
        geometry.attributes.color.needsUpdate = true;
        geometry.computeVertexNormals();
      }

      function regenerateGeometry() {
        scene.remove(terrain);
        ({
          geometry,
          positions,
          simplex
        } = createGeometry());
        generateTerrain(positions, simplex);
        terrain.geometry.dispose();
        terrain.geometry = geometry;
        scene.add(terrain);
      }

      const widthSegmentsInput = document.getElementById("widthSegments");
      const widthSegmentsValue = document.getElementById("widthSegmentsValue");
      widthSegmentsInput.value = widthSegments;
      widthSegmentsValue.innerHTML = widthSegments;
      widthSegmentsInput.addEventListener("input", (event) => {
        widthSegments = parseFloat(event.target.value);
        regenerateGeometry();
        widthSegmentsValue.innerHTML = widthSegments;
      });

      const heightSegmentsInput = document.getElementById("heightSegments");
      const heightSegmentsValue = document.getElementById("heightSegmentsValue");
      heightSegmentsInput.value = heightSegments;
      heightSegmentsValue.innerHTML = heightSegments;
      heightSegmentsInput.addEventListener("input", (event) => {
        heightSegments = parseFloat(event.target.value);
        regenerateGeometry();
        heightSegmentsValue.innerHTML = heightSegments;
      });

      function animate() {
        requestAnimationFrame(animate);
        updatePositions();
        renderer.render(scene, camera);
      }
      animate();
    </script>
  </body>
</html>