var Morph = {
	// Proprietà
	config : {
		fps : 25
	},
	_cache : [null],
	// Metodi
	// ##################################
	// Loops
	// Metodo privato che crea la ricorsione
	_looper : function(c) {
		var l = Morph._cache[c];
		if(l) {
			Morph.set.apply(null, l.d);
			l.l = window.setTimeout('Morph._looper(' + c + ');', (l.r * 1000));
		}
	},
	// Imposta un loop
	setLoop : function() {
		var a = arguments, r = 0, c = Morph._cache.length, e = [];
		for(var i = 0, m; i < a.length; i++) {
			o = Morph._adjust(a[i]);
			r += o.time + o.wait;
			a[i] = o;
			m = o.element;
			o = I(o.element);
			e[e.length] = m;
			if(!o._xFx) Morph._init(o);
			o._xFx.loop = c;
		}
		e = e.unique();
		Morph._cache[c] = {
			d: a,
			e: e,
			c: c,
			r: r,
			l: null
		};
		Morph._looper(c, r);
		return c;
	},
	// Cancella un loop
	clearLoop : function(c, s) {
		var l = Morph._cache[c];
		if(l) {
			var m = l.e, t = l.l;
			if(s) Morph.stop(m);
			else for(var i = 0, k = m.length; i <= k; i++) m[i]._xFx.loop = null;
			if(t) window.clearTimeout(l.l);
		}
		delete Morph._cache[c];
	},
	// Inizializzatore del morphing
	set : function() {
		var a = arguments, l = a.length, r = 0, c = '', e = [];
		for(var i = 0; i < l; i++) {
			a[i] = Morph._adjust(a[i]);
			var u = a[i].element, o = I(u), x = o._xFx;
			if(!x) Morph._init(o);
			else if(x.animated === true) {
				if(x.locked) return false;
				Morph.stop(x.elements);
			}
			if(e.indexOf(u) == -1) {
				c += 'Morph._init("' + u + '");';
				e[e.length] = u;
			}
		}
		for(i = 0; i < l; i++) {
			var k = a[i];
			r += k.wait; k.wait = r; r += k.time;
			Morph._core(k);
		}
		var f = window.setTimeout(c, (r * 1000));
		l = e.length;
		for(i = 0; i < l; i++) {
			x = I(e[i])._xFx;
			x.frames = x.frames.concat(f);
			x.elements = e;
		}
		return e;
	},
	// Metodo privato del CORE del morphing
	_core : function(o) {
		var i = o.element, l = o.styles, s = {}, fps = Morph.config.fps, fpsDiv = 1000 / fps, t = Math.round(o.time * fps),
		e = o.effect, r = o.wait * 1000, c = ['in', 'cm', 'mm', 'pt', 'pc', 'em', 'ex', 'px', '%'],
		u = document.getElementById(i), f = [], z, og, oz, xFx = u._xFx, ss, ff, g, j, ls, z, ee, b,
		ii, jj, yy, mm = null, fs, p, m, exec = [], args = [];
		for(j in l) {
			ls = l[j];
			// Controllo che lo stile sia un array
			if(ls.constructor != Array) ls = [ls];
			// Ottengo lo stile attuale
			z = (j == 'opacity') ? Dom.getOpacity(i) : Dom.getStyle(i, j);
			// Se lo stile attuale è un colore diverso nel formato rg o hsl lo converto
			if(z && (z+'').match(/(hsl|rgb)\([0-9]+%?,[\s]*[0-9]+%?,[\s]*[0-9]+%?\)/i)) z = Color.css2hex(z);
			// Ottengo lo stile originale e nel caso lo setto
			og = xFx.originals[j];
			if(!og && og !== 0) { xFx.originals[j] = z; oz = z; } else oz = og;
			// Sostituisco gli stili attuali e originali
			ls = ls.replace('actual', z).replace('original', oz);
			// Se il primo elemento è una funzione la estraggo e la considero come effetto
			ee = (typeof ls[0] == 'function') ? ls.shift() : e;
			// Se il primo elemento è una unità di misura la estraggo e la conservo
			b = (c.indexOf(ls[0]) != -1) ? ls.shift() : '';
			// Lunghezza dell'array
			ll = ls.length;
			// Indice di scorrimento dei frame
			yy = 0;
			if(ls[0].toString().match(/((rgb|hsl)\([0-9]+%?,[\s]*[0-9]+%?,[\s]*[0-9]+%?\)|#[0-9ABCDEF]{3,6})/gi)) {
				if(ll < 2) {
					ls = [z].concat(ls);
					ll++;
				}
				p = Math.round(t / (ll - 1));
				var s0, s1, s2;
				for(ii = 0; ii < (ll - 1); ii++) {
					ss = Color.css2rgb(ls[ii]);
					ff = Color.css2rgb(ls[ii + 1]);
					g = (ii > 0) ? p + 1 : p;
					s0 = ss[0]; s1 = ss[1]; s2 = ss[2];
					for(jj = 0; jj < g; jj++) {
						if(ii === 0 || (ii > 0 && jj > 0)) {
							m = Color.rgb2hex([
								Math.floor(ee(jj, s0, (ff[0] - s0), g - 1)),
								Math.floor(ee(jj, s1, (ff[1] - s1), g - 1)),
								Math.floor(ee(jj, s2, (ff[2] - s2), g - 1))
							]);
							if(m !== mm) {
								ar = args[yy];
								if(!ar) exec[yy] = args[yy] = '';
								exec[yy] += 's.' + j + '="' + m + '";';
								args[yy] += ((!ar) ? '' : ',') + '"' + j + '":"' + m + '"';
								mm = m;
							}
							yy++;
						}
					}
				}
			} else if(b || typeof ls[0] == 'number') {
				if(ll < 2) {
					ls = [Tools.cleanSize(z)].concat(ls);
					ll++;
				}
				p = Math.round(t / (ll - 1));
				for(ii = 0; ii < (ll - 1); ii++) {
					ss = Tools.cleanSize(ls[ii]);
					ff = Tools.cleanSize(ls[ii + 1]);
					g = (ii > 0) ? p + 1 : p;
					for(jj = 0; jj < g; jj++) {
						if(ii === 0 || (ii > 0 && jj > 0)) {
							m = ee(jj, ss, (ff - ss), g - 1);
							if(!isNaN(m)) {
								m = ((b == 'em' || b === '') ? Math.floor(m * 100) / 100 : Math.floor(m)) + b;
								if((m || m === 0) && m !== mm) {
									ar = args[yy];
									if(!ar) exec[yy] = args[yy] = '';
									if(j == 'opacity') exec[yy] += 'Dom.setOpacity(u,' + m + ');';
									else exec[yy] += 's.' + j + '="' + m + '";';
									args[yy] += ((!ar) ? '' : ',') + '"' + j + '":"' + m + '"';
									mm = m;
								}
							}
							yy++;
						}
					}
				}
			} else {
				if(ll < 2) {
					ls = [ls[0], ls[0]];
					ll++;
				}
				p = Math.round(t / (ll - 1));

				if(!exec[0]) exec[0] = args[0] = '';
				m = ls[0];
				exec[0] += 's.' + j + '="' + m + '";';
				args[0] += '"' + j + '":"' + m + '"';

				for(ii = 1; ii < t - 1; ii++) if(ii % p === 0) {
					m = ls[(ii / p)];
					exec[ii] += 's.' + j + '="' + m + '";';
					args[ii] += ',"' + j + '":"' + m + '"';
				}
				m = ls[ll - 1];
				exec[t - 1] += 's.' + j + '="' + m + '";';
				args[t - 1] += ',"' + j + '":"' + m + '"';
			}
			if(b) ls = [b].concat(ls);
			if(e !== ee) ls = [ee].concat(ls);
			l[j] = ls;
		}
		var v = '', y = '', cd = '', cf = '', os = o.onstart, oh = o.onfinish, oc = o.onchange, of = o.onframe,
		k = 0, x = '', af, a;
		z = 'var u = document.getElementById("' + i + '"), s = u.style;';
		// onChange // per i frame non vuoti
		if(oc) {
			k = Morph._cache.length;
			Morph._cache[k] = oc;
			cd = 'Morph._cache[' + k + '].apply(u,';
			cf = 'delete Morph._cache[' + k + '];';
		}
		// onFrame // per ogni frame
		if(of) {
			k = Morph._cache.length;
			Morph._cache[k] = of;
			v = 'Morph._cache[' + k + '].apply(u,';
			y = 'delete Morph._cache[' + k + '];';
		}
		for(j = 0; j < t; j++) {
			x = '';
			// Se è il frame 0 e non coincide con l'ultimo, e è settato un evento iniziale
			if(j === 0 && j != (t - 1) && os) {
				k = Morph._cache.length;
				Morph._cache[k] = os;
				x += 'Morph._cache[' + k + '].apply(u);delete Morph._cache[' + k + '];';
			}
			m = exec[j];
			if(m) x += m;
			m = args[j];
			if(!m) m = '';
			// ar = '[{' + m + '},' + (j + 1) + ',' + t + ']';
			ar = '[' + (j + 1) + ',' + t + ',{' + m + '}]';

			// Se è
			if((x || j == (t - 1)) && cd) x += cd + ar + ');';
			if(v) x += v + ar + ');'; // Tolto  != ''
			if(j == (t - 1)) {
				if(oh) {
					k = Morph._cache.length;
					Morph._cache[k] = oh;
					x += 'Morph._cache[' + k + '].apply(u);delete Morph._cache[' + k + '];';
				}
				x += y + cf;
			}
			if(x) {
				x = z + x + 'u._xFx.frames.shift();';
				f[f.length] = window.setTimeout(x, Math.round((fpsDiv * (j + 1)) + r));
			}
		}
		xFx.frames = xFx.frames.concat(f);
		xFx.locked = o.locked;
		xFx.animated = true;
	},
	_adjust: function(m) {
		var i = m.element, z = m.styles, e = m.effect, s = m.onstart, f = m.onfinish, a = m.onframe, c = m.onchange,
		t = m.time, w = m.wait, h = m.hits;
		return {
			element: ((i) ? Dom.getId(i, true) : null),
			styles: ((z && typeof z == 'object') ? z : {}),
			effect: ((e) ? ((typeof e == 'function') ? e : Effects[e]) : Effects.linear),
			time: ((t) ? parseFloat(t) : 1),
			wait: ((w) ? parseFloat(w) : 0),
			hits: ((h) ? parseInt(h, 10) : 1),
			onstart: ((typeof s == 'function') ? s : null),
			onfinish: ((typeof f == 'function') ? f : null),
			onframe: ((typeof a == 'function') ? a : null),
			onchange: ((typeof c == 'function') ? c : null),
			locked: ((m.locked) ? true : false)
			//attend: ((m.attend) ? true : false)
		};
	},
	// Inizializza la proprietà privata per gli elementi in morphing
	_init: function(o) {
		o = I(o);
		if(o) {
			if(!o._xFx) o._xFx = {originals : {}};
			o = o._xFx;
			o.frames = [];
			o.animated = false;
			o.elements = [];
			o.locked = false;
			o.paused = [];
			o.loop = null;
		}
	},
	_runCode: function(o) {
		o = I(o);
		if(o._xFx.paused.length > 0) {
			var m = o._xFx.paused.shift();
			Morph.set.apply(null, m);
		}
	},
	// Resetta gli stili originali
	resetStyles: function(o) {
		o = I(o);
		var x = o._xFx;
		if(x) {
			var r = x.originals;
			for(var i in r) {
				if(i == 'opacity') Dom.setOpacity(o, r[i]);
				else o.style[i] = r[i];
			}
		}
	},
	// Ferma il morphing
	stop: function(l) {
		if(l.constructor != Array) l = [l];
		for(var i = 0, k = l.length, o, x, f, g; i < k; i++) {
			o = I(l[i]); x = o._xFx;
			if(x) {
				f = x.frames; g = x.loop;
				for(var j = 0, p = f.length; j < p; j++) window.clearTimeout(f[j]);
				if(g && Morph._cache[g]) {
					var u = Morph._cache[g].l;
					if(u) window.clearTimeout(u);
					delete Morph._cache[g];
				}
				x.loop = null;
			}
			Morph._init(o);
		}
	}
};


var Fx = {
	// #############################################
	// Usa il morph
	opacityShift: function(o) {
		var i = o.element, t = o.time, e = o.effect;
		o = Dom.getOpacity(i);
		if(o < 0.50) Morph.set({element: i, styles : {'opacity' : [o, 1]}, time: t, effect : e});
		else Morph.set({element: i, styles : {'opacity' : [0, o]}, time: t, effect : e});
	},
	// Blind Up-Down
	blindUp: function(o) {
		o = Morph._adjust(o);
		var i = I(o.element), s = i.style;
		s.overflow = 'hidden'; s.display = 'block';
		var n = Tools.cleanSize(Dom.getStyle(i, 'height')), h = Dom.getRealHeight(i);
		h = (h > n) ? h : n;
		o.styles.height = ['px', h, 0];
		Morph.set(o);
	},
	blindDown: function(o) {
		o = Morph._adjust(o);
		var i = I(o.element), s = i.style;
		s.overflow = 'hidden'; s.display = 'block';
		var h = Tools.cleanSize(Dom.getStyle(i, 'height'));
		h = (h > 0) ? h : 0;
		o.styles.height = ['px', h, Dom.getRealHeight(i)];
		Morph.set(o);
	},
	blindShift: function(o) {
		var i = o.element, s = Fx.blindStatus(i);
		if(s < 3) Fx.blindUp(o);
		else Fx.blindDown(o);
	},
	// To check the blind
	blindStatus: function(o) {
		var r = Dom.getRealHeight(o), h = Tools.cleanSize(Dom.getStyle(o, 'height')), m = r / 2;
		if(h == r) return 1;
		if(h == 0) return 5;
		if(h > m) return 2;
		if(h < m) return 3;
		if(h == m) return 4;
		return false;
	},
	// Effetti complessi
	foldUp: function(o) {
		if(!o.effect) o.effect = Effects.outCubic;
		var a = Morph._adjust(o), b = Morph._adjust(o);
		var i = I(a.element), s = i.style, t = a.time / 2;
		s.overflow = 'hidden'; s.display = 'block';
		var n = Tools.cleanSize(Dom.getStyles(i, 'height').height), h = Dom.getRealHeight(i);
		h = (h > n) ? h : n;
		a.time = t; b.time = t;
		a.styles.height = ['px', h, 5];
		a.onfinish = null;
		b.styles.width = ['px', 0];
		b.onstart = null;
		Morph.set(a, b);
	},
	pulse: function(o){
		o = Morph._adjust(o);
		var r = [1], h = o.hits;
		for(i = 0; i < h; i++) r = r.concat([0, 1]);
		o.styles.opacity = r;
		Morph.set(o);
	},
	drop: function(o) {
		if(!o.effect) o.effect = Effects.outCubic;
		o = Morph._adjust(o);
		var i = I(o.element), s = Dom.getStyles(i, 'height', 'position', 'top'),
		t = Tools.cleanSize(s.top), h = Tools.cleanSize(s.height);
		if(s.position != 'absolute') i.style.position = 'relative';
		o.styles.opacity = [1, 0];
		o.styles.top = ['px', t, t+h];
		Morph.set(o);
	},
	vclose: function(o) {
		if(!o.effect) o.effect = Effects.outCubic;
		o = Morph._adjust(o);
		var i = o.element;
		Dom.setStyles(i, {overflow: 'hidden', display: 'block'});
		var s = Dom.getStyles(i, 'height', 'marginTop', 'marginBottom', 'fontSize'),
		n = Tools.cleanSize(s.height), h = Dom.getRealHeight(i),
		f = Tools.cleanSize(s.fontSize, true);
		h = (h > n) ? h : n;
		if(f[0] === 0) f = [1, 'em'];
		//o.styles.opacity = [1, 0];
		o.styles.height = ['px', h, 0];
		//o.styles.fontSize = [f[1], f[0], 0];
		o.onframe = function() {
			var a = Tools.cleanSize(Dom.getStyle(this, 'height'));
			this.style.marginTop = ((h - a) / 2) + 'px';
			this.style.marginBottom = ((h - a) / 2) + 'px';
		 };
		Morph.set(o);
	},
	vanish: function(o) {
		if(!o.effect) o.effect = Effects.outCubic;
		o = Morph._adjust(o);
		var i = o.element,
		s = Dom.getStyles(i, 'width', 'height', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft', 'fontSize'),
		w = Tools.cleanSize(s.width, true), h = Tools.cleanSize(s.height, true), f = Tools.cleanSize(s.fontSize, true);
		if(f[0] === 0) f = [1, 'em'];
		s = o.styles;
		s.opacity = [1,0];
		s.width = [w[1], w[0], (w[0]*2)];
		s.height = [h[1], h[0], (h[0]*2)];
		s.fontSize = [f[1], f[0], (f[0]*2)];
		o.onframe = function() {
			var s = Dom.getStyles(this, 'width', 'height'),
			l = Tools.cleanSize(s.width), a = Tools.cleanSize(s.height);
			s = this.style;
			s.marginTop = ((h[0] - a) / 2) + h[1];
			s.marginRight = ((w[0] - l) / 2) + w[1];
			s.marginBottom = ((h[0] - a) / 2) + h[1];
			s.marginLeft = ((w[0] - l) / 2) + w[1];
		};
		Morph.set(o);
	},

	// #############################################
	// Non usa il morph
	hide: function() {
		var a = arguments;
		for(var i = 0; i < a.length; i++) I(a[i]).style.visibility = 'hidden';
	},
	hideByTagName: function() {
		var a = arguments, l = a.length, r = [];
		for(var i = 0; i < l; i++) r = r.concat(Dom.byTagName(a[i]));
		Fx.hide.apply(this, r);
	},
	animage: function(o) {
		o = Fx._cleanAnimage(o);
		var u = o.url, w = o.width, h = o.height, f = o.frames, d = o.delay, p = o.pause, v = o.vertical,
		c = o.element, l = o.loop, i = Tools.generateId(), s = o.style, g = new Image(); g.src = u;
		if(!f) {
			f = Math.round(g.width / w);
		}
		Dom.create(['div',
			{
				style: {
					display: 'block',
					width: w + 'px',
					height: h + 'px',
					backgroundImage: "url('" + u + "')",
					backgroundRepeat: 'no-repeat',
					backgroundPosition: "0px 0px"
				},
				id: i,
				className: 'animage'
			}
		], c);
		Dom.setStyles(i, s);
		if(v === true) w = 0; else h = 0;
		Fx._animageLoop(i, w, h, f, d, p, l, 0);
	},
	_animageLoop: function(i, w, h, f, d, p, l, a) {
		var t = d;
		if(a === 0 || a == f) {
			a = 0;
			t = p;
			l--;
		}
		if(l >= 0) {
			I(i).style.backgroundPosition = "-" + (w * a) + "px -" + (h * a) + "px";
			a++;
			window.setTimeout("Fx._animageLoop('" + i + "'," + w + "," + h + "," + f + "," + d + "," + p + "," + l + "," + a + ")", t);
		}
	},
	_cleanAnimage: function(o) {
		var r = {}, e = o.element, u = o.url, w = o.width, h = o.height, f = o.frames,
		d = o.delay, p = o.pause, l = o.loop, s = o.style, z = typeof s;
		r.element = (e) ? e : null;
		r.url = (u) ? u : '';
		r.width = (w) ? parseInt(w, 10) : 0;
		r.height = (h) ? parseInt(h, 10) : 0;
		r.frames = (f) ? parseInt(f, 10) : 0;
		r.delay = (d) ? parseInt(d, 10) : 40;
		r.pause = (p) ? parseInt(p, 10) : 40;
		r.vertical = (o.vertical) ? true : false;
		r.loop = (l) ? ((typeof l == 'number') ? parseInt(l, 10) : Infinity) : 1;
		r.style = (z == 'object' || z == 'string') ? s : {};
		return r;
	},
	makeTabs: function(o, a, e) {
		o = I(o); a = P(a, o); var l = a.length, f = false;
		for(var i = 0; i < l; i++) {
			var b = a[i];
			var n = b.tagName;
			if(n && n.toLowerCase() == 'a') {
				var h = b.getAttribute('href');
				var s = h.split('#');
				if(s[1]) {
					var d = I(s[1]), s = d.style;
					if(d) {
						if(!f) {
							s.display = 'block';
							Dom.addClassName(b, 'active');
							f = true;
						} else {
							s.display = 'none';
							s.height = '0px';
							Dom.setOpacity(d, 0);
						}

						b.onclick = function() {
							if(Dom.hasClassName(this, 'active')) return false;

							var h = null;
							for(var j = 0; j < l; j++) {
								var b = a[j];
								var n = b.tagName;
								if(n && n.toLowerCase() == 'a') {
									if(Dom.hasClassName(a[j], 'active')) {
										h = b.getAttribute('href').split('#');
										Dom.removeClassName(a[j], 'active');
										break;
									}
								}
							}

							var s = this.getAttribute('href').split('#');

							if(h) {
								Fx.blindUp({
									element: h[1],
									styles: {
										opacity: [1, 0],
										display: ['block', 'none']
									},
									onfinish: function() {
										Fx.blindDown({
											element: s[1],
											styles: {
												opacity: [0, 1],
												display: ['block']
											},
											time: 0.5
										});
									},
									time: 0.5
								});
							} else {
								Fx.blindDown({
									element: s[1],
									styles: {
										opacity: [0, 1],
										display: ['block']
									},
									time: 0.5
								});
							}
							Dom.addClassName(this, 'active');
							return false;
						};
					}
				}
			}
		}
	}

};



var Color = {
	// Metodo per ottenere un oggetto contenente
	colorize: function(o, e, f, d) {
		var s = {}, r = {}, g = ['backgroundColor', 'borderTopColor', 'borderRightColor', 'borderBottomColor', 'borderLeftColor', 'color'];
		o = I(o);
		if(!e) e = Color.toGrayscale; if(!f) f = '#000000';
		if(o.currentStyle) s = o.currentStyle;
		else if(document.defaultView.getComputedStyle) s = document.defaultView.getComputedStyle(o, '');
		for(var n = 0, i = g.length - 1, j, z, c; i >= 0; i--) {
			j = g[i]; z = s[j];
			if(z.length > 0 && z != 'transparent') {
				c = Color.css2hex(z);
				r[j] = (d) ? [e(c, f), c] : [c, e(c, f)];
				n++;
			}
		}
		return (n > 0) ? r : false;
	},
	// Metodi per convertire i colori
	sepia: function(o) {
		o = Color.hex2rgb(o);
		var a = o[0], b = o[1], c = o[2];
		return Color.rgb2hex([
			Math.round((a * 0.393) + (b * 0.769) + (c * 0.189)),
			Math.round((a * 0.349) + (b * 0.686) + (c * 0.168)),
			Math.round((a * 0.272) + (b * 0.534) + (c * 0.131))
		]);
	},
	negative: function(c) {
		c = Color.hex2rgb(c);
		return Color.rgb2hex([255 - c[0], 255 - c[1], 255 - c[2]]);
	},
	grayscale: function(o, f) {
		if(!f) f = 4; o = Color.hex2rgb(o);
		var a = o[0], b = o[1], c = o[2], r = [];
		switch(f) {
			case 1: case 'SimpleAverage':
				r = [Math.round((a + b + c) / 3),
					Math.round((a + b + c) / 3),
					Math.round((a + b + c) / 3)];
			break;
			case 2: case 'WeightAverage':
				r = [Math.round((3 * a) + (4 * c) + (2 * b) / 9),
					Math.round((3 * a) + (4 * c) + (2 * b) / 9),
					Math.round((3 * a) + (4 * c) + (2 * b) / 9)];
			break;
			case 3: case 'CCIRRec709':
				r = [Math.round((0.2125 * a) + (0.7154 * b) + (0.0721 * c)),
					Math.round((0.2125 * a) + (0.7154 * b) + (0.0721 * c)),
					Math.round((0.2125 * a) + (0.7154 * b) + (0.0721 * c))];
			break;
			default: case 4: case 'NtscPal':
				r = [Math.round((0.299 * a) + (0.587 * b) + (0.114 * c)),
					Math.round((0.299 * a) + (0.587 * b) + (0.114 * c)),
					Math.round((0.299 * a) + (0.587 * b) + (0.114 * c))];
			break;
		}
		return Color.rgb2hex(r);
	},
	monochrome: function(o, f) {
		o = Color.hex2rgb(o); f = Color.hex2rgb(f);
		var a = o[0], b = o[1], c = o[2], x = f[0], y = f[1], z = f[2];
		return Color.rgb2hex([
			Math.round((a * (x / 255)) + (b * (x / 255)) + (c * (x / 255))),
			Math.round((a * (y / 255)) + (b * (y / 255)) + (c * (y / 255))),
			Math.round((a * (z / 255)) + (b * (z / 255)) + (c * (z / 255)))
		]);
	},
	color: function(o, f) {
		o = Color.hex2rgb(o);
		var a = o[0], b = o[1], c = o[2];
		return Color.rgb2hex([
			a + Math.round(a / 100 * f[0]),
			b + Math.round(b / 100 * f[1]),
			c + Math.round(c / 100 * f[2])
		]);
	},
	contrast: function(c, f) {
		c = Color.hex2rgb(c);
		return Color.rgb2hex([
			((((c[0] / 255) - 0.5) * Math.pow((1 + (f / 100)), 2)) + 0.5) * 255,
			((((c[1] / 255) - 0.5) * Math.pow((1 + (f / 100)), 2)) + 0.5) * 255,
			((((c[2] / 255) - 0.5) * Math.pow((1 + (f / 100)), 2)) + 0.5) * 255
		]);
	},
	brightness: function(c, f) {
		c = Color.hex2rgb(c);
		return Color.rgb2hex([
			c[0] + Math.round(255 / 100 * f),
			c[1] + Math.round(255 / 100 * f),
			c[2] + Math.round(255 / 100 * f)
		]);
	},
	media: function() {
		var a = arguments, l = a.length, i, c, r = 0, g = 0, b = 0;
		for(i = l-1; i >= 0; i--) {
			c = Color.hex2rgb(a[i]);
			r += c[0]; g += c[1]; b += c[2];
		}
		r /= l; g /= l; b /= l;
		return Color.rgb2hex([r, g, b]);
	},
	hex2rgb: function(h) {
		h = h.replace('#', '');
		return [Color.hex2dec(h.substring(0, 2)), Color.hex2dec(h.substring(2, 4)), Color.hex2dec(h.substring(4, 6))];
	},
	rgb2hex: function(a) {
		var r = a[0], g = a[1], b = a[2];
		if(!r) r = 0; if(!g) g = 0; if(!b) b = 0;
		return ('#' + Color.dec2hex(r) + Color.dec2hex(g) + Color.dec2hex(b)).toUpperCase();
	},
	css2hex: function(c) {
		return Color.rgb2hex(Color.css2rgb(c));
	},
	allCss2rgb: function(c) {
		var m = c.match(/((rgb|hsl)\([0-9]+%?,[\s]*[0-9]+%?,[\s]*[0-9]+%?\)|#[0-9ABCDEF]{3,6})/gi);
		if(!m)  return null;
		for(var i = 0, l = 4, r = []; i < l; i++) {
			c = m[i];
			if(c) c = Color.css2rgb(c);
			else {
				if(i == 1 || i == 2) c = r[0];
				if(i == 3) c = r[1];
			}
			r[i] = c;
		}
		return r;
	},
	css2rgb: function(c) {
		if(c.match(/^#[0-9ABCDEF]{6}$/gi)) return Color.hex2rgb(c);
		var m = c.match(/rgb\(([0-9]+%?),[\s]*([0-9]+%?),[\s]*([0-9]+%?)\)/i);
		if(m) {
			var r = m[1], g = m[2], b = m[3];
			r = (r.indexOf('%') >= 0) ? parseInt(r, 10) * 2.55 : parseInt(r);
			g = (g.indexOf('%') >= 0) ? parseInt(g, 10) * 2.55 : parseInt(g);
			b = (b.indexOf('%') >= 0) ? parseInt(b, 10) * 2.55 : parseInt(b);
			//alert(r + ' - ' + g + ' - ' + b)
			return [r, g, b];
		}
		m = c.match(/hsl\(([0-9]+?),[\s]*([0-9]+%),[\s]*([0-9]+%)\)/i);
		if(m) return Color.hsl2rgb([parseInt(m[1], 10), parseInt(m[2], 10), parseInt(m[3], 10)], t);
		return [0, 0, 0];
	},
	// Converte la serie di valori hls in rgb
 	hsl2rgb: function(c) {
		var h = c[0] / 360, s = c[1] / 100, l = c[2] / 100;
		if(l <= 0.5) m2 = l * (s + 1);
		else m2 = l + s - l * s;
		m1 = l * 2 - m2;
		r = Color.hue2rgb(m1, m2, h + 1 / 3);
		g = Color.hue2rgb(m1, m2, h);
		b = Color.hue2rgb(m1, m2, h - 1 / 3);
		return [Math.round(r*255), Math.round(g*255), Math.round(b*255)];
	},
	hue2rgb: function(m1, m2, h) {
		if(h < 0) h = h + 1;
		if(h > 1) h = h - 1;
		if(h * 6 < 1) return m1 + (m2 - m1) * h * 6;
		if(h * 2 < 1) return m2;
		if(h * 3 < 2) return m1 + (m2 - m1) * (2 / 3 - h) * 6;
		return m1;
	},
	// restituisce la CSS stringa rgb
	_rgb: function(c, s) {
		if(s) return 'rgb(' + c[0] + ',' + c[1] + ',' + c[2] + ')';
		return c;
	},
	hex2dec: function(d) {
		d = parseInt(d, 16);
		return ((d > 255) ? 255 : ((d < 0) ? 0 : d));
	},
	dec2hex: function(o) {
		var d = (o > 255) ? 255 : ((o < 0) ? 0 : o), h = parseInt(d, 10).toString(16);
		if(d < 16) h = '0' + h;
		return h;
	},
	/*cmyk2rgb: function(c, m, y, k) {
		var b = (255 - k) / 255;
		return [
			(255 - c) * b,
			(255 - m) * b,
			(255 - y) * b
		];
	},*/
	hex2name: function(c) {
		c = c.toUpperCase();
		var n = Color._names, l = n.length, i, d;
		for(i = l - e; i >= 0; i--) {
			d = n[i];
			if(c == d[1]) return d[0];
		}
		return null;
	},
	rgb2name: function(c) {
		return Color.hex2name(Color.rgb2hex(c));
	},
	name2hex: function(c) {
		c = c.toLowerCase();
		var n = Color._names, l = n.length, i, d;
		for(i = l - e; i >= 0; i--) {
			d = n[i];
			if(c == d[0].toLowerCase()) return d[1];
		}
		return null;
	},
	name2rgb: function(c) {
		c = Color.name2hex(c);
		if(c) c = Color.hex2rgb(c);
		return c;
	},
	_names: [
		['AliceBlue', '#F0F8FF'],
		['AntiqueWhite', '#FAEBD7'],
		['Aqua', '#00FFFF'],
		['Aquamarine', '#7FFFD4'],
		['Azure', '#F0FFFF'],
		['Beige', '#F5F5DC'],
		['Bisque', '#FFE4C4'],
		['Black', '#000000'],
		['BlanchedAlmond', '#FFEBCD'],
		['Blue', '#0000FF'],
		['BlueViolet', '#8A2BE2'],
		['Brown', '#A52A2A'],
		['BurlyWood', '#DEB887'],
		['CadetBlue', '#5F9EA0'],
		['Chartreuse', '#7FFF00'],
		['Chocolate', '#D2691E'],
		['Coral', '#FF7F50'],
		['CornflowerBlue', '#6495ED'],
		['Cornsilk', '#FFF8DC'],
		['Crimson', '#DC143C'],
		['Cyan', '#00FFFF'],
		['DarkBlue', '#00008B'],
		['DarkCyan', '#008B8B'],
		['DarkGoldenRod', '#B8860B'],
		['DarkGray', '#A9A9A9'],
		['DarkGrey', '#A9A9A9'],
		['DarkGreen', '#006400'],
		['DarkKhaki', '#BDB76B'],
		['DarkMagenta', '#8B008B'],
		['DarkOliveGreen', '#556B2F'],
		['Darkorange', '#FF8C00'],
		['DarkOrchid', '#9932CC'],
		['DarkRed', '#8B0000'],
		['DarkSalmon', '#E9967A'],
		['DarkSeaGreen', '#8FBC8F'],
		['DarkSlateBlue', '#483D8B'],
		['DarkSlateGray', '#2F4F4F'],
		['DarkSlateGrey', '#2F4F4F'],
		['DarkTurquoise', '#00CED1'],
		['DarkViolet', '#9400D3'],
		['DeepPink', '#FF1493'],
		['DeepSkyBlue', '#00BFFF'],
		['DimGray', '#696969'],
		['DimGrey', '#696969'],
		['DodgerBlue', '#1E90FF'],
		['FireBrick', '#B22222'],
		['FloralWhite', '#FFFAF0'],
		['ForestGreen', '#228B22'],
		['Fuchsia', '#FF00FF'],
		['Gainsboro', '#DCDCDC'],
		['GhostWhite', '#F8F8FF'],
		['Gold', '#FFD700'],
		['GoldenRod', '#DAA520'],
		['Gray', '#808080'],
		['Grey', '#808080'],
		['Green', '#008000'],
		['GreenYellow', '#ADFF2F'],
		['HoneyDew', '#F0FFF0'],
		['HotPink', '#FF69B4'],
		['IndianRed ', '#CD5C5C'],
		['Indigo ', '#4B0082'],
		['Ivory', '#FFFFF0'],
		['Khaki', '#F0E68C'],
		['Lavender', '#E6E6FA'],
		['LavenderBlush', '#FFF0F5'],
		['LawnGreen', '#7CFC00'],
		['LemonChiffon', '#FFFACD'],
		['LightBlue', '#ADD8E6'],
		['LightCoral', '#F08080'],
		['LightCyan', '#E0FFFF'],
		['LightGoldenRodYellow', '#FAFAD2'],
		['LightGray', '#D3D3D3'],
		['LightGrey', '#D3D3D3'],
		['LightGreen', '#90EE90'],
		['LightPink', '#FFB6C1'],
		['LightSalmon', '#FFA07A'],
		['LightSeaGreen', '#20B2AA'],
		['LightSkyBlue', '#87CEFA'],
		['LightSlateGray', '#778899'],
		['LightSlateGrey', '#778899'],
		['LightSteelBlue', '#B0C4DE'],
		['LightYellow', '#FFFFE0'],
		['Lime', '#00FF00'],
		['LimeGreen', '#32CD32'],
		['Linen', '#FAF0E6'],
		['Magenta', '#FF00FF'],
		['Maroon', '#800000'],
		['MediumAquaMarine', '#66CDAA'],
		['MediumBlue', '#0000CD'],
		['MediumOrchid', '#BA55D3'],
		['MediumPurple', '#9370D8'],
		['MediumSeaGreen', '#3CB371'],
		['MediumSlateBlue', '#7B68EE'],
		['MediumSpringGreen', '#00FA9A'],
		['MediumTurquoise', '#48D1CC'],
		['MediumVioletRed', '#C71585'],
		['MidnightBlue', '#191970'],
		['MintCream', '#F5FFFA'],
		['MistyRose', '#FFE4E1'],
		['Moccasin', '#FFE4B5'],
		['NavajoWhite', '#FFDEAD'],
		['Navy', '#000080'],
		['OldLace', '#FDF5E6'],
		['Olive', '#808000'],
		['OliveDrab', '#6B8E23'],
		['Orange', '#FFA500'],
		['OrangeRed', '#FF4500'],
		['Orchid', '#DA70D6'],
		['PaleGoldenRod', '#EEE8AA'],
		['PaleGreen', '#98FB98'],
		['PaleTurquoise', '#AFEEEE'],
		['PaleVioletRed', '#D87093'],
		['PapayaWhip', '#FFEFD5'],
		['PeachPuff', '#FFDAB9'],
		['Peru', '#CD853F'],
		['Pink', '#FFC0CB'],
		['Plum', '#DDA0DD'],
		['PowderBlue', '#B0E0E6'],
		['Purple', '#800080'],
		['Red', '#FF0000'],
		['RosyBrown', '#BC8F8F'],
		['RoyalBlue', '#4169E1'],
		['SaddleBrown', '#8B4513'],
		['Salmon', '#FA8072'],
		['SandyBrown', '#F4A460'],
		['SeaGreen', '#2E8B57'],
		['SeaShell', '#FFF5EE'],
		['Sienna', '#A0522D'],
		['Silver', '#C0C0C0'],
		['SkyBlue', '#87CEEB'],
		['SlateBlue', '#6A5ACD'],
		['SlateGray', '#708090'],
		['SlateGrey', '#708090'],
		['Snow', '#FFFAFA'],
		['SpringGreen', '#00FF7F'],
		['SteelBlue', '#4682B4'],
		['Tan', '#D2B48C'],
		['Teal', '#008080'],
		['Thistle', '#D8BFD8'],
		['Tomato', '#FF6347'],
		['Turquoise', '#40E0D0'],
		['Violet', '#EE82EE'],
		['Wheat', '#F5DEB3'],
		['White', '#FFFFFF'],
		['WhiteSmoke', '#F5F5F5'],
		['Yellow', '#FFFF00'],
		['YellowGreen', '#9ACD32']
	]
};



// Easing Equations from Robert Penner http://www.robertpenner.com/
var Effects = {
	linear: function (t, b, c, d) {
		return c*t/d + b;
	},
	inQuad: function(t, b, c, d) {
		return c*(t/=d)*t + b;
	},
	outQuad: function(t, b, c, d) {
		return -c *(t/=d)*(t-2) + b;
	},
	inOutQuad: function(t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},
	inCubic: function (t, b, c, d) {
		return c*(t/=d)*t*t + b;
	},
	outCubic: function (t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	},
	inOutCubic: function (t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t + b;
		return c/2*((t-=2)*t*t + 2) + b;
	},
	inQuart: function (t, b, c, d) {
		return c*(t/=d)*t*t*t + b;
	},
	outQuart: function (t, b, c, d) {
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},
	inOutQuart: function (t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	},
	inQuint: function (t, b, c, d) {
		return c*(t/=d)*t*t*t*t + b;
	},
	outQuint: function (t, b, c, d) {
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},
	inOutQuint: function (t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	},
	inSine: function (t, b, c, d) {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},
	outSine: function (t, b, c, d) {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	},
	inOutSine: function (t, b, c, d) {
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},
	inExpo: function (t, b, c, d) {
		return (t===0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	},
	outExpo: function (t, b, c, d) {
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},
	inOutExpo: function (t, b, c, d) {
		if (t===0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	},
	inCirc: function (t, b, c, d) {
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	},
	outCirc: function (t, b, c, d) {
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	},
	inOutCirc: function (t, b, c, d) {
		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	},
	inElastic: function (t, b, c, d, a, p) {
		if (t===0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*0.3; if(!a) a=0;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	},
	outElastic: function (t, b, c, d, a, p) {
		if (t===0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*0.3; if(!a) a=0;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},
	inOutElastic: function (t, b, c, d, a, p) {
		if (t===0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(0.3*1.5); if(!a) a=0;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		if (t < 1) return -0.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*0.5 + c + b;
	},
	inBack: function (t, b, c, d, s) {
		if (s === undefined) s = 1.70158;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},
	outBack: function (t, b, c, d, s) {
		if (s === undefined) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},
	inOutBack: function (t, b, c, d, s) {
		if (s === undefined) s = 1.70158;
		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
	},
	inBounce: function (t, b, c, d) {
		return c - Effects.outBounce (d-t, 0, c, d) + b;
	},
	outBounce: function (t, b, c, d) {
		if ((t/=d) < (1/2.75)) {
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)) {
			return c*(7.5625*(t-=(1.5/2.75))*t + 0.75) + b;
		} else if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + 0.9375) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + 0.984375) + b;
		}
	},
	inOutBounce: function (t, b, c, d) {
		if (t < d/2) return Effects.inBounce (t*2, 0, c, d) * 0.5 + b;
		return Effects.outBounce (t*2-d, 0, c, d) * 0.5 + c*0.5 + b;
	}
};

Effects.circleY = function(t, b, c, d) {
	return (c * Math.sin(t / d * 2 * Math.PI)) + b;
};
Effects.circleX = function(t, b, c, d) {
	return (c * Math.cos(t / d * 2 * Math.PI)) + b;
};
Effects.outSpiralY = function(t, b, c, d) {
	return ((c / d * t) * Math.sin(t / d * 2 * Math.PI)) + b;
};
Effects.outSpiralX = function(t, b, c, d) {
	return ((c / d * t) * Math.cos(t / d * 2 * Math.PI)) + b;
};
Effects.inSpiralY = function(t, b, c, d) {
	return ((c / d * (d-t)) * Math.sin(t / d * 2 * Math.PI)) + b;
};
Effects.inSpiralX = function(t, b, c, d) {
	return ((c / d * (d-t)) * Math.cos(t / d * 2 * Math.PI)) + b;
};
