function generateFluidFlow (ctx, size, color) {
  const detail = 15 + Math.floor(Math.random() * 15)
  const vectors = []
  const streamlines = 12 + Math.floor(Math.random() * 12)

  // Create a vector field using perlin-like noise
  for (let i = 0; i < detail; i++) {
    for (let j = 0; j < detail; j++) {
      const x = (i + 0.5) * (size / detail)
      const y = (j + 0.5) * (size / detail)

      // Generate vector field using harmonic functions for smoother flow
      const angle = Math.sin(x * 0.01) * Math.cos(y * 0.01) * Math.PI * 2 +
                   Math.sin(x * 0.02 + y * 0.01) * Math.PI +
                   Math.cos(x * 0.01 - y * 0.03) * Math.PI

      vectors.push({
        x,
        y,
        dx: Math.cos(angle),
        dy: Math.sin(angle)
      })
    }
  }

  // Interpolate vector at any position
  function getVector (x, y) {
    // Find the four nearest vectors
    let totalWeight = 0
    let dx = 0
    let dy = 0

    for (const v of vectors) {
      const distance = Math.sqrt((x - v.x) ** 2 + (y - v.y) ** 2)
      const weight = 1 / (distance + 0.1)

      dx += v.dx * weight
      dy += v.dy * weight
      totalWeight += weight
    }

    return {
      dx: dx / totalWeight,
      dy: dy / totalWeight
    }
  }

  // Draw streamlines
  ctx.strokeStyle = color
  ctx.lineWidth = 1

  for (let i = 0; i < streamlines; i++) {
    // Random starting point
    let x = Math.random() * size
    let y = Math.random() * size

    ctx.beginPath()
    ctx.moveTo(x, y)

    // Follow the vector field
    for (let step = 0; step < 100; step++) {
      const v = getVector(x, y)
      x += v.dx * 5
      y += v.dy * 5

      if (x < 0 || x >= size || y < 0 || y >= size) break

      ctx.lineTo(x, y)
    }

    ctx.stroke()
  }
}
Generates a fluid flow field with streamlines