             let totalDuration = 2.0 * (delay + interval)
             keyTimes =
             [
-                0.0,                                              // Initial gradient
-                delay/totalDuration,                              // Begin of fade in
-                (delay + 0.4)/totalDuration,                      // End of fade in, just as scroll away starts
-                0.95 * totalDuration/totalDuration,               // Begin of fade out, just before scroll home completes
-                1.0,                                              // End of fade out, as scroll home completes
-                1.0                                               // Buffer final value (used on continuous types)
+                0.0,                                                // 1) Initial gradient
+                delay/totalDuration,                                // 2) Begin of LE fade-in, just as scroll away starts
+                (delay + 0.4)/totalDuration,                        // 3) End of LE fade in [LE fully faded]
+                (delay + interval - 0.4)/totalDuration,             // 4) Begin of TE fade out, just before scroll away finishes
+                (delay + interval)/totalDuration,                   // 5) End of TE fade out [TE fade removed]
+                (delay + interval + delay)/totalDuration,           // 6) Begin of TE fade back in, just as scroll home starts
+                (delay + interval + delay + 0.4)/totalDuration,     // 7) End of TE fade back in [TE fully faded]
+                (totalDuration - 0.4)/totalDuration,                // 8) Begin of LE fade out, just before scroll home finishes
+                1.0                                                 // 9) End of LE fade out, just as scroll home finishes
             ]
             
         // .MLContinuous, .MLContinuousReverse

    
    private func keyFrameAnimationForGradient(fadeLength: CGFloat, interval: CGFloat, delay: CGFloat) -> CAKeyframeAnimation {
        // Setup
        var values: [AnyObject]? = nil
        var keyTimes: [AnyObject]? = nil
        let fadeFraction = fadeLength/self.bounds.size.width
        
        // Create new animation
        let animation = CAKeyframeAnimation(keyPath: "locations")
        
        // Get timing function
        let timingFunction = timingFunctionForAnimationCurve(animationCurve)

        // Remove any in flight animations
        gradientMask.removeAllAnimations()
        
        // Set up colors
        let transparent = UIColor.clearColor().CGColor
        let opaque = UIColor.blackColor().CGColor
        
        gradientMask.bounds = self.layer.bounds
        gradientMask.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds))
        gradientMask.shouldRasterize = true
        gradientMask.rasterizationScale = UIScreen.mainScreen().scale
        gradientMask.startPoint = CGPointMake(0.0, 0.5)
        gradientMask.endPoint = CGPointMake(1.0, 0.5)
        // Start with default (no fade) locations
        gradientMask.colors = [opaque, opaque, opaque, opaque]
        gradientMask.locations = [0.0, 0.0, 1.0, 1.0]
        
        // Set mask
        self.layer.mask = gradientMask
        
        let leftFadeStop = fadeLength/self.bounds.size.width
        let rightFadeStop = fadeLength/self.bounds.size.width
        
        // Adjust stops based on fade length
        let adjustedLocations = [0.0, leftFadeStop, (1.0 - rightFadeStop), 1.0]
        
        // Determine colors for non-scrolling label (i.e. at home)
        var adjustedColors: [CGColorRef]
        let trailingFadeNeeded = (!self.labelize || self.labelShouldScroll())
        
        switch (type) {
        case .ContinuousReverse, .RightLeft:
            adjustedColors = [(trailingFadeNeeded ? transparent : opaque), opaque, opaque, opaque]
        
        // .MLContinuous, .MLLeftRight
        default:
            adjustedColors = [opaque, opaque, opaque, (trailingFadeNeeded ? transparent : opaque)]
            break
        }
        
        if (animated) {
            // Create animation for location change
            let locationAnimation = CABasicAnimation(keyPath: "locations")
            locationAnimation.fromValue = gradientMask.locations
            locationAnimation.toValue = adjustedLocations
            locationAnimation.duration = 0.25
            
            // Create animation for location change
            let colorAnimation = CABasicAnimation(keyPath: "colors")
            colorAnimation.fromValue = gradientMask.locations
            colorAnimation.toValue = adjustedColors
            colorAnimation.duration = 0.25
            
            // Create animation group
            let group = CAAnimationGroup()
            group.animations = [locationAnimation, colorAnimation]
            group.duration = 0.25
            
            gradientMask.addAnimation(group, forKey: colorAnimation.keyPath)
            gradientMask.locations = adjustedLocations
            gradientMask.colors = adjustedColors;
        } else {
            CATransaction.begin()
            CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
            gradientMask.locations = adjustedLocations
            gradientMask.colors = adjustedColors
            CATransaction.commit()
        }
    }
