/*
	Custom Fidelity jQuery Add-on
*/

	if(typeof(fidelity) == 'undefined'){

		/* functions */
		fidelity = {
			cache : [],
			// implements uniform event handlers
			events : {
				// gracefully add an event handler
				add : function(node, eventName, eventHandler){
					// if the object is valid
					if(node){
						// prefered method
						if('addEventListener' in node){
							node.addEventListener(eventName, eventHandler, false);
						}
						// alternative method
						else if('attachEvent' in node){
							node.attachEvent('on'+eventName, function(event){eventHandler(event)});
						}
						// desperate method
						else{
							node['on'+eventName] = eventHandler;
						}
						// report success
						return true;
					}else{
						// report failure
						return true;
					}
				},
				set : function(node, eventName, eventHandler){
					node['on'+eventName] = eventHandler;
				},
				// trigger an event handler manually
				trigger : function(node, eventName){
					// prefered method
					if('fireEvent' in node){
						node.fireEvent('on' + eventName);
					}
					// alternative method
					else if('dispatchEvent' in node){
						var evt = document.createEvent('HTMLEvents');
						evt.initEvent(eventName, false, true);
						node.dispatchEvent(evt);
					}
					// desperate method
					else{
						eval('node.on' + eventName + '()');
					}
					// report success
					return true;
				},
				// returns the target of the event
				target : function(event){
					var node;
					// if there's no event, pick the one from the window
					if(!event){
						var event = window.event;
					}
					// pick the compatible method
					var node = (event.srcElement) ? event.srcElement : event.target;
					// Safari bug
					if(node.nodeType == 3){
						node = node.parentNode;
					}
					// return the object
					return node;
				}
			},
			// provided a debug console for the framework
			reports : {
				// report a console message
				send : function(message){
					// if the reporting panel doesn't exist
					var reportPanel = document.getElementById('reportPanel');
					if(reportPanel == null){
						// create the panel
						var reportPanel = document.createElement('DIV');
						reportPanel.id = 'reportPanel';
						reportPanel.style.background = '#fff none';
						reportPanel.style.border = 'solid 1px #000';
						reportPanel.style.color = '#000';
						reportPanel.style.fontSize = '12px';
						reportPanel.style.padding = '10px';
						reportPanel.style.position = (navigator.userAgent.indexOf('MSIE 6')>-1) ? 'absolute' : 'fixed' ;
						reportPanel.style.right = '10px';
						reportPanel.style.bottom = '10px';
						reportPanel.style.width = '180px';
						reportPanel.style.height = '320px';
						reportPanel.style.overflow = 'auto';
						reportPanel.style.zIndex = '100000';
						reportPanel.innerHTML = '&nbsp;';
						// store a copy of this node in the move buffer
						document.body.appendChild(reportPanel);
					}
					// truncate the queue
					var reportString = (reportPanel.innerHTML.length < 1000) ? reportPanel.innerHTML : reportPanel.innerHTML.substring(0, 800);
					// output the queue to the panel
					reportPanel.innerHTML = message + '<br/>' + reportString;
				},
				test : function(node, event){
					// write the properties of the node into a string
					var reportString = 'Node properties: ';
					reportString += node.nodeName;
					if(node.id) reportString += '#' + node.id;
					if(node.className) reportString += '.' + node.className.split(' ').join('.');
					// print the string
					fidelity.reports.send(reportString);
					// cancel the click is need be
					if(event != null){
						event.preventDefault ? event.preventDefault() : event.returnValue = false;
					}
				}
			},
			// uses CSS selectors assign behaviours
			selectors : {
				// contains a temprary stylesheet for IE to work with
				stylesheet : null,
				// checks if a node is related to a (common) parent
				related : function(node, parent){
					// if the parent is null
					if(parent == null){
						// don't even look
						return true;
					}else{
						// for all child nodes of the parent
						var allChildNodes = parent.getElementsByTagName('*');
						for(var a=0; a<allChildNodes.length; a++){
							// if this childnode is the given node
							if(node == allChildNodes[a]){
								// return true
								return true;
							}
						}
					}
					// return false if nothing was found at all
					return false;
				},
				// get the DOM elements that belong to the selectors
				query : function(selector, parent){
					// empty collection
					var affectedNodes = [];
					// if the browser supports query selectors
					if(document.querySelectorAll){
						// select elements that match the selector
						affectedNodes = document.querySelectorAll(selector);
					// else use jQuery
					}else if(typeof(jQuery) != 'undefined'){
						affectedNodes = $(selector).get();
					// else use a fall back [1]
					}else{
						// create a stylesheet or use an existing one
						if(fidelity.selectors.styleSheet == null){
							fidelity.selectors.styleSheet = document.createStyleSheet();
						}
						// add a generic rule to the stylesheet
						fidelity.selectors.styleSheet.addRule(selector, "foo:bar");
						// for all nodes in the document
						var allNodes = document.all;
						for (var a=0, b=allNodes.length; a<b; a++){
							// if this node has the generic style
							if(allNodes[a].currentStyle.foo === "bar"){
								// store it in the results list
								affectedNodes.push(allNodes[a]);
							}
						}
						// remove the generic style
						fidelity.selectors.styleSheet.removeRule(0);
					}
					// if a parent node was given
					if(parent != null){
						// empty collection
						var filteredNodes = [];
						// for all the found nodes
						for(var a=0; a<affectedNodes.length; a++){
							// if the objects share the common parent
							if(fidelity.selectors.related(affectedNodes[a], parent)){
								// add it to the filtered collection
								filteredNodes.push(affectedNodes[a]);
							}
						}
						// return the filtered nodes
						return filteredNodes;
					}else{
						// return all the nodes
						return affectedNodes;
					}
				},
				// processes the queued selectors
				process : function(queue, parent){
					// for all selectors in the queue
					for(var selector in queue){
						// get the nodes matching the selector
						var nodes = (typeof(selector) == 'string') ? fidelity.selectors.query(selector, parent) : [selector] ;
						// for all matching nodes
						for(var a=0; a<nodes.length; a++){
							// handle the rules in the object
							fidelity.selectors.handle(nodes[a], queue[selector]);
						}
					}
				},
				// handles the rules of a selector
				handle : function(node, rules){
					// for all rules
					for(var rule in rules){
						// select the intended condition or event handler
						switch(rule){
							// immediately
							case 'start' :
								// execute the rule(s)
								fidelity.selectors.execute(node, null, rules[rule], rules);
								break;
							// in internet explorer
							case 'msie' :
								// if this is internet explorer
								if(navigator.userAgent.indexOf('MSIE')>-1){
									// execute the rule(s)
									fidelity.selectors.execute(node, null, rules[rule], rules);
								}
								break;
							// assume an event handler
							default :
								// add the event handler
								fidelity.events.add(node, rule, (
									// with a copy of the subnode pointer
									function(node, functions, settings){
										return function(event){
											// execute the rule(s)
											fidelity.selectors.execute(node, event, functions, settings);
										}
									}(node, rules[rule], rules)
								));
						}
					}
				},
				// execute the functions belonging to a rule
				execute : function(node, event, functions, settings){
					// if the object is an array
					if(Object.prototype.toString.call(functions) == "[object Array]"){
						// for every function in the array
						for(var a=0; a<functions.length; a++){
							// execute it
							functions[a](node, event, settings);
						}
					// else
					}else{
						// execute it
						functions(node, event, settings);
					}
				},
				// waits for enough of the document to load
				wait : function(queue, parent){
					// check if enough of the DOM was loaded
					if(/interactive|loaded|complete/i.test(document.readyState)){
						// start the parser with a delay
						setTimeout(function(){
							// process the queued up selectors
							fidelity.selectors.process(queue, parent);
						}, 200);
					// else
					}else{
						// wait a while
						setTimeout(function(){
							// check again
							fidelity.selectors.wait(queue, parent);
						}, 200);
					}
				}
			},
			// loading and saving cookies and local data
			storage : {
				// returns a space to store generic configuration data
				settings : function(id){
					// if there no configuration object
					if(fidelity.cache[id] == null){
						fidelity.cache[id] = {};
					}
					// return the configuration object that goes with this id
					return fidelity.cache[id];
				},
				// stores the value in a HTML node
				set : function(node, name, value){
					if(node!=null){
						// create a default value, if there isn't one
						if(node.className==null){
							node.className = '';
						}
						if(node.className.indexOf(' ' + name + '_')<0){
							node.className += ' ' + name + '_0';
						}
						// get the old value
						var current = fidelity.storage.get(node, name, null);
						// replace the old value
						if(current != null){
							node.className = node.className.replace(name + '_' + current, name + '_' + value);
						}
					}
				},
				// retrieves the value from a HTML node
				get : function(node, name, backup){
					// if the node exists
					if(node != null){
						// get the value from the class name or use the default
						var value = (node.className.indexOf(' ' + name + '_')>-1) ?
							node.className.split(' ' + name + '_')[1].split(' ')[0] :
							backup ;
						// return the value as a number or a string
						return (isNaN(parseInt(value))) ?
							value :
							parseFloat(value.toString().replace('D','.')) ;
					// else
					}else{
						// return the default
						return backup;
					}
				},
				// calculates an expiration date for cookies
				expiration : function(days){
					// return a date object in the future
					return new Date(
						new Date().getTime() + days * 24 * 60 * 60 * 1000
					);
				},
				// save a value into a cookie
				save : function(name, value, expires, path, domain, secure) {
					// formulate the cookie
					document.cookie = name + "=" + escape(value) +
						((expires) ? "; expires=" + expires.toGMTString() : "") +
						((path) ? "; path=" + path : "") +
						((domain) ? "; domain=" + domain : "") +
						((secure) ? "; secure" : "");
				},
				// loads a value from a cookie
				load : function(name) {
					// return the clipped value from the cookie
					return (
						(document.cookie.indexOf(name + '=') > -1) ?
							unescape(document.cookie.split(name + '=')[1].split(';')[0]) :
							null
					);
				},
				// clears the value from a cookie
				clear : function(name, path, domain) {
					// if the cookie exists
					if(fidelity.storage.load(name)){
						// clear and expire it
						document.cookie = name + "=" +
						((path) ? "; path=" + path : "") +
						((domain) ? "; domain=" + domain : "") +
						"; expires=Thu, 01-Jan-70 00:00:01 GMT";
					}
				}
			},
			// selectively turns DOM elements on and off
			toggles : {
				// stores the group that is currently processed
				group : null,
				// sets the initial toggle state
				init : function(node, event, options){
					// get the target rule
					var targetRule = (options.target.rule != null) ?
						options.target.rule :
						'#' + node.href.split('#')[1] ;
					// get the target node
					var targetNode = (node.href != null) ?
						document.getElementById(node.href.split('#')[1]) :
						fidelity.toggles.sibling(node);
					// get the target siblings
					var siblingTargets = fidelity.selectors.query(targetRule);
					// determine if this is the first in a group
					var isFirstInGroup = ((fidelity.toggles.group != options.source.rule) && options.grouped);
					fidelity.toggles.group = options.source.rule;
					// determine of the tab starts active
					var isActive = (
						(document.location.hash == '#' + targetNode.id) ||
						(options.initial == 'first' && isFirstInGroup) ||
						(options.initial == targetNode.id)
					);
					// set the source' initial state if there's not already one
					var modifyNode = fidelity.toggles.parent(node, options.source.parent);
					if(
						modifyNode.className.indexOf(options.source.classes[0]) < 0 &&
						modifyNode.className.indexOf(options.source.classes[1]) < 0
					){
						modifyNode.className += (isActive) ?
							' ' + options.source.classes[1] :
							' ' + options.source.classes[0] ;
					}
					// for all nodes that match the rule
					for(var a=0; a<siblingTargets.length; a++){
						// set the target's initial state if there's not already one
						var modifyNode = fidelity.toggles.parent(siblingTargets[a], options.target.parent);
						// if this is the active node
						if(isActive && modifyNode == targetNode){
							// if the node doesn't have any class name
							if(modifyNode.className.indexOf(options.target.classes[0]) < 0 && modifyNode.className.indexOf(options.target.classes[1]) < 0){
								// add the active classname
								modifyNode.className += ' ' + options.target.classes[1];
							// else
							}else{
								// change the passive to active
								modifyNode.className = modifyNode.className.replace(options.target.classes[0], options.target.classes[1]);
							}
						// else
						}else{
							// if the node doesn't have any class name
							if(modifyNode.className.indexOf(options.target.classes[0]) < 0 && modifyNode.className.indexOf(options.target.classes[1]) < 0){
								// add the passive classname
								modifyNode.className += ' ' + options.target.classes[0];
							}
						}
					}
					// the auto property
					if(options.auto != null){
						fidelity.toggles.auto(node, targetNode, options);
					}
				},
				auto : function(node, targetNode, options){
					// get the persistent settings for this group of elements
					var cycleConfig  = fidelity.storage.settings(options.source.rule + ',' + options.target.rule);
					// if the same group has not already been processed
					if(cycleConfig.active == null){
						// mark this cycle as active
						cycleConfig.active = true;
						// set up a loop for this group of sources / targets
						cycleConfig.timeout = setInterval(function(){
							fidelity.toggles.cycle(options);
						}, options.auto);
					}
					// set the mouse pause / resume events for the cycle on each source
					fidelity.events.add(node, 'mouseover', function(){
						clearInterval(cycleConfig.timeout);
					});
					fidelity.events.add(node, 'mouseout', function(){
						cycleConfig.timeout = setInterval(function(){
							fidelity.toggles.cycle(options);
						}, options.auto);
					});
					// set the mouse pause / resume events for the cycle on each target
					fidelity.events.add(targetNode, 'mouseover', function(){
						clearInterval(cycleConfig.timeout);
					});
					fidelity.events.add(targetNode, 'mouseout', function(){
						cycleConfig.timeout = setInterval(function(){
							fidelity.toggles.cycle(options);
						}, options.auto);
					});
				},
				cycle : function(options){
					// get the objects involved in this cycle
					var siblingSources = fidelity.selectors.query(options.source.rule);
					var siblingTargets = fidelity.selectors.query(options.target.rule);
					// check all sources
					var currentActive = -1;
					var a = 0;
					while(a < siblingSources.length && currentActive < 0){
						// if the source if active
						if(siblingSources[a].className.indexOf(options.source.classes[1]) > -1){
							// store it
							currentActive = a;
							foundActive = true;
						}
						// increase the index
						a++;
					}
					// pick the next active
					var nextActive = (a < siblingSources.length) ? a : 0 ;
					// deactivate the current active toggle if there is no group action active
					if(!options.grouped && currentActive > -1){
						fidelity.toggles.execute(siblingSources[currentActive], null, options);
					}
					// activate the next active toggle
					fidelity.toggles.execute(siblingSources[nextActive], null, options);
				},
				// toggle between two states
				execute : function(node, event, options){
					// get the source node
					var sourceNode = node;
					// get the target node
					var targetNode = (node.href != null) ?
						document.getElementById(node.href.split('#')[1]) :
						fidelity.toggles.sibling(sourceNode);
					// get the delays if any
					var openDelay = (options.delay != null) ? options.delay.open : 0 ;
					var closeDelay = (options.delay != null) ? options.delay.close : 0 ;
					// get the sibling nodes
					var siblingSources = fidelity.selectors.query(options.source.rule);
					var siblingTargets = fidelity.selectors.query(options.target.rule);
					// for all sibling nodes
					for(var a=0, b=siblingTargets.length; a<siblingTargets.length; a++){
						// if this sibling is not the target
						if(targetNode == siblingTargets[a]){
							setTimeout((function(a, siblingSources, siblingTargets, options){
								return function(){
									// toggle the source' state
									var modifyNode = fidelity.toggles.parent(sourceNode, options.source.parent);
									if(modifyNode.className.indexOf(options.source.classes[0]) < 0 && options.toggle){
										//fidelity.transitions.tween(modifyNode, options.source.classes[1], options.source.classes[0]);
										modifyNode.className = modifyNode.className.replace(options.source.classes[1], options.source.classes[0]);
									}else{
										//fidelity.transitions.tween(modifyNode, options.source.classes[0], options.source.classes[1]);
										modifyNode.className = modifyNode.className.replace(options.source.classes[0], options.source.classes[1]);
									}
									// toggle the target's state
									var modifyNode = fidelity.toggles.parent(targetNode, options.target.parent);
									if(modifyNode.className.indexOf(options.target.classes[0]) < 0 && options.toggle){
										fidelity.transitions.tween(modifyNode, options.target.classes[1], options.target.classes[0]);
									}else{
										fidelity.transitions.tween(modifyNode, options.target.classes[0], options.target.classes[1]);
									}
								}
							}(a, siblingSources, siblingTargets, options)), openDelay);
						// else
						}else if(options.grouped){
							setTimeout((function(a, siblingSources, siblingTargets, options){
								return function(){
									// make source' state passive
									var modifyNode = fidelity.toggles.parent(siblingSources[a], options.source.parent);
									//fidelity.transitions.tween(modifyNode, options.source.classes[1], options.source.classes[0]);
									modifyNode.className = modifyNode.className.replace(options.source.classes[1], options.source.classes[0]);
									// make the target's state closed
									var modifyNode = fidelity.toggles.parent(siblingTargets[a], options.target.parent);
									fidelity.transitions.tween(modifyNode, options.target.classes[1], options.target.classes[0]);
								}
							}(a, siblingSources, siblingTargets, options)), closeDelay);
						}
					}
					// cancel the click event
					if(event != null) event.preventDefault ? event.preventDefault() : event.returnValue = false;
				},
				// finds the parent node
				parent : function(node, recursions){
					// get the indicated parent of the node
					if(recursions != null){
						for(var a = 0; a < recursions; a++){
							node = node.parentNode;
						}
					}
					// return it
					return node;
				},
				// finds the next sibling node
				sibling : function(node){
					// look for the next likely node
					var nextNode = node.nextSibling;
					while(nextNode.nodeName.indexOf('#') > -1){
						// get the next sibling node
						nextNode = nextNode.nextSibling;
						// if there is no next sibling, take the given one
						if(nextNode == null){
							nextNode = node;
						}
					}
					// return it
					return nextNode;
				},
				// finds the position of the element, relative to the document
				position : function(node, parent) {
					// define a position object
					var position = {
						'x' : 0,
						'y' : 0,
						'scroll' : 0
					};
					// if offsetparent exists
					if(node.offsetParent){
						// add every parent's offset
						do{
							position.x += node.offsetLeft;
							position.y += node.offsetTop;
						}while (node = node.offsetParent);
					}
					// find the current position in the document
					if(parent != null){
						position.scroll = parent.scrollTop;
					}else{
						position.scroll = (self.pageYOffset) ?
							self.pageYOffset :
							(document.documentElement) ?
								document.documentElement.scrollTop :
								document.body.scrollTop ;
					}
					// return the object
					return position;
				}
			},
			// emulates CSS3 transitions
			transitions : {
				// stores the compatibility with CSS3
				css3 : false,
				// identifies the use of internet explorer
				msie : (navigator.userAgent.indexOf('MSIE')>-1),
				// list of supported styles
				supported : [
					{name : 'top', alias : ['top']},
					{name : 'right', alias : ['right']},
					{name : 'bottom', alias : ['bottom']},
					{name : 'left', alias : ['left']},
					{name : 'maxHeight', alias : ['maxHeight']},
					{name : 'marginTop', alias : ['marginTop']},
					{name : 'marginRight', alias : ['marginRight']},
					{name : 'marginBottom', alias : ['marginBottom']},
					{name : 'marginLeft', alias : ['marginLeft']},
					{name : 'color', alias : ['color']},
					{name : 'backgroundColor', alias : ['backgroundColor']},
					{name : 'width', alias : ['width']},
					{name : 'minWidth', alias : ['minWidth']},
					{name : 'maxWidth', alias : ['maxWidth']},
					{name : 'height', alias : ['height']},
					{name : 'minHeight', alias : ['minHeight']},
					{name : 'maxHeight', alias : ['maxHeight']},
					{name : 'opacity', alias : ['opacity', 'mozOpacity', 'webkitOpacity', 'oOpacity', 'msOpacity']},
					{name : 'transform', alias : ['transform', 'mozTransform', 'webkitTransform', 'oTransform', 'msTransform']}
				],
				// object of supported styles
				styles : function(){
					// shortcut pointer
					var st = fidelity.transitions;
					// for all supported styles
					for(var a=0; a<st.supported.length; a++){
						// create an entry
						this[st.supported[a].name] = '';
					}
				},
				// returns the named style property of an object
				style : function(node, property){
					// for internet explorer
					if (node.currentStyle){
						// request the value of a style property
						var value = node.currentStyle[property];
					// for real browsers
					}else if(window.getComputedStyle){
						// request the value of a style property
						var value = document.defaultView.getComputedStyle(node,null).getPropertyValue(property);
					}
					// return the value
					return value;
				},
				// checks transition compatibility
				compatibility : function(node){
					// assume the worst
					var hasCSS3 = false;
					// check the generic transition support
					try{
						document.createEvent('transitionEvent');
						hasCSS3 = true;
					}catch(e){}
					// check the opera transition support
					try{
						document.createEvent('OTransitionEvent');
						hasCSS3 = 'opera';
					}catch(e){}
					// check the webkit transition support
					try{
						document.createEvent('WebKitTransitionEvent');
						hasCSS3 = 'webkit';
						// if there's a flash object on screen in Safari on OS X, the transitions stop working (yay)
						if(navigator.userAgent.indexOf('Safari')>-1 && navigator.userAgent.indexOf('Macintosh')>-1 && navigator.userAgent.indexOf('Chrome')<0){
							hasCSS3 = false;
						}
					}catch(e){}
					// check the mozilla transition support
					var newDiv = document.createElement('div');
					if(typeof(newDiv.style.MozTransition) != 'undefined'){
						hasCSS3 = 'mozilla';
					}
					newDiv = null;
					// pass back the news
					return hasCSS3;
				},
				// checks if a property exists
				exists : function(property){
					return (
						typeof(property)!='undefined' &&
						property!=''
					);
				},
				// merges two sets of styles
				merge : function(transitionStyles, overrideStyles){
					// shortcut pointers
					var st = fidelity.transitions;
					// for all supported styles
					for(var a=0; a<st.supported.length; a++){
						// get the style names
						var propertyName = st.supported[a].name;
						// copy any overriding properties
						if(st.exists(overrideStyles[propertyName])){
							transitionStyles[propertyName] =  overrideStyles[propertyName];
						}
					}
					// return the found styles
					return transitionStyles;
				},
				// gets the current interpolated styles
				get : function(node, transitionStyles){
					// shortcut pointers
					var st = fidelity.transitions;
					// create an object for the styles rules, if one wasn't given
					if(transitionStyles == null){
						var transitionStyles = new st.styles;
					}
					// create an object for the current styles
					var currentStyle = {}
					// for all supported styles
					for(var a=0; a<st.supported.length; a++){
						// for all aliasses of this style
						for(var b=0; b<st.supported[a].alias.length; b++){
							// get the style names
							var propertyName = st.supported[a].name;
							var aliasName = st.supported[a].alias[b];
							// try to fill in the manifested css2 styles
							currentStyle[propertyName] = (st.exists(node.style[aliasName])) ? node.style[aliasName] : transitionStyles[propertyName];
						}
					}
					// exception for Internet Explorer
					if(st.msie){
						if(typeof(node.style.filter)!='undefined' && node.style.filter!=''){
							if(node.style.filter.indexOf('opacity=')>-1){
								currentStyle.opacity = parseInt(node.style.filter.split('opacity=')[1])/100;
							}
						}
					}
					// pass the object back
					return currentStyle;
				},
				// sets the current interpolated styles
				set : function(node, oldStyles, newStyles){
					// shortcut pointers
					var st = fidelity.transitions;
					// for all supported styles
					for(var a=0; a<st.supported.length; a++){
						// for all aliasses of this style
						for(var b=0; b<st.supported[a].alias.length; b++){
							// get the style names
							var propertyName = st.supported[a].name;
							var aliasName = st.supported[a].alias[b];
							// try to fill the manifested css2 styles
							if(st.exists(newStyles[propertyName])){
								node.style[aliasName] = newStyles[propertyName];
							}
						}
					}
					// exception for Internet Explorer
					if(st.msie && newStyles.opacity != oldStyles.opacity && newStyles.opacity != ''){
						node.style.filter = 'alpha(opacity=' + Math.round(newStyles.opacity*100) + ')';
					}
				},
				// initiates a transition between two class names or objects of style rules
				tween : function(node, oldStyling, newStyling, onComplete){
					// if a change in classnames is requested
					if(oldStyling != newStyling){
						// shortcut pointers
						var st = fidelity.transitions;
						var ss = fidelity.storage;
						// check compatibility
						st.css3 = st.compatibility(node);
						// get the end event handler's name
						switch(st.css3){
							case true :
								var endEventName = 'transitionend';
								break;
							case 'mozilla' :
								var endEventName = 'transitionend';
								break;
							case 'opera' :
								var endEventName = 'oTransitionEnd';
								break;
							case 'webkit' :
								var endEventName = 'webkitTransitionEnd';
								break;
							default :
								var endEventName = '';
						}
						// if this was an automatic transition
						if(endEventName != ''){
							// set the complete event
							if(onComplete != null){
								// on complete event
								node.addEventListener(
									endEventName,
									// on complete function
									whenComplete = function(referer){
										// optional call back
										onComplete(referer);
										// remove the event handler
										node.removeEventListener(endEventName, whenComplete, true);
									},
									true
								);
							}
							// trigger the transition
							fidelity.transitions.complete(node, oldStyling, newStyling, null);
						// else if the emulator was included
						}else if(st.loop){
							// if the styling is a classname
							if(typeof(oldStyling) == 'string'){
								// get the rules from the stylesheet
								var oldStyles = st.rules(oldStyling);
								// add the rules from the dom object
								oldStyles = st.get(node, oldStyles)
							// else the styling is an object full of rules
							}else{
								// expand the style object to the full supported set
								var oldStyles = st.merge(new st.styles, oldStyling);
								// get any existing styles from the node
								oldStyles = st.get(node, oldStyles);
							}
							// if the styling is a classname
							if(typeof(newStyling) == 'string'){
								// get the rules from the stylesheet
								var newStyles =  st.rules(newStyling);
							// else the styling is an object full of rules
							}else{
								// expand the style object to the full supported set
								var newStyles = st.merge(new st.styles, newStyling);
							}
							//if it doesn't already have one
							if(!node.id){
								// give the object an id
								node.id = 'transition_' + st.instance++ ;
							}
							// halt its current transition
							clearTimeout(ss.settings(node.id).timeout);
							// start the transition loop
							st.loop(
								// target of the transition
								node,
								// object of initial styles
								oldStyles,
								// object of replacement styles
								newStyles,
								// start time of the effect
								new Date().getTime(),
// TODO: get the transition time from the stylesheet
								// end time of the effect
								new Date().getTime() + 500,
								// call back on complete
								function(referer){
									fidelity.transitions.complete(referer, oldStyling, newStyling, onComplete);
								}
							);
						// else if neither the transitions emulator is present nor transitions are supported
						}else{
							fidelity.transitions.complete(node, oldStyling, newStyling, onComplete);
						}
					}
				},
				// finishes a manual transition
				complete : function(node, oldStyling, newStyling, onComplete){
					// if this is a classname
					if(typeof(newStyling) == 'string'){
						// transition between classnames
						node.className = node.className.replace(new RegExp(oldStyling, 'g'), newStyling);
					// else assume an object full of styles
					}else{
						// transition between styles
						fidelity.transitions.set(node, oldStyling, newStyling);
					}
					// if there is an optional end event
					if(onComplete != null){
						// trigger the end event
						onComplete(node);
					}
				}
			}
		}

		/* jQuery integration */
		if(typeof(jQuery)!='undefined'){
			(function($){
				var methods = {
					init : function(options){
						return this.each(function(){
							fidelity.selectors.handle($(this).get()[0], options);
						});
					},
					test : function(){
						return this.each(function(){
							fidelity.reports.test($(this).get()[0]);
						});
					}
				};
				$.fn.fidelity = function(method){
					if(methods[method]){
						return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
					}else if(typeof method === 'object' || !method){
						return methods.init.apply(this, arguments);
					}else{
						$.error('Method ' +  method + ' does not exist on fidelity.js');
					}
				};
			})(jQuery);
		}

		/* shortcuts */
		var debug = fidelity.reports.send;

	}

/*
	Transition Emulator for Internet Explorer
*/

	if(fidelity.transitions != null){

		// stores the number of time this object is initiated
		fidelity.transitions.instance = 0;

		// sets the master animation rate based on known browser limitations
		fidelity.transitions.rate = (navigator.userAgent.indexOf('MSIE 6')>-1 || navigator.userAgent.indexOf('MSIE 7')>-1 || navigator.userAgent.indexOf('MSIE 8')>-1) ? 50 : 25;

		// storage place for previously used css properties
		fidelity.transitions.cache = [];

		// storage place for this object's settings
		fidelity.transitions.settings = [];

		// gets specified stylesheet rules from the stylesheet
		fidelity.transitions.rules = function(styleName, transitionStyles){
			// shortcut pointers
			var st = fidelity.transitions;
			var stylesheetRules;
			var stylesheetSelector;
			var wantedName = styleName.toLowerCase();
			// create an object for the styles rules, if one wasn't given
			if(transitionStyles == null){
				var transitionStyles = new st.styles;
			}
			// check if this class was found before and stored
			if(st.cache[styleName] != null){
				// for all supported styles
				for(var a=0; a<st.supported.length; a++){
					transitionStyles[st.supported[a].name] = st.cache[styleName][st.supported[a].name];
				}
			// else find the class in the stylesheet
			}else{
				// create a new cache entry
				st.cache[styleName] = new st.styles;
				// for all stylesheets
				for(var a=0; a<document.styleSheets.length; a++){
					// check if the stylesheet lives on the same domain as the page
					var localStylesheet = true;
					if(document.styleSheets[a].href!=null){
						if(document.styleSheets[a].href.indexOf(document.domain)<0 && document.styleSheets[a].href.indexOf('http')>-1){
							localStylesheet = false;
						}
					}
					if(localStylesheet){
						// get its style rules
						atMediaRules = (document.styleSheets[a].cssRules != null) ? document.styleSheets[a].cssRules : document.styleSheets[a].rules ;
						// loop through the selectors
						for(var b=0; b<atMediaRules.length; b++){
							// if this rule has child rules use these rules instead
							stylesheetRules = (atMediaRules[b].cssRules != null) ? atMediaRules[b].cssRules : atMediaRules[b].rules ;
							if(stylesheetRules == null){
								stylesheetRules = [atMediaRules[b]];
							}
							// for all rules
							for(var c=0; c<stylesheetRules.length; c++){
								// if this is an actual style rule
								if(typeof(stylesheetRules[c].selectorText)!='undefined'){
									// if this is the selector we were looking for
									stylesheetSelector = stylesheetRules[c].selectorText.toLowerCase();
									if(stylesheetSelector.indexOf('.' + wantedName)>-1 && stylesheetSelector.indexOf('.' + wantedName) == stylesheetSelector.length - wantedName.length - 1){
										// for all supported styles
										for(var d=0; d<st.supported.length; d++){
											// for all aliasses of this style
											for(var e=0; e<st.supported[d].alias.length; e++){
												// get the style names
												var propertyName = st.supported[d].name;
												var aliasName = st.supported[d].alias[e];
												// if the alias exists
												if(st.exists(stylesheetRules[c].style[aliasName])){
													// get and store the property
													transitionStyles[propertyName] = stylesheetRules[c].style[aliasName];
													st.cache[styleName][propertyName] = stylesheetRules[c].style[aliasName];
												}
											}
										}
										// exception for Internet Explorer
										if(st.msie){
											// if the filter property is present
											if(typeof(stylesheetRules[c].style.filter) != 'undefined'){
												// and the filter used is opacity
												if(stylesheetRules[c].style.filter.indexOf('opacity=') > -1){
													// get and store the property
													transitionStyles.opacity = parseInt(stylesheetRules[c].style.filter.split('opacity=')[1])/100;
													st.cache[styleName].opacity = stylesheetRules[c].style.opacity;
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
			// return the found styles
			return transitionStyles;
		}

		// parses style rules for usable numbers
		fidelity.transitions.parse = {
			// parses several different colour notations
			colour : function(colour){
				if(colour.indexOf('#')>-1){
					// hex colour
					if(colour.length==7){
						var colours =  new Array(colour.substr(1,2), colour.substr(3,2), colour.substr(5,2));
					}else{
						var colours =  new Array(colour.substr(1,1), colour.substr(2,1), colour.substr(3,1));
						colours[0] += colours[0];
						colours[1] += colours[1];
						colours[2] += colours[2];
					}
					for(var a=0; a<colours.length; a++){
						colours[a] = parseInt(colours[a], 16);
					}
				}else if(colour.indexOf('rgb(')>-1){
					// rgb colour
					var colours = colour.replace('rgb(', '').replace(')', '').split(',');
					for(var a=0; a<colours.length; a++){
						colours[a] = parseInt(colours[a]);
					}
				}else if(colour.indexOf('rgba(')>-1){
					// rgba
				}else{
					// named colours
				}
				// return the colour array
				return colours;
			},
			// parses a transformation matrix
			transform : function(transform){
				// create a new transformation object
				var transformation = {
					rotate : [],
					scale : [],
					skew : [],
					translate : [],
					units : []
				}
				// split the incoming transformation
				transform = transform.replace(/, /gi, ',');
				transform = transform.replace(/\( /gi, '(');
				transform = transform.split(' ');
				// for all the parts of the transform style
				for(var a=0; a<transform.length; a++){
					// get the rotation from the transform style
					if(transform[a].indexOf('rotate')>-1){
						transform[a] = transform[a].replace('rotate(', '').replace(')', '');
						transformation.rotate[0] = parseFloat(transform[a]);
					// get the scale from the transform style
					}else if(transform[a].indexOf('scale')>-1){
						transform[a] = transform[a].replace('scale(', '').replace(')', '');
						transformation.scale[0] = parseFloat(transform[a]);
					// get the skew from the transform style
					}else if(transform[a].indexOf('skew')>-1){
						transform[a] = transform[a].replace('skew(', '').replace(')', '');
						transform[a] = transform[a].split(',');
						transformation.skew[0] = parseFloat(transform[a][0]);
						if(transform[a].length>1){
							transformation.skew[1] = parseFloat(transform[a][1]);
						}
					// get the translate from the transform style
					}else if(transform[a].indexOf('translate')>-1){
						transform[a] = transform[a].replace('translate(', '').replace(')', '');
						transform[a] = transform[a].split(',');
						transformation.translate[0] = parseFloat(transform[a][0]);
						transformation.units[0] = (transform[a][0].indexOf('%')>-1) ? '%' : 'px' ;
						if(transform[a].length>1){
							transformation.translate[1] = parseFloat(transform[a][1]);
							transformation.units[1] = (transform[a][1].indexOf('%')>-1) ? '%' : 'px' ;
						}
					}
				}
				// return the transform array
				return transformation;
			}
		}

		// compiles specific style formatting
		fidelity.transitions.compile = {
			// builds a hexadecimal colour string
			colour : function(colours){
				var colour = '#';
				// get hex values for the values
				colour += (colours[0].toString(16).length==1) ? '0' + colours[0].toString(16) : colours[0].toString(16) ;
				colour += (colours[1].toString(16).length==1) ? '0' + colours[1].toString(16) : colours[1].toString(16) ;
				colour += (colours[2].toString(16).length==1) ? '0' + colours[2].toString(16) : colours[2].toString(16) ;
				// return the color string
				return colour;
			}
		}

		// handles interpolations of styles
		fidelity.transitions.interpolate = {
			// interpolates between colours
			colour : function(startStyle, endStyle, progressFraction){
				var currentStyle;
				// shortcut pointers
				var st = fidelity.transitions;
				// if both the begin and end state exist
				if(startStyle!='' && startStyle.toLowerCase()!='transparent' && endStyle!='' && endStyle.toLowerCase()!='transparent'){
					var startColours = st.parse.colour(startStyle);
					var endColours = st.parse.colour(endStyle);
					// interpolate
					var currentColours = new Array(
						parseInt((endColours[0] - startColours[0]) * progressFraction + startColours[0]),
						parseInt((endColours[1] - startColours[1]) * progressFraction + startColours[1]),
						parseInt((endColours[2] - startColours[2]) * progressFraction + startColours[2])
					);
					currentStyle = st.compile.colour(currentColours);
				}
				return currentStyle;
			},
			// interpolates between sizes
			size : function(startStyle, endStyle, progressFraction){
				var currentStyle;
				// if both the begin and end state exist
				if(startStyle != '' && endStyle != ''){
					var startSize = (startStyle.indexOf('%')>-1) ? parseFloat(startStyle)/100 : parseFloat(startStyle) ;
					var endSize = (endStyle.indexOf('%')>-1) ? parseFloat(endStyle)/100 : parseFloat(endStyle) ;
					var currentSize = (endSize - startSize) * progressFraction + startSize;
					if(!isNaN(currentSize)){
						if(startStyle.indexOf('%')>-1) currentStyle = (currentSize * 100) + '%'
						else if(startStyle.indexOf('em')>-1) currentStyle = currentSize + 'em'
						else currentStyle = parseInt(currentSize) + 'px';
					}
				}
				return currentStyle;
			},
			// interpolates between opacities
			opacity : function(startStyle, endStyle, progressFraction){
				var currentStyle;
				// if both the begin and end state exist
				if(!isNaN(parseFloat(startStyle)) && !isNaN(parseFloat(endStyle))){
					var startOpacity = parseFloat(startStyle);
					var endOpacity = parseFloat(endStyle);
					var currentOpacity = (endOpacity - startOpacity) * progressFraction + startOpacity;
					if(!isNaN(currentOpacity)){
						currentStyle = currentOpacity;
					}
				}
				return currentStyle;
			},
			// interpolate between transformation matrices
			transform : function(startStyle, endStyle, progressFraction){
				var currentStyle;
				// shortcut pointers
				var st = fidelity.transitions;
				// if both the begin and end state exist
				if(startStyle!='' && endStyle!=''){
					var startTransform = st.parse.transform(startStyle);
					var endTransform = st.parse.transform(endStyle);
					// formulate the transformation
					currentStyle = '';
					if(startTransform.rotate.length>0 && endTransform.rotate.length>0){
						var currentRotation = (endTransform.rotate[0] - startTransform.rotate[0]) * progressFraction + startTransform.rotate[0];
						currentStyle += 'rotate(' + currentRotation + 'deg) ';
					}
					if(startTransform.scale.length>0 && endTransform.scale.length>0){
						var currentScale = (endTransform.scale[0] - startTransform.scale[0]) * progressFraction + startTransform.scale[0];
						currentStyle += 'scale(' + currentScale + ') ';
					}
					if(startTransform.skew.length>0 && endTransform.skew.length>0){
						var currentSkew = (endTransform.skew[0] - startTransform.skew[0]) * progressFraction + startTransform.skew[0];
						currentStyle += 'skew(' + currentSkew + 'deg';
						if(startTransform.skew.length>1 && endTransform.skew.length>1){
							currentSkew = (endTransform.skew[1] - startTransform.skew[1]) * progressFraction + startTransform.skew[1];
							currentStyle += ', ' + currentSkew + 'deg';
						}
						currentStyle += ') ';
					}
					if(startTransform.translate.length>0 && endTransform.translate.length>0){
						var currentTranslate = (endTransform.translate[0] - startTransform.translate[0]) * progressFraction + startTransform.translate[0];
						currentStyle += 'translate(' + currentTranslate + endTransform.units[0];
						if(startTransform.translate.length>1 && endTransform.translate.length>1){
							currentTranslate = (endTransform.translate[1] - startTransform.translate[1]) * progressFraction + startTransform.translate[1];
							currentStyle += ', ' + currentTranslate + endTransform.units[1];
						}
						currentStyle += ') ';
					}
				}
				return currentStyle;
			}
		}

		// loops interpolations from start to end
		fidelity.transitions.loop = function(node, startStyles, endStyles, startTime, endTime, onComplete){
			// shortcut pointers
			var st = fidelity.transitions;
			var ss = fidelity.storage;
			// get the fraction of progress
			var currentTime = new Date().getTime();
			var progressFraction = (currentTime - startTime) / (endTime - startTime);
			// normalise the value
			if(progressFraction>1) progressFraction = 1;
			// interpolate the top style
			var interPolatedStyle = st.interpolate.size(startStyles.top, endStyles.top, progressFraction);
			if(interPolatedStyle != null) node.style.top = interPolatedStyle;
			// interpolate the right style
			interPolatedStyle = st.interpolate.size(startStyles.right, endStyles.right, progressFraction);
			if(interPolatedStyle != null) node.style.right = interPolatedStyle;
			// interpolate the bottom style
			interPolatedStyle = st.interpolate.size(startStyles.bottom, endStyles.bottom, progressFraction);
			if(interPolatedStyle != null) node.style.bottom = interPolatedStyle;
			// interpolate the left style
			interPolatedStyle = st.interpolate.size(startStyles.left, endStyles.left, progressFraction);
			if(interPolatedStyle != null) node.style.left = interPolatedStyle;
			// interpolate the top margin style
			interPolatedStyle = st.interpolate.size(startStyles.marginTop, endStyles.marginTop, progressFraction);
			if(interPolatedStyle != null) node.style.marginTop = interPolatedStyle;
			// interpolate the right margin style
			interPolatedStyle = st.interpolate.size(startStyles.marginRight, endStyles.marginRight, progressFraction);
			if(interPolatedStyle != null) node.style.marginRight = interPolatedStyle;
			// interpolate the bottom margin style
			interPolatedStyle = st.interpolate.size(startStyles.marginBottom, endStyles.marginBottom, progressFraction);
			if(interPolatedStyle != null) node.style.marginBottom = interPolatedStyle;
			// interpolate the left margin style
			interPolatedStyle = st.interpolate.size(startStyles.marginLeft, endStyles.marginLeft, progressFraction);
			if(interPolatedStyle != null) node.style.marginLeft = interPolatedStyle;
			// interpolate the width style
			interPolatedStyle = st.interpolate.size(startStyles.width, endStyles.width, progressFraction);
			if(interPolatedStyle != null) node.style.width = interPolatedStyle;
			// interpolate the min-width style
			interPolatedStyle = st.interpolate.size(startStyles.minWidth, endStyles.minWidth, progressFraction);
			if(interPolatedStyle != null) node.style.minWidth = interPolatedStyle;
			// interpolate the max-width style
			interPolatedStyle = st.interpolate.size(startStyles.maxWidth, endStyles.maxWidth, progressFraction);
			if(interPolatedStyle != null) node.style.maxWidth = interPolatedStyle;
			// interpolate the height style
			interPolatedStyle = st.interpolate.size(startStyles.height, endStyles.height, progressFraction);
			if(interPolatedStyle != null) node.style.height = interPolatedStyle;
			// interpolate the min-height style
			interPolatedStyle = st.interpolate.size(startStyles.minHeight, endStyles.minHeight, progressFraction);
			if(interPolatedStyle != null) node.style.minHeight = interPolatedStyle;
			// interpolate the max-height style
			interPolatedStyle = st.interpolate.size(startStyles.maxHeight, endStyles.maxHeight, progressFraction);
			if(interPolatedStyle != null) node.style.maxHeight = interPolatedStyle;
			// interpolate the colour style
			interPolatedStyle = st.interpolate.colour(startStyles.color, endStyles.color, progressFraction);
			if(interPolatedStyle != null) node.style.color = interPolatedStyle;
			// interpolate the background colour style
			interPolatedStyle = st.interpolate.colour(startStyles.backgroundColor, endStyles.backgroundColor, progressFraction);
			if(interPolatedStyle != null) node.style.backgroundColor = interPolatedStyle;
			// interpolate the opacity
			interPolatedStyle = st.interpolate.opacity(startStyles.opacity, endStyles.opacity, progressFraction);
			if(interPolatedStyle != null){
				// make sure the object is visible
				node.style.visibility = (interPolatedStyle>0) ? 'visible' : 'hidden';
				node.style.display = (interPolatedStyle>0) ? 'block' : 'none';
				// set the opacity
				node.style.opacity = interPolatedStyle;
				node.style.MozOpacity = interPolatedStyle;
				node.style.WebkitOpacity = interPolatedStyle;
				node.style.OOpacity = interPolatedStyle;
				node.style.msOpacity = interPolatedStyle;
				if(st.msie && startStyles.opacity != endStyles.opacity){
					node.style.filter = 'alpha(opacity=' + Math.round(interPolatedStyle*100) + ')';
				}
			}
			// interpolate the transform
			interPolatedStyle = st.interpolate.transform(startStyles.backgroundColor, endStyles.backgroundColor, progressFraction);
			if(interPolatedStyle != null && interPolatedStyle!=''){
				node.style.transform = interPolatedStyle;
				node.style.MozTransform = interPolatedStyle;
				node.style.WebkitTransform = interPolatedStyle;
				node.style.OTransform = interPolatedStyle;
				node.style.msTransform = interPolatedStyle;
			}
			// if the end time hasn't come yet
			if(currentTime < endTime){
				// order another update and store the timeout in the object settings
				ss.settings(node.id).timeout = setTimeout(
					function(){
						st.loop(node, startStyles, endStyles, startTime, endTime, onComplete);
					},
					st.rate + currentTime - new Date().getTime()
				);
			}else{
				// clear the stored timeout
				fidelity.storage.settings(node.id).timeout = null;
				// finalise the transition
				st.set(node, startStyles, endStyles);
				// trigger the end event
				if(onComplete != null){
					onComplete(node);
				}
			}
		}
	}

/*
	Tabs for use as a Slideshow
*/

	fidelity.tabs = {
		resize : function(node, event, settings){
			// get the target node
			var targetNode = (node.href != null) ?
				document.getElementById(node.href.split('#')[1]) :
				fidelity.toggles.sibling(node);
			// apply its size to the root node
			if(targetNode.offsetHeight && targetNode.offsetHeight > 0 && targetNode.offsetHeight > targetNode.parentNode.offsetHeight){
				targetNode.parentNode.style.height = (targetNode.offsetHeight - 20) + 'px';
			}
		}
	}

/*
	rules
*/

	fidelity.selectors.wait({
		'div.pinBoardCarousel ul.pbcPager li a' : {
			'start' : [
				fidelity.toggles.init,
				fidelity.tabs.resize
			],
			'click' : [
				fidelity.toggles.execute,
				fidelity.tabs.resize
			],
			'source' : {
				'rule' : 'div.pinBoardCarousel ul.pbcPager li a',
				'parent' : 0,
				'classes' : [
					'pbcLink',
					'pbcActive'
				]
			},
			'target' : {
				'rule' : 'div.pinBoardCarousel div.pbcSlides div.pbcSlide',
				'parent' : 0,
				'classes' : [
					'pbcRightStandBy',
					'pbcCenterPosition'
				]
			},
			'grouped' : true,
			'toggle' : false,
			'initial' : 'first',
			'auto' : 8000,
			'delay' : {
				'close' : 0,
				'open' : 0
			}
		}
	}, document.body);



