    var FadeColor = Class.create();
    FadeColor.prototype = {
    	r: 0, g: 0, b: 0,
    	normalize: function(c) {
    		return c >= 255 ? 255 : (c <= 0 ? 0 : c);
    	},
    	initialize: function(r, g, b) {
    		this.r = this.normalize(r);
    		this.g = this.normalize(g);
    		this.b = this.normalize(b);
    	},
    	getStyle: function() {
    		return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
    	},
    	equal: function(color) {
    		return this.r == color.r && this.g == color.g && this.b == color.b;
    	},
    	add: function (r, g, b) {
    		return new FadeColor(
    			this.normalize(this.r + r),
    			this.normalize(this.g + g),
    			this.normalize(this.b + b));
    	}
    }

    var FadeEffect = Class.create();
    FadeEffect.prototype = {
    	fadeDuration: 1000,		// 1 sec
    	fadeStep: 5,			// 5 points on every fade step
    	stepDelay: 20,			// delay between fade steps
    	startDelay: 500,		// 0.5 sec
    	className: 'fade',
    	startColor: new FadeColor(255, 255, 0),
    	endColor: new FadeColor(255, 255, 234),
    	r: 0, g: 0, b: 0,
    	initialize: function() {},
		cmp: function(a, b) {
			return a > b ? 1 : (a < b ? -1 : 0);
		},
		start: function () {
			this.stepDelay = this.fadeDuration / Math.max(
				Math.abs(this.endColor.r - this.startColor.r), 
				Math.abs(this.endColor.g - this.startColor.g), 
				Math.abs(this.endColor.b - this.startColor.b)) * this.fadeStep;
			this.r = this.cmp(this.endColor.r, this.startColor.r);
			this.g = this.cmp(this.endColor.g, this.startColor.g);
			this.b = this.cmp(this.endColor.b, this.startColor.b);
			var c = this;
			document.getElementsByClassName(
				this.className, document.documentElement).each(function(el, index) {
				setTimeout((
					function(el, color) {
						this.fade(el, color);
					}).bind(c, el, c.startColor), this.startDelay);
			});
		},
		fade: function (el, color) {
			el.style.background = color.getStyle();
			if (! color.equal(this.endColor))
				setTimeout((
					function(el, color) {
						var newColor = color.add(this.r * this.fadeStep, 
							this.g * this.fadeStep, this.b * this.fadeStep);
						newColor.r = newColor.r > this.endColor.r ? this.endColor.r : newColor.r;
						newColor.g = newColor.g > this.endColor.g ? this.endColor.g : newColor.g;
						newColor.b = newColor.b > this.endColor.b ? this.endColor.b : newColor.b;

						this.fade(el, newColor);
					}).bind(this, el, color), this.stepDelay);
		}
	}
	var FadeEffect = new FadeEffect();
	window.onload = function () { FadeEffect.start(); }
