var shout = function(el, loud) {
	var type = typeof el;
	var rtrn = "typeof " + type + "\n";
	if (type == 'object')
		for (e in el)
			rtrn += e + ": " + el[e] + "\n";
	if (!loud) alert(rtrn);
	else return rtrn;
}
var develab = {};
	develab.cache = {};
	develab.cache.objects = {};
// !develab.system [anonymous class]
	develab.system = new Object({
		_keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
		registerObject: function(obj, gr) {
			var group	= gr || '_global';

			if (!develab.cache.objects[group])
				develab.cache.objects[group]	= new Array();
			if (typeof obj == 'object' && !develab.cache.objects[group][obj] && develab.cache.objects[group].push(obj)) {
				develab.cache.objects[group].last()._group = develab.cache.objects[group];
				return obj;
			} else if (develab.cache.objects[group][obj])
				return develab.cache.objects[group][obj];
			else return false;
		},
		utf8encode: function(str) {
			str = str.replace(/\r\n/g,"\n");
			var ret = "";

			for (var n = 0; n < str.length; n++) {
				var c = str.charCodeAt(n);
				if (c < 128)
					ret += String.fromCharCode(c);
				else if((c > 127) && (c < 2048)) {
					ret += String.fromCharCode((c >> 6) | 192);
					ret += String.fromCharCode((c & 63) | 128);
				} else {
					ret += String.fromCharCode((c >> 12) | 224);
					ret += String.fromCharCode(((c >> 6) & 63) | 128);
					ret += String.fromCharCode((c & 63) | 128);
				}
			}
			return ret;
		},
		utf8decode: function(str) {
			var ret = "";
			var i = 0;
			var c = c1 = c2 = 0;

			while ( i < str.length ) {
				c = str.charCodeAt(i);
				if (c < 128) {
					ret += String.fromCharCode(c);
					i++;
				} else if((c > 191) && (c < 224)) {
					c2 = str.charCodeAt(i+1);
					ret += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
					i += 2;
				} else {
					c2 = str.charCodeAt(i+1);
					c3 = str.charCodeAt(i+2);
					ret += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
					i += 3;
				}
			}
			return ret;
		},
		base64encode: function(str) {
			var ret = '';
			var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
			var i = 0;

			str = this.utf8encode(str);

			while (i < str.length) {
				chr1 = str.charCodeAt(i++);
				chr2 = str.charCodeAt(i++);
				chr3 = str.charCodeAt(i++);
				enc1 = chr1 >> 2;
				enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
				enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
				enc4 = chr3 & 63;

				if (isNaN(chr2))
					enc3 = enc4 = 64;
				else if (isNaN(chr3))
					enc4 = 64;

				ret = ret
					+ this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2)
					+ this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
			}
			return ret;
		},
		base64decode: function(str) {
			var ret = "";
			var chr1, chr2, chr3;
			var enc1, enc2, enc3, enc4;
			var i = 0;

			str = str.replace(/[^A-Za-z0-9\+\/\=]/g, "");

			while (i < str.length) {
				enc1	= this._keyStr.indexOf(str.charAt(i++));
				enc2	= this._keyStr.indexOf(str.charAt(i++));
				enc3	= this._keyStr.indexOf(str.charAt(i++));
				enc4	= this._keyStr.indexOf(str.charAt(i++));
				chr1	= (enc1 << 2) | (enc2 >> 4);
				chr2	= ((enc2 & 15) << 4) | (enc3 >> 2);
				chr3	= ((enc3 & 3) << 6) | enc4;
				ret		= ret + String.fromCharCode(chr1);

				if (enc3 != 64)
					ret	= ret + String.fromCharCode(chr2);
				if (enc4 != 64)
					ret	= ret + String.fromCharCode(chr3);
			}
			return this.utf8decode(ret);
		},
		serialize: function(mixed_value) {
			var _getType = function(inp) {
				var type = typeof inp, match;
				var key;
				if (type == 'object' && !inp)
					return 'null';
				if (type == "object") {
					if (!inp.constructor)
						return 'object';
					var cons	= inp.constructor.toString();
						match	= cons.match(/(\w+)\(/);
					if (match)
						cons	= match[1].toLowerCase();
					var types	= ["boolean", "number", "string", "array"];
					for (key in types) {
						if (cons == types[key]) {
							type = types[key];
							break;
						}
					}
				}
				return type;
			};
			var type = _getType(mixed_value);
			var val, ktype = '';
			
			switch (type) {
				case "function": 
					val = ""; 
					break;
				case "boolean":
					val = "b:" + (mixed_value ? "1" : "0");
					break;
				case "number":
					val = (Math.round(mixed_value) == mixed_value ? "i" : "d") + ":" + mixed_value;
					break;
				case "string":
					mixed_value = this.utf8encode(mixed_value);
					val = "s:" + encodeURIComponent(mixed_value).replace(/%../g, 'x').length + ":\"" + mixed_value + "\"";
					break;
				case "array":
				case "object":
					val = "a";
					var count = 0;
					var vals = "";
					var okey;
					var key;
					for (key in mixed_value) {
						ktype = _getType(mixed_value[key]);
						if (ktype == "function")
							continue;
						okey = (key.match(/^[0-9]+$/) ? parseInt(key, 10) : key);
						vals += this.serialize(okey) +
						this.serialize(mixed_value[key]);
						count++;
					}
					val += ":" + count + ":{" + vals + "}";
					break;
				case "undefined":
				default:
					val = "N";
					break;
			}
			if (type != "object" && type != "array")
				val += ";";
			return val;
		}
	});
// !develab.element [class]
	develab.element = Class.create(develab.system, {
		initialize: function(el, options) {
			var el = $(el);
			var cb = this.setup.bind(this) || Prototype.emptyFunction;

			this.element	= el || 0;
			this.options	= options || {};

			if (this.registerObject(this, this.options.group))
				cb();
			else return false;
		}
	});
// !develab.loader [class]
	develab.loader = Class.create(develab.element, {
		setup: function() {
			if (this.element.href.indexOf('#') < 0) {
				this.href			= this.options.href || this.element.href || '';
				this.element.href	= '#' + this.href.substr(this.href.indexOf(document.location.hostname) + document.location.hostname.length);
				this.element.observe('click', this.load.bind(this));
			}
		},
		load: function() {
			var req	= new Ajax.Request(
				this.href
				+ (this.options.hrefvar || '?request=')
				+ (this.options.hrefvalue || this.base64encode(this.serialize(this.element.rel.replace(/nofollow/g, '').split(' ')))),
				{
					method:			this.options.method || 'post',
					asynchronous:	this.options.asynchronous || 'true',
					encoding:		this.options.encoding || 'UTF-8',
					evalJS:			this.options.evalJS || true,
					evalJSON:		this.options.evalJSON || true,
					parameters:		this.options.parameters || '',

					onCreate:		this.options.oncreate || Prototype.emptyFunction,
					onComplete:		this.options.oncomplete || Prototype.emptyFunction,
					onFailure:		this.options.onfailure || Prototype.emptyFunction,
					onSuccess:		this.options.onsuccess || Prototype.emptyFunction
				}
			);
		}
	});
	develab.animation = {};
	develab.animation.transitions = {};
	develab.animation.transitions.regular = {};
	develab.animation.transitions.regular.easein = function(t, b, c, d) {
		return c*(t/=d)*t + b;
	};
	develab.animation.transitions.regular.easeout = function(t, b, c, d) {
		return -c *(t/=d)*(t-2) + b;
	};
	develab.animation.transitions.regular.easeinout = function(t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	};
// !develab.animation.tween [class]
	develab.animation.tween = Class.create({
		options: {
			begin		: 0,
			finish		: 1,
			duration	: 1,
			fps			: 20,
			transition	: develab.animation.transitions.regular.easeout,
			callback	: Prototype.emptyFunction,
			beforeBegin	: Prototype.emptyFunction,
			afterFinish	: Prototype.emptyFunction
		},
		initialize: function(opt) {
			var options				= opt || 0;
			for (opt in options)
				this.options[opt]	= options[opt];

			this.reset()
			this.start();
		},
		reset: function() {
			this.position			= this.options.finish - this.options.begin;
			this.tweening			= false;
		},
		start: function() {
			this.options.beforeBegin(this);
			this.time		= new Date().getTime();
			this.interval	= new PeriodicalExecuter(this.loop.bind(this), 1 / this.options.fps);
			this.tweening	= true;
		},
		loop: function() {
			this.elapsed	= new Date().getTime() - this.time;
			if (this.elapsed >= this.options.duration * 1000)
				return this.stop();
			this.position	= this.options.transition(this.elapsed, this.options.begin, this.position, this.options.duration * 1000);
			this.options.callback(this.position);
		},
		stop: function() {
			this.interval.stop();
			//this.options.callback(this.options.finish);
			this.tweening = false;
			this.options.afterFinish(this);
			this.reset();
		}
	});
// !develab.animation.slideDown [class]
	develab.animation.slideDown = Class.create(develab.element, {
		setup: function() {
			new Effect.SlideDown(this.element, { duration: .2, afterFinish: this.options.afterFinish });
		}
	});
// !develab.animation.slideUp [class]
	develab.animation.slideUp = Class.create(develab.element, {
		setup: function() {
			new Effect.SlideUp(this.element, { duration: .2, afterFinish: this.options.afterFinish });
		}
	});
// !develab.animation.blindDown [class]
	develab.animation.blindDown = Class.create(develab.element, {
		setup: function() {
			new Effect.BlindDown(this.element, { duration: .2, afterFinish: this.options.afterFinish });
		}
	});
// !develab.animation.blindUp [class]
	develab.animation.blindUp = Class.create(develab.element, {
		setup: function() {
			new Effect.BlindUp(this.element, { duration: .2, afterFinish: this.options.afterFinish });
		}
	});
	develab.image = {};
// !develab.image.loader [class]
	develab.image.loader = Class.create({
		initialize: function() {
			var imgs = arguments[0] || 0;
			this.clbk = arguments[1] || Prototype.emptyFunction;
			if (imgs && imgs.length) {
				this.queue = [];
				imgs.each(this.queueAdd.bind(this));
				this.queueStart();
			} else this.clbk();
		},
		queueAdd: function() {
			this.queue.push({ src: arguments[0], ready: false });
		},
		queueStart: function() {
			this.queue.each(this._load.bind(this));
		},
		checkStatus: function() {
			var allready = true;
			this.queue.each((function(c) {
				if (!c.ready) allready = false;
			}).bind(this));
			if (allready)
				this.clbk();
		},
		_load: function() {
			var inQueue = arguments[0];
				inQueue.cache = new Image();
				inQueue.cache.onload = (function() {
					inQueue.ready = true;
					this.checkStatus();
				}).bind(this);
				inQueue.cache.src = inQueue.src;
		}
	});
// !develab.accordion [class]
	develab.accordion = Class.create(develab.element, {
		idle: false,
		setup: function() {
			this.opened;
			this.options.effect	= (this.options.effect || 'slide').toLowerCase();
			this.targets		= this.element.select('.' + this.options.targetClass);
			this.handlers		= this.element.select('.' + this.options.handleClass);
			this.handlers.each((function(handler) {
				handler.targetElement = this.options.isWrapped ? handler.up() : handler;
				handler.targetElement = handler.targetElement.next('.' + this.options.targetClass).hide().removeClassName('noscript');
				handler.observe('click', (function(event) {
					event.stop();
					if (!this.idle) {
						this.idle = true;
						var link = '/' + handler.pathname.replace(/^\//i, '');
						_gaq.push(['_trackPageview', link]);
						document.location.hash = link;
						if (!handler.targetElement.visible()) {
							if (this.opened && this.opened != handler) {
								new develab.animation[this.options.effect + 'Up'](
									this.opened.targetElement, {
										afterFinish: (function() {
											this.opened = 0;
											this.idle = false;
										}).bind(this)
									}
								);
							}
							new develab.animation[this.options.effect + 'Down'](
								handler.targetElement, {
									afterFinish: (function() {
										this.opened = handler;
										this.idle = false;
									}).bind(this)
								}
							);
						} else {
							document.location.hash = '/';
							new develab.animation[this.options.effect + 'Up'](
								handler.targetElement, {
									afterFinish: (function() {
										this.opened = 0;
										this.idle = false;
									}).bind(this)
								}
							);
						}
					}
				}).bind(this));
			}).bind(this));
		}
	});
// !develab.fullscreen [class]
	develab.fullscreen = Class.create(develab.element, {
		setup: function() {
//			console.log('develab.fullscreen.setup: ' + this.element)
			this.options.onresize = this.options.onresize || Prototype.emptyFunction;
			Event.observe(window, 'resize', (function() {
				this.options.onresize(this.element);
			}).bind(this));
		}
	});
