(function($) {
$.fn.reverseOrder = function() {
	return this.each(function() {
		$(this).prependTo( $(this).parent() );
	});
};
})(jQuery);

$.fn.matchUntil = function(expr) {
    var match = [];
    this.each(function(){
        match = [this];
        for ( var i = this.nextSibling; i; i = i.nextSibling ) {
                if ( i.nodeType != 1 ) { continue; }
                if ( $(i).filter(expr).length > 0 ) { break; }
                match.push( i );
        }
    });
    return this.pushStack( match );
};


//viewport
(function($){$.belowthefold=function(element,settings){var fold=$(window).height()+$(window).scrollTop();return fold<=$(element).offset().top-settings.threshold;};$.abovethetop=function(element,settings){var top=$(window).scrollTop();return top>=$(element).offset().top+$(element).height()-settings.threshold;};$.rightofscreen=function(element,settings){var fold=$(window).width()+$(window).scrollLeft();return fold<=$(element).offset().left-settings.threshold;};$.leftofscreen=function(element,settings){var left=$(window).scrollLeft();return left>=$(element).offset().left+$(element).width()-settings.threshold;};$.inviewport=function(element,settings){return!$.rightofscreen(element,settings)&&!$.leftofscreen(element,settings)&&!$.belowthefold(element,settings)&&!$.abovethetop(element,settings);};$.extend($.expr[':'],{"below-the-fold":function(a,i,m){return $.belowthefold(a,{threshold:0});},"above-the-top":function(a,i,m){return $.abovethetop(a,{threshold:0});},"left-of-screen":function(a,i,m){return $.leftofscreen(a,{threshold:0});},"right-of-screen":function(a,i,m){return $.rightofscreen(a,{threshold:0});},"in-viewport":function(a,i,m){return $.inviewport(a,{threshold:0});}});})(jQuery);



/*
 * jQuery hashchange event - v1.3 - 7/21/2010
 * http://benalman.com/projects/jquery-hashchange-plugin/
 * 
 * Copyright (c) 2010 "Cowboy" Ben Alman
 * Dual licensed under the MIT and GPL licenses.
 * http://benalman.com/about/license/
 */
(function($,e,b){var c="hashchange",h=document,f,g=$.event.special,i=h.documentMode,d="on"+c in e&&(i===b||i>7);function a(j){j=j||location.href;return"#"+j.replace(/^[^#]*#?(.*)$/,"$1")}$.fn[c]=function(j){return j?this.bind(c,j):this.trigger(c)};$.fn[c].delay=50;g[c]=$.extend(g[c],{setup:function(){if(d){return false}$(f.start)},teardown:function(){if(d){return false}$(f.stop)}});f=(function(){var j={},p,m=a(),k=function(q){return q},l=k,o=k;j.start=function(){p||n()};j.stop=function(){p&&clearTimeout(p);p=b};function n(){var r=a(),q=o(m);if(r!==m){l(m=r,q);$(e).trigger(c)}else{if(q!==m){location.href=location.href.replace(/#.*/,"")+q}}p=setTimeout(n,$.fn[c].delay)}$.browser.msie&&!d&&(function(){var q,r;j.start=function(){if(!q){r=$.fn[c].src;r=r&&r+a();q=$('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){r||l(a());n()}).attr("src",r||"javascript:0").insertAfter("body")[0].contentWindow;h.onpropertychange=function(){try{if(event.propertyName==="title"){q.document.title=h.title}}catch(s){}}}};j.stop=k;o=function(){return a(q.location.href)};l=function(v,s){var u=q.document,t=$.fn[c].domain;if(v!==s){u.title=h.title;u.open();t&&u.write('<script>document.domain="'+t+'"<\/script>');u.close();q.location.hash=v}}})();return j})()})(jQuery,this);

/**
 * jQuery Masonry v2.0.110825
 * A dynamic layout plugin for jQuery
 * The flip-side of CSS Floats
 * http://masonry.desandro.com
 *
 * Licensed under the MIT license.
 * Copyright 2011 David DeSandro
 */
(function(a,b,c){var d=b.event,e;d.special.smartresize={setup:function(){b(this).bind("resize",d.special.smartresize.handler)},teardown:function(){b(this).unbind("resize",d.special.smartresize.handler)},handler:function(a,b){var c=this,d=arguments;a.type="smartresize",e&&clearTimeout(e),e=setTimeout(function(){jQuery.event.handle.apply(c,d)},b==="execAsap"?0:100)}},b.fn.smartresize=function(a){return a?this.bind("smartresize",a):this.trigger("smartresize",["execAsap"])},b.Mason=function(a,c){this.element=b(c),this._create(a),this._init()};var f=["position","height"];b.Mason.settings={isResizable:!0,isAnimated:!1,animationOptions:{queue:!1,duration:500},gutterWidth:0,isRTL:!1,isFitWidth:!1},b.Mason.prototype={_filterFindBricks:function(a){var b=this.options.itemSelector;return b?a.filter(b).add(a.find(b)):a},_getBricks:function(a){var b=this._filterFindBricks(a).css({position:"absolute"}).addClass("masonry-brick");return b},_create:function(c){this.options=b.extend(!0,{},b.Mason.settings,c),this.styleQueue=[],this.reloadItems();var d=this.element[0].style;this.originalStyle={};for(var e=0,g=f.length;e<g;e++){var h=f[e];this.originalStyle[h]=d[h]||""}this.element.css({position:"relative"}),this.horizontalDirection=this.options.isRTL?"right":"left",this.offset={};var i=b(document.createElement("div"));this.element.prepend(i),this.offset.y=Math.round(i.position().top),this.options.isRTL?(i.css({"float":"right",display:"inline-block"}),this.offset.x=Math.round(this.element.outerWidth()-i.position().left)):this.offset.x=Math.round(i.position().left),i.remove();var j=this;setTimeout(function(){j.element.addClass("masonry")},0),this.options.isResizable&&b(a).bind("smartresize.masonry",function(){j.resize()})},_init:function(a){this._getColumns("masonry"),this._reLayout(a)},option:function(a,c){b.isPlainObject(a)&&(this.options=b.extend(!0,this.options,a))},layout:function(a,c){var d,e,f,g,h,i;for(var j=0,k=a.length;j<k;j++){d=b(a[j]),e=Math.ceil(d.outerWidth(!0)/this.columnWidth),e=Math.min(e,this.cols);if(e===1)this._placeBrick(d,this.colYs);else{f=this.cols+1-e,g=[];for(i=0;i<f;i++)h=this.colYs.slice(i,i+e),g[i]=Math.max.apply(Math,h);this._placeBrick(d,g)}}var l={};l.height=Math.max.apply(Math,this.colYs)-this.offset.y,this.options.isFitWidth&&(l.width=this.cols*this.columnWidth-this.options.gutterWidth),this.styleQueue.push({$el:this.element,style:l});var m=this.isLaidOut?this.options.isAnimated?"animate":"css":"css",n=this.options.animationOptions,o;for(j=0,k=this.styleQueue.length;j<k;j++)o=this.styleQueue[j],o.$el[m](o.style,n);this.styleQueue=[],c&&c.call(a),this.isLaidOut=!0},_getColumns:function(){var a=this.options.isFitWidth?this.element.parent():this.element,b=a.width();this.columnWidth=this.options.columnWidth||this.$bricks.outerWidth(!0)||b,this.columnWidth+=this.options.gutterWidth,this.cols=Math.floor((b+this.options.gutterWidth)/this.columnWidth),this.cols=Math.max(this.cols,1)},_placeBrick:function(a,b){var c=Math.min.apply(Math,b),d=0;for(var e=0,f=b.length;e<f;e++)if(b[e]===c){d=e;break}var g={top:c};g[this.horizontalDirection]=this.columnWidth*d+this.offset.x,this.styleQueue.push({$el:a,style:g});var h=c+a.outerHeight(!0),i=this.cols+1-f;for(e=0;e<i;e++)this.colYs[d+e]=h},resize:function(){var a=this.cols;this._getColumns("masonry"),this.cols!==a&&this._reLayout()},_reLayout:function(a){var b=this.cols;this.colYs=[];while(b--)this.colYs.push(this.offset.y);this.layout(this.$bricks,a)},reloadItems:function(){this.$bricks=this._getBricks(this.element.children())},reload:function(a){this.reloadItems(),this._init(a)},appended:function(a,b,c){if(b){this._filterFindBricks(a).css({top:this.element.height()});var d=this;setTimeout(function(){d._appended(a,c)},1)}else this._appended(a,c)},_appended:function(a,b){var c=this._getBricks(a);this.$bricks=this.$bricks.add(c),this.layout(c,b)},remove:function(a){this.$bricks=this.$bricks.not(a),a.remove()},destroy:function(){this.$bricks.removeClass("masonry-brick").each(function(){this.style.position="",this.style.top="",this.style.left=""});var c=this.element[0].style;for(var d=0,e=f.length;d<e;d++){var g=f[d];c[g]=this.originalStyle[g]}this.element.unbind(".masonry").removeClass("masonry").removeData("masonry"),b(a).unbind(".masonry")}},b.fn.imagesLoaded=function(a){function h(){--d<=0&&this.src!==f&&(setTimeout(g),b.unbind("load error",h))}function g(){a.call(e,b)}var b=this.find("img"),d=b.length,e=this,f="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";d||g(),b.bind("load error",h).each(function(){if(this.complete||this.complete===c){var a=this.src;this.src=f,this.src=a}});return this};var g=function(a){this.console&&console.error(a)};b.fn.masonry=function(a){if(typeof a=="string"){var c=Array.prototype.slice.call(arguments,1);this.each(function(){var d=b.data(this,"masonry");if(!d)g("cannot call methods on masonry prior to initialization; attempted to call method '"+a+"'");else{if(!b.isFunction(d[a])||a.charAt(0)==="_"){g("no such method '"+a+"' for masonry instance");return}d[a].apply(d,c)}})}else this.each(function(){var c=b.data(this,"masonry");c?(c.option(a||{}),c._init()):b.data(this,"masonry",new b.Mason(a,this))});return this}})(window,jQuery);


/**
 * jQuery.ScrollTo - Easy element scrolling using jQuery.
 * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 5/25/2009
 * @author Ariel Flesler
 * @version 1.4.2
 *
 * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
 */
;(function(d){var k=d.scrollTo=function(a,i,e){d(window).scrollTo(a,i,e)};k.defaults={axis:'xy',duration:parseFloat(d.fn.jquery)>=1.3?0:1};k.window=function(a){return d(window)._scrollable()};d.fn._scrollable=function(){return this.map(function(){var a=this,i=!a.nodeName||d.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!i)return a;var e=(a.contentWindow||a).document||a.ownerDocument||a;return d.browser.safari||e.compatMode=='BackCompat'?e.body:e.documentElement})};d.fn.scrollTo=function(n,j,b){if(typeof j=='object'){b=j;j=0}if(typeof b=='function')b={onAfter:b};if(n=='max')n=9e9;b=d.extend({},k.defaults,b);j=j||b.speed||b.duration;b.queue=b.queue&&b.axis.length>1;if(b.queue)j/=2;b.offset=p(b.offset);b.over=p(b.over);return this._scrollable().each(function(){var q=this,r=d(q),f=n,s,g={},u=r.is('html,body');switch(typeof f){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(f)){f=p(f);break}f=d(f,this);case'object':if(f.is||f.style)s=(f=d(f)).offset()}d.each(b.axis.split(''),function(a,i){var e=i=='x'?'Left':'Top',h=e.toLowerCase(),c='scroll'+e,l=q[c],m=k.max(q,i);if(s){g[c]=s[h]+(u?0:l-r.offset()[h]);if(b.margin){g[c]-=parseInt(f.css('margin'+e))||0;g[c]-=parseInt(f.css('border'+e+'Width'))||0}g[c]+=b.offset[h]||0;if(b.over[h])g[c]+=f[i=='x'?'width':'height']()*b.over[h]}else{var o=f[h];g[c]=o.slice&&o.slice(-1)=='%'?parseFloat(o)/100*m:o}if(/^\d+$/.test(g[c]))g[c]=g[c]<=0?0:Math.min(g[c],m);if(!a&&b.queue){if(l!=g[c])t(b.onAfterFirst);delete g[c]}});t(b.onAfter);function t(a){r.animate(g,j,b.easing,a&&function(){a.call(this,n,b)})}}).end()};k.max=function(a,i){var e=i=='x'?'Width':'Height',h='scroll'+e;if(!d(a).is('html,body'))return a[h]-d(a)[e.toLowerCase()]();var c='client'+e,l=a.ownerDocument.documentElement,m=a.ownerDocument.body;return Math.max(l[h],m[h])-Math.min(l[c],m[c])};function p(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery);

/*
 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 *
 * Uses the built in easing capabilities added In jQuery 1.1
 * to offer multiple easing options
 *
 * TERMS OF USE - jQuery Easing
 * 
 * Open source under the BSD License. 
 * 
 * Copyright Â© 2008 George McGinley Smith
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this list of 
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list 
 * of conditions and the following disclaimer in the documentation and/or other materials 
 * provided with the distribution.
 * 
 * Neither the name of the author nor the names of contributors may be used to endorse 
 * or promote products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE. 
 *
*/

// t: current time, b: begInnIng value, c: change In value, d: duration
jQuery.easing['jswing'] = jQuery.easing['swing'];

jQuery.extend( jQuery.easing,
{
	def: 'easeOutQuad',
	swing: function (x, t, b, c, d) {
		//alert(jQuery.easing.default);
		return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
	},
	easeInQuad: function (x, t, b, c, d) {
		return c*(t/=d)*t + b;
	},
	easeOutQuad: function (x, t, b, c, d) {
		return -c *(t/=d)*(t-2) + b;
	},
	easeInOutQuad: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},
	easeInCubic: function (x, t, b, c, d) {
		return c*(t/=d)*t*t + b;
	},
	easeOutCubic: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	},
	easeInOutCubic: function (x, 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;
	},
	easeInQuart: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t + b;
	},
	easeOutQuart: function (x, t, b, c, d) {
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},
	easeInOutQuart: function (x, 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;
	},
	easeInQuint: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t*t + b;
	},
	easeOutQuint: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},
	easeInOutQuint: function (x, 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;
	},
	easeInSine: function (x, t, b, c, d) {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},
	easeOutSine: function (x, t, b, c, d) {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	},
	easeInOutSine: function (x, t, b, c, d) {
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},
	easeInExpo: function (x, t, b, c, d) {
		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	},
	easeOutExpo: function (x, t, b, c, d) {
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},
	easeInOutExpo: function (x, 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;
	},
	easeInCirc: function (x, t, b, c, d) {
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	},
	easeOutCirc: function (x, t, b, c, d) {
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	},
	easeInOutCirc: function (x, 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;
	},
	easeInElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		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;
	},
	easeOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		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;
	},
	easeInOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
		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 -.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 )*.5 + c + b;
	},
	easeInBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},
	easeOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},
	easeInOutBack: function (x, 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;
	},
	easeInBounce: function (x, t, b, c, d) {
		return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
	},
	easeOutBounce: function (x, 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 + .75) + b;
		} else if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
		}
	},
	easeInOutBounce: function (x, t, b, c, d) {
		if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
		return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
	}
});

/*
 *
 * TERMS OF USE - EASING EQUATIONS
 * 
 * Open source under the BSD License. 
 * 
 * Copyright Â© 2001 Robert Penner
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this list of 
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list 
 * of conditions and the following disclaimer in the documentation and/or other materials 
 * provided with the distribution.
 * 
 * Neither the name of the author nor the names of contributors may be used to endorse 
 * or promote products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE. 
 *
 */	

/**
 * jQuery xcolor plugin
 * Copyright (c) 2010, Robert Eisele (robert@xarg.org)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * Date: 06/21/2010
 *
 * @author Robert Eisele
 * @version 1.5
 *
 * @see http://www.xarg.org/project/jquery-color-plugin-xcolor/
 **/

(function ($) {

	// http://www.w3.org/TR/css3-color/#svg-color
	var color_names = {
		transparent: 16777216,
		aliceblue: 15792383,
		antiquewhite: 16444375,
		aqua: 65535,
		aquamarine: 8388564,
		azure: 15794175,
		beige: 16119260,
		bisque: 16770244,
		black: 0,
		blanchedalmond: 16772045,
		blue: 255,
		blueviolet: 9055202,
		brown: 10824234,
		burlywood: 14596231,
		cadetblue: 6266528,
		chartreuse: 8388352,
		chocolate: 13789470,
		coral: 16744272,
		cornflowerblue: 6591981,
		cornsilk: 16775388,
		crimson: 14423100,
		cyan: 65535,
		darkblue: 139,
		darkcyan: 35723,
		darkgoldenrod: 12092939,
		darkgray: 11119017,
		darkgreen: 25600,
		darkgrey: 11119017,
		darkkhaki: 12433259,
		darkmagenta: 9109643,
		darkolivegreen: 5597999,
		darkorange: 16747520,
		darkorchid: 10040012,
		darkred: 9109504,
		darksalmon: 15308410,
		darkseagreen: 9419919,
		darkslateblue: 4734347,
		darkslategray: 3100495,
		darkslategrey: 3100495,
		darkturquoise: 52945,
		darkviolet: 9699539,
		deeppink: 16716947,
		deepskyblue: 49151,
		dimgray: 6908265,
		dimgrey: 6908265,
		dodgerblue: 2003199,
		firebrick: 11674146,
		floralwhite: 16775920,
		forestgreen: 2263842,
		fuchsia: 16711935,
		gainsboro: 14474460,
		ghostwhite: 16316671,
		gold: 16766720,
		goldenrod: 14329120,
		gray: 8421504,
		green: 32768,
		greenyellow: 11403055,
		grey: 8421504,
		honeydew: 15794160,
		hotpink: 16738740,
		indianred: 13458524,
		indigo: 4915330,
		ivory: 16777200,
		khaki: 15787660,
		lavender: 15132410,
		lavenderblush: 16773365,
		lawngreen: 8190976,
		lemonchiffon: 16775885,
		lightblue: 11393254,
		lightcoral: 15761536,
		lightcyan: 14745599,
		lightgoldenrodyellow: 16448210,
		lightgray: 13882323,
		lightgreen: 9498256,
		lightgrey: 13882323,
		lightpink: 16758465,
		lightsalmon: 16752762,
		lightseagreen: 2142890,
		lightskyblue: 8900346,
		lightslategray: 7833753,
		lightslategrey: 7833753,
		lightsteelblue: 11584734,
		lightyellow: 16777184,
		lime: 65280,
		limegreen: 3329330,
		linen: 16445670,
		magenta: 16711935,
		maroon: 8388608,
		mediumaquamarine: 6737322,
		mediumblue: 205,
		mediumorchid: 12211667,
		mediumpurple: 9662683,
		mediumseagreen: 3978097,
		mediumslateblue: 8087790,
		mediumspringgreen: 64154,
		mediumturquoise: 4772300,
		mediumvioletred: 13047173,
		midnightblue: 1644912,
		mintcream: 16121850,
		mistyrose: 16770273,
		moccasin: 16770229,
		navajowhite: 16768685,
		navy: 128,
		oldlace: 16643558,
		olive: 8421376,
		olivedrab: 7048739,
		orange: 16753920,
		orangered: 16729344,
		orchid: 14315734,
		palegoldenrod: 15657130,
		palegreen: 10025880,
		paleturquoise: 11529966,
		palevioletred: 14381203,
		papayawhip: 16773077,
		peachpuff: 16767673,
		peru: 13468991,
		pink: 16761035,
		plum: 14524637,
		powderblue: 11591910,
		purple: 8388736,
		red: 16711680,
		rosybrown: 12357519,
		royalblue: 4286945,
		saddlebrown: 9127187,
		salmon: 16416882,
		sandybrown: 16032864,
		seagreen: 3050327,
		seashell: 16774638,
		sienna: 10506797,
		silver: 12632256,
		skyblue: 8900331,
		slateblue: 6970061,
		slategray: 7372944,
		slategrey: 7372944,
		snow: 16775930,
		springgreen: 65407,
		steelblue: 4620980,
		tan: 13808780,
		teal: 32896,
		thistle: 14204888,
		tomato: 16737095,
		turquoise: 4251856,
		violet: 15631086,
		wheat: 16113331,
		white: 16777215,
		whitesmoke: 16119285,
		yellow: 16776960,
		yellowgreen: 10145074
	};

	/**
     * @constructor
     */
	function xColor(color) {

		function _normalize(n, s) {

			var m;

			if (void 0 !== n) {
				n = parseFloat(n);
			}

			if (void 0 === s) {
				s = 255;
				m = 255;
			} else if (1 === s) {

				if (void 0 === n || 1 === n) {
					return 1;
				}
				s = 100;
				m = 1;
			} else {
				m = s;
			}

			if (isNaN(n) || n <= 0) {
				return 0;
			}

			if (s < n) {
				return m;
			}

			if (n < 1 || 1 === s) {
				if (m === 1) {
					return n;
				} else {
					return (n * m) | 0;
				}
			}
			return n * m / s;
		}

		function _hsl(h,s,l) {

			h = _normalize(h, 360) / 360;
			s = _normalize(s, 1);
			l = _normalize(l, 1);

			if (0 === s) {
				l = Math.round(l * 255);
				return [l, l, l];
			}

			function _hue(v1, v2, h) {
				if (h < 0) ++h;
				if (h > 1) --h;
				if (6 * h < 1) return v1 + (v2 - v1) * 6 * h;
				if (2 * h < 1) return v2;
				if (3 * h < 2) return v1 + (v2 - v1) * (4 - 6 * h);
				return v1;
			}

			var v = l < 0.5 ? (l + l * s) : (l + s - l * s);
			var m = l + l - v;

			return [
			Math.round(255 *_hue(m, v, h + 1 / 3)),
			Math.round(255 *_hue(m, v, h)),
			Math.round(255 *_hue(m, v, h - 1 / 3)) ];
		}

		function _hsv(h,s,v) {

			h = _normalize(h, 360) / 60;
			s = _normalize(s, 1);
			v = _normalize(v, 1);

			var hi = h|0;
			var f = h - hi;

			f = (h & 1) ? f : 1 - f;

			var m = Math.round(255 * (v * (1 - s)));
			var n = Math.round(255 * (v * (1 - s * f)));

			v = Math.round(255 * v);

			switch (hi) {
				case 6:
				case 0:
					return [v, n, m];
				case 1:
					return [n, v, m];
				case 2:
					return [m, v, n];
				case 3:
					return [m, n, v];
				case 4:
					return [n, m, v];
				case 5:
					return [v, m, n];
			}
		}

		this.setColor = function (color) {

			this.success = true;

			if (typeof color === "number") {

				this.a =((color >> 24) & 0xff) / 255;
				this.r = (color >> 16) & 0xff;
				this.g = (color >>  8) & 0xff;
				this.b = (color      ) & 0xff;
				return;
			}

			while (typeof color === "object") {

				if (0 in color && 1 in color && 2 in color) {
					this.a = _normalize(color[3], 1);
					this.r = _normalize(color[0]);
					this.g = _normalize(color[1]);
					this.b = _normalize(color[2]);
					return;
				} else if ('r' in color && 'g' in color && 'b' in color) {
					this.a = _normalize(color.a, 1);
					this.r = _normalize(color.r);
					this.g = _normalize(color.g);
					this.b = _normalize(color.b);
					return;
				} else if ('h' in color && 's' in color) {

					var rgb;

					if ('l' in color) {
						rgb = _hsl(color.h, color.s, color.l);
					} else if ('v' in color) {
						rgb = _hsv(color.h, color.s, color.v);
					} else if ('b' in color) {
						rgb = _hsv(color.h, color.s, color.b);
					} else {
						break;
					}

					this.a = _normalize(color.a, 1);
					this.r = rgb[0];
					this.g = rgb[1];
					this.b = rgb[2];
					return;
				}
				break;
			}

			if (typeof color !== "string") {
				this.success = false;
				return;
			}

			color = color.toLowerCase().replace(/[^a-z0-9,.()#%]/g, '');

			var part, c;

			if (color in color_names) {

				c = color_names[color];

				this.a =(!((c >> 24) & 0xff))|0;
				this.r =  ((c >> 16) & 0xff);
				this.g =  ((c >>  8) & 0xff);
				this.b =  ((c      ) & 0xff);
				return;
			}

			// 53892983
			if (part = /^([1-9]\d*)$/.exec(color)) {

				c = parseInt(part[1], 10);

				this.a =(((c >> 24) & 0xff) || 255) / 255;
				this.r = ((c >> 16) & 0xff);
				this.g = ((c >>  8) & 0xff);
				this.b = ((c      ) & 0xff);
				return;
			}

			// #ff9000, #ff0000
			if (part = /^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/.exec(color)) {
				this.a = 1;
				this.r = parseInt(part[1], 16);
				this.g = parseInt(part[2], 16);
				this.b = parseInt(part[3], 16);
				return;
			}

			// #f00, fff
			if (part = /^#?([0-9a-f])([0-9a-f])([0-9a-f])$/.exec(color)) {
				this.a = 1;
				this.r = parseInt(part[1] + part[1], 16);
				this.g = parseInt(part[2] + part[2], 16);
				this.b = parseInt(part[3] + part[3], 16);
				return;
			}

			// rgb(1, 234, 56)
			if (part = /^rgba?\((\d{1,3}),(\d{1,3}),(\d{1,3})(,([0-9.]+))?\)$/.exec(color)) {
				this.a = _normalize(part[5], 1);
				this.r = _normalize(part[1]);
				this.g = _normalize(part[2]);
				this.b = _normalize(part[3]);
				return;
			}

			// rgb(66%, 55%, 44%) in [0,100]%, [0,100]%, [0,100]%
			if (part = /^rgba?\(([0-9.]+\%),([0-9.]+\%),([0-9.]+\%)(,([0-9.]+)\%?)?\)$/.exec(color)) {
				this.a = _normalize(part[5], 1);
				this.r = Math.round(_normalize(part[1], 100) * 2.55);
				this.g = Math.round(_normalize(part[2], 100) * 2.55);
				this.b = Math.round(_normalize(part[3], 100) * 2.55);
				return;
			}

			// hsv(64, 40, 16) in [0, 360], [0,100], [0,100]
			if (part = /^hs([bvl])a?\((\d{1,3}),(\d{1,3}),(\d{1,3})(,([0-9.]+))?\)$/.exec(color)) {
				var func;
				if (part[1] === "l") {
					func = _hsl;
				} else {
					func = _hsv;
				}

				c = func(parseInt(part[2], 10), parseInt(part[3], 10), parseInt(part[4], 10));

				this.a = _normalize(part[6], 1);
				this.r = c[0];
				this.g = c[1];
				this.b = c[2];
				return;
			}

			// 1, 234, 56
			if (part = /^(\d{1,3}),(\d{1,3}),(\d{1,3})(,([0-9.]+))?$/.exec(color)) {
				this.a = _normalize(part[5], 1);
				this.r = _normalize(part[1]);
				this.g = _normalize(part[2]);
				this.b = _normalize(part[3]);
				return;
			}

			this.success = false;
		}

		this.getColor = function (type) {

			if (void 0 !== type) switch (type.toLowerCase()) {
				case "rgb":
					return this.getRGB();
				case "hsv":
				case "hsb":
					return this.getHSV();
				case "hsl":
					return this.getHSL();
				case "int":
					return this.getInt();
				case "array":
					return this.getArray();
				case "fraction":
					return this.getFraction();
				case "css":
				case "style":
					return this.getCSS();
				case "name":
					return this.getName();
			}
			return this.getHex();
		}

		this.getRGB = function () {

			if (this.success) {

				return {
					r: this.r,
					g: this.g,
					b: this.b,
					a: this.a
				};
			}
			return null;
		}

		this.getCSS = function () {

			if (this.success) {

				if (this.a == 1) {
					return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
				}
				return 'rgba(' + this.r + ', ' + this.g + ', ' + this.b + ', ' + this.a + ')';
			}
			return null;
		}

		this.getArray = function () {

			if (this.success) {
				return [this.r, this.g, this.b, this.a * 100 | 0];
			}
			return null;
		}

		this.getName = function () {

			if (this.success) {

				var lowest = null;
				var lowest_ndx;

				var table = color_names;

				var a = this.getHSL();

				for (var i in table) {

					/* We do not handle transparency */
					var b = new xColor(table[i]).getHSL();

					var tmp = Math.sqrt(0.5 * (a.h - b.h) * (a.h - b.h) + 0.5 * (a.s - b.s) * (a.s - b.s) + (a.l - b.l) * (a.l - b.l));

					if (null === lowest || tmp < lowest) {
						lowest = tmp;
						lowest_ndx = i;
					}
				}
				return lowest_ndx;
			}
			return null;
		}

		this.getFraction = function () {

			if (this.success) {

				return {
					r: this.r / 255,
					g: this.g / 255,
					b: this.b / 255,
					a: this.a
				};
			}
			return null;
		}

		this.getHSL = function () {

			// inspiration: http://130.113.54.154/~monger/hsl-rgb.html
			if (this.success) {

				var r = this.r / 255;
				var g = this.g / 255;
				var b = this.b / 255;

				var min = Math.min(r, g, b);
				var max = Math.max(r, g, b);
				var delta = max - min;

				var h, s, l = (max + min) / 2;

				if (0 == delta) {
					h = 0;
					s = 0;
				} else {

					if (max == r) {
						h = (g - b) / delta;
					} else if (max == g) {
						h = 2 + (b - r) / delta;
					} else if (max == b) {
						h = 4 + (r - g) / delta;
					}

					if (h < 0) {
						h+= 6;
					}
					s = delta / (l < 0.5 ? max + min : 2 - max - min);
				}
				return {
					h: Math.round(h * 60),
					s: Math.round(s * 100),
					l: Math.round(l * 100),
					a: this.a
				};
			}
			return null;
		}

		this.getHSV = function () {

			if (this.success) {

				var r = this.r / 255;
				var g = this.g / 255;
				var b = this.b / 255;

				var min = Math.min(r, g, b);
				var max = Math.max(r, g, b);
				var delta = max - min;

				var h, s, v = max;

				if (0 == delta) {
					h = 0;
					s = 0;
				} else {
					s = delta / max;

					delta*= 6;

					var dR = .5 + (max - r) / delta;
					var dG = .5 + (max - g) / delta;
					var dB = .5 + (max - b) / delta;

					if (r == max) {
						h = dB - dG;
					} else if (g == max) {
						h = 1 / 3 + dR - dB;
					} else if (b == max) {
						h = 2 / 3 + dG - dR;
					}

					if (h < 0) ++h;
					if (h > 1) --h;
				}

				return {
					h: Math.round(h * 360),
					s: Math.round(s * 100),
					v: Math.round(v * 100),
					a: this.a
				};
			}
			return null;
		}

		this.getHex = function () {

			if (this.success) {

				var chars = "0123456789abcdef";

				var r1 = this.r >> 4;
				var g1 = this.g >> 4;
				var b1 = this.b >> 4;

				var r2 = this.r & 0xf;
				var g2 = this.g & 0xf;
				var b2 = this.b & 0xf;

				if (0 === ((r1 ^ r2) | (g1 ^ g2) | (b1 ^ b2))) {
					return '#' + chars.charAt(r1) + chars.charAt(g1) + chars.charAt(b1);
				}
				return '#'
				+ chars.charAt(r1) + chars.charAt(r2)
				+ chars.charAt(g1) + chars.charAt(g2)
				+ chars.charAt(b1) + chars.charAt(b2);
			}
			return null;
		}

		this.getInt = function (alpha) {

			if (this.success) {
				if (void 0 !== alpha) {
					return ((this.a * 100 | 0) << 24 ^ this.r << 16 ^ this.g << 8 ^ this.b);
				}
				return (this.r << 16 ^ this.g << 8 ^ this.b) & 0xffffff;
			}
			return null;
		}

		this.toString = function () {
			return this.getHex();
		}

		this.setColor(color);
	}

	$.each(['color', 'backgroundColor', 'borderColor', 'borderTopColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'outlineColor'], function(i, attr) {

		$.fx.step[attr] = function(fx) {

			if (fx.xinit === void 0) {

				if (typeof fx.end === "string" && -1 !== fx.end.indexOf(";")) {

					var x, arr = fx.end.split(";");

					if (arr.length > 2) {

						for (x in arr) {
							if (-1 === arr[x].indexOf('native')) {
								arr[x] = new xColor(arr[x]);
							} else {
								arr[x] = findColor(fx.elem, attr);
							}
						}
						fx.start = null;
						fx.end = arr;
					} else {
						fx.start = new xColor(arr[0]);
						fx.end = new xColor(arr[1]);
					}
				} else {
					fx.start = findColor(fx.elem, attr);
					fx.end = new xColor(fx.end);
				}

				fx.xinit = 1;
			}

			var S = fx.start;
			var E = fx.end;
			var P = fx.pos;

			if (null === S) {
				var m = P * (E.length - 1), n = P < 1 ? m | 0 : E.length - 2;
				S = E[n];
				E = E[n + 1];
				P = m - n;
			}

			if ($.support.opacity) {
				fx.elem.style[attr] = "rgba("
				+ ((S.r + (E.r - S.r) * P)|0) + ","
				+ ((S.g + (E.g - S.g) * P)|0) + ","
				+ ((S.b + (E.b - S.b) * P)|0) + ","
				+ ((S.a + (E.a - S.a) * P)) + ")";
			} else {
				fx.elem.style[attr] = "rgb("
				+ ((S.r + (E.r - S.r) * P)|0) + ","
				+ ((S.g + (E.g - S.g) * P)|0) + ","
				+ ((S.b + (E.b - S.b) * P)|0) + ")";
			}
		}
	});

	function findColor(elem, attr) {

		var color = "";

		do {
			color = $.curCSS(elem, attr);

			if ("" !== color && "transparent" !== color && "rgba(0, 0, 0, 0)" !== color || $.nodeName(elem, "body")) break;

		} while (elem = elem.parentNode);

		if ("" === color) {

			if ($.support.opacity) {
				color = "transparent";
			} else if ("backgroundColor" === attr) {
				color = "white";
			} else {
				color = "black";
			}
		}
		return new xColor(color);
	}

	/**
     * @constructor
     */
	function xColorMix() {

		this.test = function (col) {

			var c = new xColor(col);

			if (c.success) {
				return c;
			}
			return null;
		}

		this.red = function (col) {

			var c = new xColor(col);

			if (c.success) {
				c.g = 0xff;
				c.b = 0xff;
				return c;
			}
			return null;
		}

		this.blue = function (col) {

			var c = new xColor(col);

			if (c.success) {
				c.r = 0xff;
				c.g = 0xff;
				return c;
			}
			return null;
		}

		this.green = function (col) {

			var c = new xColor(col);

			if (c.success) {
				c.r = 0xff;
				c.b = 0xff;
				return c;
			}
			return null;
		}

		this.sepia = function(col) {

			var c = new xColor(col);

			// Microsoft's sepia function http://msdn.microsoft.com/en-us/magazine/cc163866.aspx
			if (c.success) {

				var r = c.r, g = c.g, b = c.b;

				c.r = Math.round(r * 0.393 + g * 0.769 + b * 0.189);
				c.g = Math.round(r * 0.349 + g * 0.686 + b * 0.168);
				c.b = Math.round(r * 0.272 + g * 0.534 + b * 0.131);

				return c;
			}
			return null;
		}

		this.random = function () {

			return new xColor([
				(255 * Math.random())|0,
				(255 * Math.random())|0,
				(255 * Math.random())|0
				]);
		}

		this.inverse = function (col) {

			var c = new xColor(col);

			if (c.success) {
				c.r^= 0xff;
				c.g^= 0xff;
				c.b^= 0xff;
				return c;
			}
			return null;
		}

		this.opacity = function (x, y, o) {

			var a = new xColor(x);
			var b = new xColor(y);

			if (a.success & b.success) {

				if (o > 1) {
					o/= 100;
				}

				o = Math.max(o - 1 + b.a, 0);

				a.r = Math.round((b.r - a.r) * o + a.r);
				a.g = Math.round((b.g - a.g) * o + a.g);
				a.b = Math.round((b.b - a.b) * o + a.b);

				return a;
			}
			return null;
		}

		this.greyfilter = function (col, formula) {

			var v, c = new xColor(col);

			if (c.success) {
				switch (formula) {
					case 1:
						// My own formula
						v = .35 + 13 * (c.r + c.g + c.b) / 60;
						break;
					case 2:
						// Sun's formula: (1 - avg) / (100 / 35) + avg)
						v = (13 * (c.r + c.g + c.b) + 5355) / 60;
						break;
					default:
						v = c.r * .3 + c.g * .59 + c.b * .11;
				}
				c.r = c.g = c.b = Math.min(v|0, 255);

				return c;
			}
			return null;
		}

		this.webround = function (col) {

			var c = new xColor(col);

			if (c.success) {
				if ((c.r+= 0x33 - c.r % 0x33) > 0xff) c.r = 0xff;
				if ((c.g+= 0x33 - c.g % 0x33) > 0xff) c.g = 0xff;
				if ((c.b+= 0x33 - c.b % 0x33) > 0xff) c.b = 0xff;
				return c;
			}
			return null;
		}

		this.distance = function (x, y) {

			var a = new xColor(x);
			var b = new xColor(y);

			if (a.success & b.success) {
				// Approximation attempt of http://www.compuphase.com/cmetric.htm
				return Math.sqrt(3 * (b.r - a.r) * (b.r - a.r) + 4 * (b.g - a.g) * (b.g - a.g) + 2 * (b.b - a.b) * (b.b - a.b));
			}
			return null;
		}

		this.readable = function (bg, col) {

			var a = new xColor(col);
			var b = new xColor(bg);

			if (a.success & b.success) {
				return (
					(b.r - a.r) * (b.r - a.r) +
					(b.g - a.g) * (b.g - a.g) +
					(b.b - a.b) * (b.b - a.b)) > 0x28A4;
			}
			return null;
		}

		this.combine = function (x, y) {

			var a = new xColor(x);
			var b = new xColor(y);

			if (a.success & b.success) {
				a.r^= b.r;
				a.g^= b.g;
				a.b^= b.b;
				return a;
			}
			return null;
		}

		this.breed = function (x, y) {

			var a = new xColor(x);
			var b = new xColor(y);

			var mask = 0;

			if (a.success & b.success) {

				for (var i = 0; i < 6; ++i) {
					if (Math.random() < .5) {
						mask|= 0x0f << (i << 2);
					}
				}

				a.r = (a.r & ((mask >> 0x10) & 0xff)) | (b.r & (((mask >> 0x10) & 0xff) ^ 0xff));
				a.g = (a.g & ((mask >> 0x08) & 0xff)) | (b.g & (((mask >> 0x08) & 0xff) ^ 0xff));
				a.b = (a.b & ((mask >> 0x00) & 0xff)) | (b.b & (((mask >> 0x00) & 0xff) ^ 0xff));
				return a;
			}
			return null;
		}

		this.additive = function (x, y) {

			var a = new xColor(x);
			var b = new xColor(y);

			if (a.success & b.success) {

				if ((a.r+= b.r) > 0xff) a.r = 0xff;
				if ((a.g+= b.g) > 0xff) a.g = 0xff;
				if ((a.b+= b.b) > 0xff) a.b = 0xff;

				return a;
			}
			return null;
		}

		this.subtractive = function (x, y) {

			var a = new xColor(x);
			var b = new xColor(y);

			if (a.success & b.success) {

				if ((a.r+= b.r - 0xff) < 0) a.r = 0;
				if ((a.g+= b.g - 0xff) < 0) a.g = 0;
				if ((a.b+= b.b - 0xff) < 0) a.b = 0;

				return a;
			}
			return null;
		}

		this.subtract = function (x, y) {

			var a = new xColor(x);
			var b = new xColor(y);

			if (a.success & b.success) {

				if ((a.r-= b.r) < 0) a.r = 0;
				if ((a.g-= b.g) < 0) a.g = 0;
				if ((a.b-= b.b) < 0) a.b = 0;

				return a;
			}
			return null;
		}

		this.multiply = function (x, y) {

			var a = new xColor(x);
			var b = new xColor(y);

			if (a.success & b.success) {
				a.r = (a.r / 255 * b.r)|0;
				a.g = (a.g / 255 * b.g)|0;
				a.b = (a.b / 255 * b.b)|0;
				return a;
			}
			return null;
		}

		this.average = function (x, y) {

			var a = new xColor(x);
			var b = new xColor(y);

			if (a.success & b.success) {
				a.r = (a.r + b.r) >> 1;
				a.g = (a.g + b.g) >> 1;
				a.b = (a.b + b.b) >> 1;
				return a;
			}
			return null;
		}

		this.triad = function (col) {

			var c = new xColor(col);

			if (c.success) {

				return [c,
				new xColor([c.b, c.r, c.g]),
				new xColor([c.g, c.b, c.r])];
			}
			return null;
		}

		this.tetrad = function (col) {

			var c = new xColor(col);

			if (c.success) {

				return [c,
				new xColor([c.b, c.r, c.b]),
				new xColor([c.b, c.g, c.r]),
				new xColor([c.r, c.b, c.r])];
			}
			return null;
		}

		this.gradientlevel = function (x, y, level, deg) {

			if (level > deg) return null;

			var a = new xColor(x);
			var b = new xColor(y);

			if (a.success & b.success) {

				a.r = (a.r + ((b.r - a.r) / deg) * level)|0;
				a.g = (a.g + ((b.g - a.g) / deg) * level)|0;
				a.b = (a.b + ((b.b - a.b) / deg) * level)|0;

				return a;
			}
			return null;
		}

		this.gradientarray = function (arr, ndx, size) {

			if (ndx > size) return null;

			var e = (ndx * (arr.length - 1) / size)|0;
			var m = (ndx - size * e / (arr.length - 1)) / size;

			var a = new xColor(arr[e]);
			var b = new xColor(arr[e + 1]);

			if (a.success & b.success) {

				a.r = (a.r + arr.length * (b.r - a.r) * m)|0;
				a.g = (a.g + arr.length * (b.g - a.g) * m)|0;
				a.b = (a.b + arr.length * (b.b - a.b) * m)|0;

				return a;
			}
			return null;
		}

		this.nearestname = function (a) {

			a = new xColor(a);

			if (a.success) {
				return a.getName();
			}
			return null;
		}

		this.darken = function (col, by, shade) {

			if (by === void 0) {
				by = 1;
			} else if (by < 0) return this.lighten(col, -by, shade);

			if (shade === void 0) {
				shade = 32;
			}

			var c = new xColor(col);

			if (c.success) {
				if ((c.r-= shade * by) < 0) c.r = 0;
				if ((c.g-= shade * by) < 0) c.g = 0;
				if ((c.b-= shade * by) < 0) c.b = 0;
				return c;
			}
			return null;
		}

		this.lighten = function (col, by, shade) {

			if (by === void 0) {
				by = 1;
			} else if (by < 0) return this.darken(col, -by, shade);

			if (shade === void 0) {
				shade = 32;
			}

			var c = new xColor(col);

			if (c.success) {
				if ((c.r+= shade * by) > 0xff) c.r = 0xff;
				if ((c.g+= shade * by) > 0xff) c.g = 0xff;
				if ((c.b+= shade * by) > 0xff) c.b = 0xff;
				return c;
			}
			return null;
		}

		this.analogous = function (col, results, slices) {

			if (results === void 0) {
				results = 8;
			}

			if (slices === void 0) {
				slices = 30;
			}

			var c = new xColor(col);

			if (c.success) {

				var hsv = c.getHSV();
				var part = 360 / slices, ret = [ c ];

				for (hsv.h = ((hsv.h - (part * results >> 1)) + 720) % 360; --results; ) {
					hsv.h+= part;
					hsv.h%= 360;
					ret.push(new xColor(hsv));
				}
				return ret;
			}
			return null;
		}

		this.complementary = function(col) {

			var c = new xColor(col);

			if(c.success) {

				var hsl = c.getHSL();

				hsl.h = (hsl.h + 180) % 360;

				return new xColor(hsl);
			}
			return null;
		}

		this.splitcomplement = function (col) {

			var c = new xColor(col);

			if (c.success) {

				var hsv = c.getHSV();
				var ret = [ c ];

				hsv.h+= 72;
				hsv.h%= 360;
				ret.push(new xColor(hsv));

				hsv.h+= 144;
				hsv.h%= 360;
				ret.push(new xColor(hsv));

				return ret;
			}
			return null;
		}

		this.monochromatic = function (col, results) {

			if (results === void 0) {
				results = 6;
			}

			var c = new xColor(col);

			if (c.success) {

				var hsv = c.getHSV();
				var ret = [ c ];

				while (--results) {
					hsv.v+= 20;
					hsv.v%= 100;
					ret.push(new xColor(hsv));
				}
				return ret;
			}
			return null;
		}
	}

	$.xcolor = new xColorMix();

	$.fn.isReadable = function () {

		var elem = this[0];
		var f = "";
		var b = "";

		do {

			if ("" === f && ("transparent" === (f = $.curCSS(elem, "color")) || "rgba(0, 0, 0, 0)" === f)) {
				f = "";
			}

			if ("" === b && ("transparent" === (b = $.curCSS(elem, "backgroundColor")) || "rgba(0, 0, 0, 0)" === b)) {
				b = "";
			}

			if ("" !== f && "" !== b || $.nodeName(elem, "body")) {
				break;
			}

		} while (elem = elem.parentNode);

		if ("" === f) {
			f = "black";
		}

		if ("" === b) {
			b = "white";
		}

		// todo: if alpha != 1, use opacity() to calculate correct color on certain element and it's parent
		return $.xcolor.readable(b, f);
	}

})(jQuery);

