diff --git a/src/parallax-css-testpage/particles.js b/src/parallax-css-testpage/particles.js
index 7bc7882aeaaddb6914bfacbe26cd73b18b260879..f28b9911a7d68bc25a6ed57f7253f43e9334b8d2 100644
--- a/src/parallax-css-testpage/particles.js
+++ b/src/parallax-css-testpage/particles.js
@@ -4,8 +4,19 @@
  *  Particle emitter and renderer.
  */
 
-const Debug = false
-const Static = true
+
+// Polyfill: requestAnimationFrame()
+//
+// window.requestAnimationFrame = function() {
+//     return window.requestAnimationFrame ||
+//        	window.webkitRequestAnimationFrame ||
+// 		window.mozRequestAnimationFrame ||
+// 		window.msRequestAnimationFrame ||
+// 		window.oRequestAnimationFrame ||
+// 		function(f) {
+// 			window.setTimeout(f,1e3/60);
+// 		}
+// }();
 
 
 //
@@ -50,9 +61,9 @@ function MaxValue(value, max) {
 }
 
 function RandomPoint2D(minMaxX, minMaxY) {
-    const x = randomValue(minMaxX.min, minMaxX.max)
-    const y = randomValue(minMaxY.min, minMaxY.max)
-    return Point2D(x, y)
+    var x = randomValue(minMaxX.min, minMaxX.max)
+    var y = randomValue(minMaxY.min, minMaxY.max)
+    return Point2D( x, y )
 }
 
 function Particle({ position, direction, size, color }) {
@@ -69,87 +80,85 @@ function Update(scene, particle) {
     // Cache object access
     var width = scene.width
     var height = scene.height
+    var particleSize = particle.size
+    var particleSizeValue = particleSize.value
+    var particleSizeBound = particleSize.bound
+    var particleSizeStep = particleSize.step
+    var particlePosition = particle.position
+    var particlePositionX = particlePosition.x
+    var particlePositionY = particlePosition.y
+    var particleDirection = particle.direction
+    var particleDirectionX = particleDirection.x
+    var particleDirectionY = particleDirection.y
 
     // Animate the pulse effect of the particle
     //
-    const isMaxSize = particle.size.value >= particle.size.bound.max
-    const isMinSize = particle.size.value <= particle.size.bound.min
-    const updateSizeStep =
-        Object.assign({}, particle, {
-            size: Object.assign({}, particle.size, {
-                direction:
-                    (isMaxSize || isMinSize)
-                      ? particle.size.direction * -1
-                      : particle.size.direction
-            })
-        })
-    const updateSize =
-        Object.assign({}, updateSizeStep, {
-            size: Object.assign({}, updateSizeStep.size, {
-                value:
-                    updateSizeStep.size.value + updateSizeStep.size.step * updateSizeStep.size.direction,
-                    // updateSizeStep.size.value
-            })
-        })
+    var isMaxSize = particleSizeValue >= particleSizeBound.max
+    var isMinSize = particleSizeValue <= particleSizeBound.min
+    var sizeDirection =
+        (isMaxSize || isMinSize)
+            ? particleSize.direction * -1
+            : particleSize.direction
+    var sizeValue =
+        particleSizeValue + particleSizeStep * sizeDirection
 
     // Animate the movement of the particle
     // 
-    const sizeOffset = particle.size.value * 0.5
-    const y = particle.position.y
-
-    const top    = y + sizeOffset
-    const bottom = y - sizeOffset
-    const left   = particle.position.x - sizeOffset
-    const right  = particle.position.x + sizeOffset
-
-    const isRightEdge  = (right >= width)
-    const isLeftEdge   = (left <= 0)
-    const isTopEdge    = (bottom < 0)
-    const isBottomEdge = (top > height)
-
-    const updateDirection =
-        Object.assign({}, updateSize, {
-            direction:
-                Point2D(
-                    // Bounce of the right and left edges of the scene
-                    (isRightEdge || isLeftEdge)
-                        ? updateSize.direction.x * -1
-                        : updateSize.direction.x,
-                    // Bounce from the top and bottom edges of the scene
-                    (isTopEdge || isBottomEdge)
-                        ? particle.direction.y * -1
-                        : particle.direction.y,
-                )
-        })
-    const updatePosition =
-        Object.assign({}, updateDirection, {
-            position:
-                Point2D(
-                    updateDirection.position.x + updateDirection.direction.x,
-                    updateDirection.position.y + updateDirection.direction.y,
-                    // (isTopEdge)
-                    //     ? height + sizeOffset
-                    //     : (isBottomEdge)
-                    //         ? -sizeOffset
-                    //         : (updateDirection.position.y + updateDirection.direction.y),
-                )
-        })
-
-    const updatedParticle = Particle(updatePosition)
-    return updatedParticle
+    var sizeOffset = sizeValue * 0.5
+    var top    = particlePositionY + sizeOffset
+    var bottom = particlePositionY - sizeOffset
+    var left   = particlePositionX - sizeOffset
+    var right  = particlePositionX + sizeOffset
+
+    var isRightEdge  = (left > width)
+    var isLeftEdge   = (right < 0)
+    var isTopEdge    = (bottom < 0)
+    var isBottomEdge = (top > height)
+
+    var positionX =
+        (isRightEdge)
+            ? -sizeOffset
+            : (isLeftEdge)
+                ? width + sizeOffset
+                : particlePositionX + particleDirectionX
+
+    var positionY =
+        (isBottomEdge)
+            ? -sizeOffset
+            : (isTopEdge)
+                ? height + sizeOffset
+                : particlePositionY + particleDirectionY
+
+    return Particle({
+        position: {
+            x: positionX,
+            y: positionY,
+        },
+        direction: {
+            x: particleDirectionX,
+            y: particleDirectionY,
+        },
+        size: {
+            value: sizeValue,
+            bound: particleSizeBound,
+            step: particleSizeStep,
+            direction: sizeDirection
+        },
+        color: particle.color
+    })
 }
 
 function Draw(scene, particle) {
     // Cache object access
-    const size     = particle.size.value
-    const position = particle.position
+    var size     = particle.size.value
+    var position = particle.position
 
     // Draw calculations
-    const yOffset = scene.yOffset * scene.depthScale
-    const drawOffset = size * 0.5
-    const y = yOffset + (position.y - drawOffset)
-    const ctx = scene.ctx
-    const isVisible = (size > 0) && (y < window.innerHeight) && (y > 0)
+    var yOffset = scene.yOffset * scene.depthScale
+    var drawOffset = size * 0.5
+    var y = yOffset + (position.y - drawOffset)
+    var ctx = scene.ctx
+    var isVisible = (size > 0) && (y < window.innerHeight) && (y > 0)
 
     // Draw
     if (isVisible) {
@@ -172,39 +181,43 @@ function Render(scene, particles) {
 }
 
 function Animate(scene, particles) {
-    var fpsInterval = scene.fpsInterval
-    var now = Date.now()
-    var then = scene.then
-    var elapsed = now - then
+    var updatedParticles = [],
+        fpsInterval = scene.fpsInterval,
+        now       = performance.now(),
+        then      = scene.then,
+        elapsed   = now - then,
+        tolerance = 0.1
     
     // Just render when we're reaching the configured fps
-    if (elapsed > scene.fpsInterval) {
+    if (elapsed >= (scene.fpsInterval - tolerance)) {
         scene.yOffset = getNodeYOffset(scene.anchorNode)
         scene.then = now - (elapsed % fpsInterval)
         Render(scene, particles)
     }
 
     // Update particle positions for the next render call
-    const updatedParticles = particles.map(function doUpdate(p) {
+    updatedParticles = particles.map(function doUpdate(p) {
         return Update(scene, p)
     })
 
     // Function to animate the next frame
     return function () {
-        return Animate(scene, updatedParticles)
+        return Animate(
+            scene,
+            updatedParticles
+        )
     }
 }
 
 function CreateScene({ canvasId, contentId, depth, fps }) {
-    const contentNode = document.getElementById(contentId)
-    const height = getNodeHeight(contentNode)
-
-    const fpsInterval = 1000 / fps
-    const width  = window.innerWidth
-    const yOffset = 0
-    const canvas = document.getElementById(canvasId)
-    const ctx = canvas.getContext('2d')
-    const depthScaledHeight = height * (depth+1)
+    var contentNode = document.getElementById(contentId),
+        height = getNodeHeight(contentNode),
+        width  = window.innerWidth,
+        fpsInterval = 1000 / fps,
+        yOffset = 0,
+        canvas  = document.getElementById(canvasId),
+        ctx = canvas.getContext('2d'),
+        depthScaledHeight = height * (depth+1)
 
     ctx.canvas.width = width
     ctx.canvas.height = window.innerHeight
@@ -217,7 +230,7 @@ function CreateScene({ canvasId, contentId, depth, fps }) {
         ctx,
         fps,
         fpsInterval,
-        then: Date.now(),
+        then: performance.now(),
         anchorNode: contentNode
     }
 }
@@ -268,9 +281,16 @@ function CreateParticles(scene, {
 
 
 function Particles(configs) {
+
+    var particles = []
+    var isRunning = false
+    var throttled = false
+    var delay = 25
+    var rafId = undefined
+
     function animate(rendererList) {
         if (isRunning) {
-            requestAnimationFrame(function () {
+            rafId = requestAnimationFrame(function () {
                 animate(
                     rendererList.map(function doRender(render) {
                         return render()
@@ -281,43 +301,38 @@ function Particles(configs) {
     }
 
     function init() {
-        return configs.map(function (particleConfig) {
+        particles = configs.map(function (particleConfig) {
             var scene     = CreateScene(particleConfig.scene)
             var particles = CreateParticles(scene, particleConfig.particles)
             return Animate(scene, particles)
         })
+        return particles
     }
 
-    var particles = []
-    var isRunning = false
-    var throttled = false
-    var delay = 250
-
-    return {
-        init: function () {
+    function run() {
+        if (particles.length === 0) {
             particles = init()
-        },
-
-        run: function () {
-            if (particles.length === 0) {
-                particles = init()
-            }
-            isRunning = true
-            animate(particles)
-        },
+        }
+        isRunning = true
+        animate(particles)
+    }
 
-        stop: function () {
-            isRunning = false
-        },
+    function stop() {
+        isRunning = false
+        cancelAnimationFrame(rafId)
+    }
 
+    return {
+        init: init,
+        run: run,
+        stop: stop,
         onScreenSizeChange: function () {
-            isRunning = false
+            stop()
             if (!throttled) {
                 throttled = true
                 setTimeout(function () {
                     particles = init()
-                    isRunning = true                
-                    animate(particles)
+                    run()
                     throttled = false
                 }, delay)
             }
diff --git a/src/parallax-css-testpage/template.html b/src/parallax-css-testpage/template.html
index 4e26a8770ea90757318849f88c8b065651bc0ffd..fe10fd3894019c37e82ce550e8559959611b7317 100644
--- a/src/parallax-css-testpage/template.html
+++ b/src/parallax-css-testpage/template.html
@@ -109,7 +109,7 @@
                 // rendering height and it's the anchor to get the y offset
                 // to simulate scrolling.
                 contentId: 'content',
-                fps: 14,
+                fps: 16,
                 depth: 0.08,
             },
             particles: {