/*
 * Copyright (c) 2009 Simo Kinnunen.
 * Licensed under the MIT license.
 */
//var Cufon=(function(){var L=function(){return L.replace.apply(null,arguments)};var V=L.DOM={ready:(function(){var a=false,c={loaded:1,complete:1};var Z=[],b=function(){if(a){return}a=true;for(var d;d=Z.shift();d()){}};if(document.addEventListener){document.addEventListener("DOMContentLoaded",b,false);window.addEventListener("pageshow",b,false)}if(!window.opera&&document.readyState){(function(){c[document.readyState]?b():setTimeout(arguments.callee,10)})()}if(document.readyState&&document.createStyleSheet){(function(){try{document.body.doScroll("left");b()}catch(d){setTimeout(arguments.callee,1)}})()}P(window,"load",b);return function(d){if(!arguments.length){b()}else{a?d():Z.push(d)}}})()};var M=L.CSS={Size:function(a,Z){this.value=parseFloat(a);this.unit=String(a).match(/[a-z%]*$/)[0]||"px";this.convert=function(b){return b/Z*this.value};this.convertFrom=function(b){return b/this.value*Z};this.toString=function(){return this.value+this.unit}},getStyle:function(a){var Z=document.defaultView;if(Z&&Z.getComputedStyle){return new A(Z.getComputedStyle(a,null))}if(a.currentStyle){return new A(a.currentStyle)}return new A(a.style)},quotedList:I(function(c){var b=[],a=/\s*((["'])([\s\S]*?[^\\])\2|[^,]+)\s*/g,Z;while(Z=a.exec(c)){b.push(Z[3]||Z[1])}return b}),recognizesMedia:I(function(c){var b=document.createElement("style"),a,Z;b.type="text/css";b.media=c;a=F("head")[0];a.insertBefore(b,a.firstChild);Z=!!(b.sheet||b.styleSheet);a.removeChild(b);return Z}),supports:function(b,a){var Z=document.createElement("span").style;if(Z[b]===undefined){return false}Z[b]=a;return Z[b]===a},textAlign:function(c,b,Z,a){if(b.get("textAlign")=="right"){if(Z>0){c=" "+c}}else{if(Z<a-1){c+=" "}}return c},textDecoration:function(e,d){if(!d){d=this.getStyle(e)}var a={underline:null,overline:null,"line-through":null};for(var Z=e;Z.parentNode&&Z.parentNode.nodeType==1;){var c=true;for(var b in a){if(!J(a,b)||a[b]){continue}if(d.get("textDecoration").indexOf(b)!=-1){a[b]=d.get("color")}c=false}if(c){break}d=this.getStyle(Z=Z.parentNode)}return a},textShadow:I(function(d){if(d=="none"){return null}var c=[],e={},Z,a=0;var b=/(#[a-f0-9]+|[a-z]+\(.*?\)|[a-z]+)|(-?[\d.]+[a-z%]*)|,/ig;while(Z=b.exec(d)){if(Z[0]==","){c.push(e);e={},a=0}else{if(Z[1]){e.color=Z[1]}else{e[["offX","offY","blur"][a++]]=Z[2]}}}c.push(e);return c}),color:I(function(a){var Z={};Z.color=a.replace(/^rgba\((.*?),\s*([\d.]+)\)/,function(c,b,d){Z.opacity=parseFloat(d);return"rgb("+b+")"});return Z}),textTransform:function(a,Z){return a[{uppercase:"toUpperCase",lowercase:"toLowerCase"}[Z.get("textTransform")]||"toString"]()}};M.ready=(function(){var a=!M.recognizesMedia("all");var Z=[],c=function(){a=true;for(var f;f=Z.shift();f()){}};var d=F("link"),e={stylesheet:1};function b(){var g,f,h;for(f=0;h=d[f];++f){if(h.disabled||!e[h.rel.toLowerCase()]||!M.recognizesMedia(h.media||"screen")){continue}g=h.sheet||h.styleSheet;if(!g||g.disabled){return false}}return true}if(!a){V.ready(function(){if(b()){c()}else{setTimeout(arguments.callee,10)}})}return function(f){if(a){f()}else{Z.push(f)}}})();function R(a){var Z=this.face=a.face;this.glyphs=a.glyphs;this.w=a.w;this.baseSize=parseInt(Z["units-per-em"],10);this.family=Z["font-family"].toLowerCase();this.weight=Z["font-weight"];this.style=Z["font-style"]||"normal";this.viewBox=(function(){var c=Z.bbox.split(/\s+/);var b={minX:parseInt(c[0],10),minY:parseInt(c[1],10),maxX:parseInt(c[2],10),maxY:parseInt(c[3],10)};b.width=b.maxX-b.minX,b.height=b.maxY-b.minY;b.toString=function(){return[this.minX,this.minY,this.width,this.height].join(" ")};return b})();this.ascent=-parseInt(Z.ascent,10);this.descent=-parseInt(Z.descent,10);this.height=-this.ascent+this.descent}function E(){var a={},Z={oblique:"italic",italic:"oblique"};this.add=function(b){(a[b.style]||(a[b.style]={}))[b.weight]=b};this.get=function(f,g){var e=a[f]||a[Z[f]]||a.normal||a.italic||a.oblique;if(!e){return null}g={normal:400,bold:700}[g]||parseInt(g,10);if(e[g]){return e[g]}var c={1:1,99:0}[g%100],i=[],d,b;if(c===undefined){c=g>400}if(g==500){g=400}for(var h in e){if(!J(e,h)){continue}h=parseInt(h,10);if(!d||h<d){d=h}if(!b||h>b){b=h}i.push(h)}if(g<d){g=d}if(g>b){g=b}i.sort(function(k,j){return(c?(k>g&&j>g)?k<j:k>j:(k<g&&j<g)?k>j:k<j)?-1:1});return e[i[0]]}}function Q(){function b(d,e){if(d.contains){return d.contains(e)}return d.compareDocumentPosition(e)&16}function Z(f){var d=f.relatedTarget;if(!d||b(this,d)){return}a(this)}function c(d){a(this)}function a(d){setTimeout(function(){L.replace(d,D.get(d).options,true)},10)}this.attach=function(d){if(d.onmouseenter===undefined){P(d,"mouseover",Z);P(d,"mouseout",Z)}else{P(d,"mouseenter",c);P(d,"mouseleave",c)}}}function Y(){var b={},Z=0;function a(c){return c.cufid||(c.cufid=++Z)}this.get=function(c){var d=a(c);return b[d]||(b[d]={})}}function A(Z){var b={},a={};this.get=function(c){return b[c]!=undefined?b[c]:Z[c]};this.getSize=function(d,c){return a[d]||(a[d]=new M.Size(this.get(d),c))};this.extend=function(c){for(var d in c){if(J(c,d)){b[d]=c[d]}}return this}}function P(a,Z,b){if(a.addEventListener){a.addEventListener(Z,b,false)}else{if(a.attachEvent){a.attachEvent("on"+Z,function(){return b.call(a,window.event)})}}}function T(a,Z){var b=D.get(a);if(b.options){return a}if(Z.hover&&Z.hoverables[a.nodeName.toLowerCase()]){B.attach(a)}b.options=Z;return a}function I(Z){var a={};return function(b){if(!J(a,b)){a[b]=Z.apply(null,arguments)}return a[b]}}function C(e,d){if(!d){d=M.getStyle(e)}var a=M.quotedList(d.get("fontFamily").toLowerCase()),c;for(var b=0,Z=a.length;b<Z;++b){c=a[b];if(H[c]){return H[c].get(d.get("fontStyle"),d.get("fontWeight"))}}return null}function F(Z){return document.getElementsByTagName(Z)}function J(a,Z){return a.hasOwnProperty(Z)}function G(){var Z={},b,d;for(var c=0,a=arguments.length;b=arguments[c],c<a;++c){for(d in b){if(J(b,d)){Z[d]=b[d]}}}return Z}function N(c,m,a,n,d,b){var k=n.separate;if(k=="none"){return X[n.engine].apply(null,arguments)}var j=document.createDocumentFragment(),f;var g=m.split(O[k]),Z=(k=="words");if(Z&&S){if(/^\s/.test(m)){g.unshift("")}if(/\s$/.test(m)){g.push("")}}for(var h=0,e=g.length;h<e;++h){f=X[n.engine](c,Z?M.textAlign(g[h],a,h,e):g[h],a,n,d,b,h<e-1);if(f){j.appendChild(f)}}return j}function K(a,i){var b,Z,c,f,e,h;for(c=T(a,i).firstChild;c;c=e){f=c.nodeType;e=c.nextSibling;h=false;if(f==1){if(!c.firstChild){continue}if(!/cufon/.test(c.className)){arguments.callee(c,i);continue}else{h=true}}else{if(f!=3){continue}}if(!Z){Z=M.getStyle(a).extend(i)}if(!b){b=C(a,Z)}if(!b){continue}if(h){X[i.engine](b,null,Z,i,c,a);continue}var g=c.data;if(g===""){continue}var d=N(b,g,Z,i,c,a);if(d){c.parentNode.replaceChild(d,c)}else{c.parentNode.removeChild(c)}}}var S=" ".split(/\s+/).length==0;var D=new Y();var B=new Q();var W=[];var X={},H={},U={enableTextDecoration:false,engine:null,hover:false,hoverables:{a:true},printable:true,selector:(window.Sizzle||(window.jQuery&&function(Z){return jQuery(Z)})||(window.dojo&&dojo.query)||(window.$$&&function(Z){return $$(Z)})||(window.$&&function(Z){return $(Z)})||(document.querySelectorAll&&function(Z){return document.querySelectorAll(Z)})||F),separate:"words",textShadow:"none"};var O={words:/\s+/,characters:""};L.now=function(){V.ready();return L};L.refresh=function(){var b=W.splice(0,W.length);for(var a=0,Z=b.length;a<Z;++a){L.replace.apply(null,b[a])}return L};L.registerEngine=function(a,Z){if(!Z){return L}X[a]=Z;return L.set("engine",a)};L.registerFont=function(b){var Z=new R(b),a=Z.family;if(!H[a]){H[a]=new E()}H[a].add(Z);return L.set("fontFamily",'"'+a+'"')};L.replace=function(b,a,Z){a=G(U,a);if(!a.engine){return L}if(typeof a.textShadow=="string"){a.textShadow=M.textShadow(a.textShadow)}if(!Z){W.push(arguments)}if(b.nodeType||typeof b=="string"){b=[b]}M.ready(function(){for(var d=0,c=b.length;d<c;++d){var e=b[d];if(typeof e=="string"){L.replace(a.selector(e),a,true)}else{K(e,a)}}});return L};L.set=function(Z,a){U[Z]=a;return L};return L})();Cufon.registerEngine("canvas",(function(){var B=document.createElement("canvas");if(!B||!B.getContext||!B.getContext.apply){return}B=null;var A=Cufon.CSS.supports("display","inline-block");var E=!A&&(document.compatMode=="BackCompat"||/frameset|transitional/i.test(document.doctype.publicId));var F=document.createElement("style");F.type="text/css";F.appendChild(document.createTextNode(".cufon-canvas{text-indent:0}@media screen,projection{.cufon-canvas{display:inline;display:inline-block;position:relative;vertical-align:middle"+(E?"":";font-size:1px;line-height:1px")+"}.cufon-canvas .cufon-alt{display:-moz-inline-box;display:inline-block;width:0;height:0;overflow:hidden}"+(A?".cufon-canvas canvas{position:relative}":".cufon-canvas canvas{position:absolute}")+"}@media print{.cufon-canvas{padding:0 !important}.cufon-canvas canvas{display:none}.cufon-canvas .cufon-alt{display:inline}}"));document.getElementsByTagName("head")[0].appendChild(F);function D(O,H){var M=0,L=0;var G=[],N=/([mrvxe])([^a-z]*)/g,J;generate:for(var I=0;J=N.exec(O);++I){var K=J[2].split(",");switch(J[1]){case"v":G[I]={m:"bezierCurveTo",a:[M+~~K[0],L+~~K[1],M+~~K[2],L+~~K[3],M+=~~K[4],L+=~~K[5]]};break;case"r":G[I]={m:"lineTo",a:[M+=~~K[0],L+=~~K[1]]};break;case"m":G[I]={m:"moveTo",a:[M=~~K[0],L=~~K[1]]};break;case"x":G[I]={m:"closePath"};break;case"e":break generate}H[G[I].m].apply(H,G[I].a)}return G}function C(K,J){for(var I=0,H=K.length;I<H;++I){var G=K[I];J[G.m].apply(J,G.a)}}return function(q,T,k,P,X,r){var I=(T===null);var V=q.viewBox;var J=k.getSize("fontSize",q.baseSize);var h=k.get("letterSpacing");h=(h=="normal")?0:J.convertFrom(parseInt(h,10));var W=0,j=0,f=0,R=0;var U=P.textShadow,d=[];if(U){for(var p=0,m=U.length;p<m;++p){var Z=U[p];var c=J.convertFrom(parseFloat(Z.offX));var b=J.convertFrom(parseFloat(Z.offY));d[p]=[c,b];if(b<W){W=b}if(c>j){j=c}if(b>f){f=b}if(c<R){R=c}}}var u=Cufon.CSS.textTransform(I?X.alt:T,k).split("");var G=0,S=null;for(var p=0,m=u.length;p<m;++p){var Q=q.glyphs[u[p]]||q.missingGlyph;if(!Q){continue}G+=S=Number(Q.w||q.w)+h}if(S===null){return null}j+=(V.width-S);R+=V.minX;var O,K;if(I){O=X;K=X.firstChild}else{O=document.createElement("span");O.className="cufon cufon-canvas";O.alt=T;K=document.createElement("canvas");O.appendChild(K);if(P.printable){var n=document.createElement("span");n.className="cufon-alt";n.appendChild(document.createTextNode(T));O.appendChild(n)}}var v=O.style;var a=K.style;var H=J.convert(V.height-W+f);var t=Math.ceil(H);var e=t/H;K.width=Math.ceil(J.convert(G+j-R)*e);K.height=t;W+=V.minY;a.top=Math.round(J.convert(W-q.ascent))+"px";a.left=Math.round(J.convert(R))+"px";var N=Math.ceil(J.convert(G*e))+"px";if(A){v.width=N;v.height=J.convert(q.height)+"px"}else{v.paddingLeft=N;v.paddingBottom=(J.convert(q.height)-1)+"px"}var s=K.getContext("2d"),Y=t/V.height;s.scale(Y,Y);s.translate(-R,-W);s.lineWidth=q.face["underline-thickness"];s.save();function L(i,g){s.strokeStyle=g;s.beginPath();s.moveTo(0,i);s.lineTo(G,i);s.stroke()}var M=P.enableTextDecoration?Cufon.CSS.textDecoration(r,k):{};if(M.underline){L(-q.face["underline-position"],M.underline)}if(M.overline){L(q.ascent,M.overline)}s.fillStyle=k.get("color");function o(){for(var w=0,g=u.length;w<g;++w){var x=q.glyphs[u[w]]||q.missingGlyph;if(!x){continue}s.beginPath();if(x.d){if(x.code){C(x.code,s)}else{x.code=D("m"+x.d,s)}}s.fill();s.translate(Number(x.w||q.w)+h,0)}}if(U){for(var p=0,m=U.length;p<m;++p){var Z=U[p];s.save();s.fillStyle=Z.color;s.translate.apply(s,d[p]);o();s.restore()}}o();s.restore();if(M["line-through"]){L(-q.descent,M["line-through"])}return O}})());Cufon.registerEngine("vml",(function(){if(!document.namespaces){return}if(document.namespaces.cvml==null){document.namespaces.add("cvml","urn:schemas-microsoft-com:vml")}var B=document.createElement("cvml:shape");B.style.behavior="url(#default#VML)";if(!B.coordsize){return}B=null;document.write('<style type="text/css">.cufon-vml-canvas{text-indent:0}@media screen{cvml\\:shape,cvml\\:shadow{behavior:url(#default#VML);display:block;antialias:true;position:absolute}.cufon-vml-canvas{position:absolute;text-align:left}.cufon-vml{display:inline-block;position:relative;vertical-align:middle}.cufon-vml .cufon-alt{position:absolute;left:-10000in;font-size:1px}a .cufon-vml{cursor:pointer}}@media print{.cufon-vml *{display:none}.cufon-vml .cufon-alt{display:inline}}</style>');function C(D,E){return A(D,/(?:em|ex|%)$/i.test(E)?"1em":E)}function A(G,H){if(/px$/i.test(H)){return parseFloat(H)}var F=G.style.left,E=G.runtimeStyle.left;G.runtimeStyle.left=G.currentStyle.left;G.style.left=H;var D=G.style.pixelLeft;G.style.left=F;G.runtimeStyle.left=E;return D}return function(s,V,n,S,Z,t,j){var G=(V===null);if(G){V=Z.alt}var X=s.viewBox;var H=n.computedFontSize||(n.computedFontSize=new Cufon.CSS.Size(C(t,n.get("fontSize"))+"px",s.baseSize));var h=n.computedLSpacing;if(h==undefined){h=n.get("letterSpacing");n.computedLSpacing=h=(h=="normal")?0:~~H.convertFrom(A(t,h))}var P,I;if(G){P=Z;I=Z.firstChild}else{P=document.createElement("span");P.className="cufon cufon-vml";P.alt=V;I=document.createElement("span");I.className="cufon-vml-canvas";P.appendChild(I);if(S.printable){var q=document.createElement("span");q.className="cufon-alt";q.appendChild(document.createTextNode(V));P.appendChild(q)}if(!j){P.appendChild(document.createElement("cvml:shape"))}}var y=P.style;var c=I.style;var E=H.convert(X.height),v=Math.ceil(E);var g=v/E;var f=X.minX,e=X.minY;c.height=v;c.top=Math.round(H.convert(e-s.ascent));c.left=Math.round(H.convert(f));y.height=H.convert(s.height)+"px";var L=S.enableTextDecoration?Cufon.CSS.textDecoration(t,n):{};var U=n.get("color");var w=Cufon.CSS.textTransform(V,n).split("");var D=0,d=0,M=null;var T,N,W=S.textShadow;for(var r=0,p=0,o=w.length;r<o;++r){T=s.glyphs[w[r]]||s.missingGlyph;if(T){D+=M=~~(T.w||s.w)+h}}if(M===null){return null}var O=-f+D+(X.width-M);var x=H.convert(O*g),m=Math.round(x);var b=O+","+X.height,F;var Y="r"+b+"nsnf";for(r=0;r<o;++r){T=s.glyphs[w[r]]||s.missingGlyph;if(!T){continue}if(G){N=I.childNodes[p];if(N.firstChild){N.removeChild(N.firstChild)}}else{N=document.createElement("cvml:shape");I.appendChild(N)}N.stroked="f";N.coordsize=b;N.coordorigin=F=(f-d)+","+e;N.path=(T.d?"m"+T.d+"xe":"")+"m"+F+Y;N.fillcolor=U;var u=N.style;u.width=m;u.height=v;if(W){var K=W[0],J=W[1];var R=Cufon.CSS.color(K.color),Q;var a=document.createElement("cvml:shadow");a.on="t";a.color=R.color;a.offset=K.offX+","+K.offY;if(J){Q=Cufon.CSS.color(J.color);a.type="double";a.color2=Q.color;a.offset2=J.offX+","+J.offY}a.opacity=R.opacity||(Q&&Q.opacity)||1;N.appendChild(a)}d+=~~(T.w||s.w)+h;++p}y.width=Math.max(Math.ceil(H.convert(D*g)),0);return P}})());

var Cufon = (function() {
	
	var api = function() {	
		return api.replace.apply(null, arguments);
	};
	
	var DOM = api.DOM = {
			
		ready: (function() {
		
			var complete = false, readyStatus = { loaded: 1, complete: 1 };
		
			var queue = [], perform = function() {
				if (complete) return;
				complete = true;
				for (var fn; fn = queue.shift(); fn());
			};
			
			// Gecko, Opera, WebKit r26101+
			
			if (document.addEventListener) {
				document.addEventListener('DOMContentLoaded', perform, false);
				window.addEventListener('pageshow', perform, false); // For cached Gecko pages
			}
			
			// Old WebKit, Internet Explorer
			
			if (!window.opera && document.readyState) (function() {
				readyStatus[document.readyState] ? perform() : setTimeout(arguments.callee, 10);
			})();
			
			// Internet Explorer
			
			if (document.readyState && document.createStyleSheet) (function() {
				try {
					document.body.doScroll('left');
					perform();
				}
				catch (e) {
					setTimeout(arguments.callee, 1);
				}
			})();
			
			addEvent(window, 'load', perform); // Fallback
			
			return function(listener) {
				if (!arguments.length) perform();
				else complete ? listener() : queue.push(listener);
			};
			
		})()
		
	};

	var CSS = api.CSS = {
	
		Size: function(value, base) {
		
			this.value = parseFloat(value);
			this.unit = String(value).match(/[a-z%]*$/)[0] || 'px';
		
			this.convert = function(value) {
				return value / base * this.value;
			};
			
			this.convertFrom = function(value) {
				return value / this.value * base;
			};
			
			this.toString = function() {
				return this.value + this.unit;
			};

		},
	
		getStyle: function(el) {
			var view = document.defaultView;
			if (view && view.getComputedStyle) return new Style(view.getComputedStyle(el, null));
			if (el.currentStyle) return new Style(el.currentStyle);
			return new Style(el.style);
		},
		
		quotedList: cached(function(value) {
			// doesn't work properly with empty quoted strings (""), but
			// it's not worth the extra code.
			var list = [], re = /\s*((["'])([\s\S]*?[^\\])\2|[^,]+)\s*/g, match;
			while (match = re.exec(value)) list.push(match[3] || match[1]);
			return list;
		}),
		
		recognizesMedia: cached(function(media) {
			var el = document.createElement('style'), container, supported;
			el.type = 'text/css';
			el.media = media;
			container = elementsByTagName('head')[0];
			container.insertBefore(el, container.firstChild);
			supported = !!(el.sheet || el.styleSheet);
			container.removeChild(el);
			return supported;
		}),

		supports: function(property, value) {
			var checker = document.createElement('span').style;
			if (checker[property] === undefined) return false;
			checker[property] = value;
			return checker[property] === value;
		},
		
		textAlign: function(word, style, position, wordCount) {
			if (style.get('textAlign') == 'right') {
				if (position > 0) word = ' ' + word;
			}
			else if (position < wordCount - 1) word += ' ';
			return word;
		},
		
		textDecoration: function(el, style) {
			if (!style) style = this.getStyle(el);
			var types = {
				underline: null,
				overline: null,
				'line-through': null
			};
			for (var search = el; search.parentNode && search.parentNode.nodeType == 1; ) {
				var foundAll = true;
				for (var type in types) {
					if (!hasOwnProperty(types, type) || types[type]) continue;
					if (style.get('textDecoration').indexOf(type) != -1) types[type] = style.get('color');
					foundAll = false;
				}
				if (foundAll) break; // this is rather unlikely to happen
				style = this.getStyle(search = search.parentNode);
			}
			return types;
		},
		
		textShadow: cached(function(value) {
			if (value == 'none') return null;
			var shadows = [], currentShadow = {}, result, offCount = 0;
			var re = /(#[a-f0-9]+|[a-z]+\(.*?\)|[a-z]+)|(-?[\d.]+[a-z%]*)|,/ig;
			while (result = re.exec(value)) {
				if (result[0] == ',') {
					shadows.push(currentShadow);
					currentShadow = {}, offCount = 0;
				}
				else if (result[1]) {
					currentShadow.color = result[1];
				}
				else {
					currentShadow[[ 'offX', 'offY', 'blur' ][offCount++]] = result[2];
				}
			}
			shadows.push(currentShadow);
			return shadows;
		}),
		
		color: cached(function(value) {
			var parsed = {};
			parsed.color = value.replace(/^rgba\((.*?),\s*([\d.]+)\)/, function($0, $1, $2) {
				parsed.opacity = parseFloat($2);
				return 'rgb(' + $1 + ')';
			});
			return parsed;
		}),
		
		textTransform: function(text, style) {
			return text[{
				uppercase: 'toUpperCase',
				lowercase: 'toLowerCase'
			}[style.get('textTransform')] || 'toString']();
		}
		
	};
	
	CSS.ready = (function() {
		
		// don't do anything in Safari 2 (it doesn't recognize any media type)
		var complete = !CSS.recognizesMedia('all');
		
		var queue = [], perform = function() {
			complete = true;
			for (var fn; fn = queue.shift(); fn());
		};
		
		var linkElements = elementsByTagName('link'), watch = {
			stylesheet: 1
		};
		
		function allStylesLoaded() {
			var sheet, i, link;
			for (i = 0; link = linkElements[i]; ++i) {
				if (link.disabled || !watch[link.rel.toLowerCase()] || !CSS.recognizesMedia(link.media || 'screen')) continue;
				sheet = link.sheet || link.styleSheet;
				// in Opera sheet.disabled is true when it's still loading,
				// even though link.disabled is false. they stay in sync if
				// set manually.
				if (!sheet || sheet.disabled) return false;
			}
			return true;
		}
		
		DOM.ready(function() {
			if (complete || allStylesLoaded()) perform();
			else setTimeout(arguments.callee, 10);
		});
		
		return function(listener) {
			if (complete) listener();
			else queue.push(listener);
		};
		
	})();
	
	function Font(data) {
		
		var face = this.face = data.face;
		this.glyphs = data.glyphs;
		this.w = data.w;
		this.baseSize = parseInt(face['units-per-em'], 10);
		
		this.family = face['font-family'].toLowerCase();
		this.weight = face['font-weight'];
		this.style = face['font-style'] || 'normal';
		
		this.viewBox = (function () {
			var parts = face.bbox.split(/\s+/);
			var box = {
				minX: parseInt(parts[0], 10),
				minY: parseInt(parts[1], 10),
				maxX: parseInt(parts[2], 10),
				maxY: parseInt(parts[3], 10)
			};
			box.width = box.maxX - box.minX,
			box.height = box.maxY - box.minY;
			box.toString = function() {
				return [ this.minX, this.minY, this.width, this.height ].join(' ');
			};
			return box;
		})();
		
		this.ascent = -parseInt(face.ascent, 10);
		this.descent = -parseInt(face.descent, 10);
		
		this.height = -this.ascent + this.descent;
		
	}
	
	function FontFamily() {

		var styles = {}, mapping = {
			oblique: 'italic',
			italic: 'oblique'
		};
		
		this.add = function(font) {
			(styles[font.style] || (styles[font.style] = {}))[font.weight] = font;
		};
		
		this.get = function(style, weight) {
			var weights = styles[style] || styles[mapping[style]]
				|| styles.normal || styles.italic || styles.oblique;
			if (!weights) return null;
			// we don't have to worry about "bolder" and "lighter"
			// because IE's currentStyle returns a numeric value for it,
			// and other browsers use the computed value anyway
			weight = {
				normal: 400,
				bold: 700
			}[weight] || parseInt(weight, 10);
			if (weights[weight]) return weights[weight];
			// http://www.w3.org/TR/CSS21/fonts.html#propdef-font-weight
			// Gecko uses x99/x01 for lighter/bolder
			var up = {
				1: 1,
				99: 0
			}[weight % 100], alts = [], min, max;
			if (up === undefined) up = weight > 400;
			if (weight == 500) weight = 400;
			for (var alt in weights) {
				if (!hasOwnProperty(weights, alt)) continue;
				alt = parseInt(alt, 10);
				if (!min || alt < min) min = alt;
				if (!max || alt > max) max = alt;
				alts.push(alt);
			}
			if (weight < min) weight = min;
			if (weight > max) weight = max;
			alts.sort(function(a, b) {
				return (up
					? (a > weight && b > weight) ? a < b : a > b
					: (a < weight && b < weight) ? a > b : a < b) ? -1 : 1;
			});
			return weights[alts[0]];
		};
	
	}
	
	function HoverHandler() {
		
		function contains(node, anotherNode) {
			if (node.contains) return node.contains(anotherNode);
			return node.compareDocumentPosition(anotherNode) & 16;
		}
		
		function onOverOut(e) {
			var related = e.relatedTarget;
			if (!related || contains(this, related)) return;
			trigger(this);
		}
		
		function onEnterLeave(e) {
			trigger(this);
		}

		function trigger(el) {
			// A timeout is needed so that the event can actually "happen"
			// before replace is triggered. This ensures that styles are up
			// to date.
			setTimeout(function() {
				api.replace(el, sharedStorage.get(el).options, true);
			}, 10);
		}
		
		this.attach = function(el) {
			if (el.onmouseenter === undefined) {
				addEvent(el, 'mouseover', onOverOut);
				addEvent(el, 'mouseout', onOverOut);
			}
			else {
				addEvent(el, 'mouseenter', onEnterLeave);
				addEvent(el, 'mouseleave', onEnterLeave);
			}
		};
		
	}
	
	function Storage() {
		
		var map = {}, at = 0;
		
		function identify(el) {
			return el.cufid || (el.cufid = ++at);
		}
		
		this.get = function(el) {
			var id = identify(el);
			return map[id] || (map[id] = {});
		};
		
	}
	
	function Style(style) {
		
		var custom = {}, sizes = {};
		
		this.get = function(property) {
			return custom[property] != undefined ? custom[property] : style[property];
		};
		
		this.getSize = function(property, base) {
			return sizes[property] || (sizes[property] = new CSS.Size(this.get(property), base));
		};
		
		this.extend = function(styles) {
			for (var property in styles) {
				if (hasOwnProperty(styles, property)) custom[property] = styles[property];
			}
			return this;
		};
		
	}
	
	function addEvent(el, type, listener) {
		if (el.addEventListener) {
			el.addEventListener(type, listener, false);
		}
		else if (el.attachEvent) {
			el.attachEvent('on' + type, function() {
				return listener.call(el, window.event);
			});
		}
	}
	
	function attach(el, options) {
		var storage = sharedStorage.get(el);
		if (storage.options) return el;
		if (options.hover && options.hoverables[el.nodeName.toLowerCase()]) {
			hoverHandler.attach(el);
		}
		storage.options = options;
		return el;
	}
	
	function cached(fun) {
		var cache = {};
		return function(key) {
			if (!hasOwnProperty(cache, key)) cache[key] = fun.apply(null, arguments);
			return cache[key];
		};	
	}
	
	function getFont(el, style) {
		if (!style) style = CSS.getStyle(el);
		var families = CSS.quotedList(style.get('fontFamily').toLowerCase()), family;
		for (var i = 0, l = families.length; i < l; ++i) {
			family = families[i];
			if (fonts[family]) return fonts[family].get(style.get('fontStyle'), style.get('fontWeight'));
		}
		return null;
	}
	
	function elementsByTagName(query) {
		return document.getElementsByTagName(query);
	}
	
	function hasOwnProperty(obj, property) {
		return obj.hasOwnProperty(property);
	}
	
	function merge() {
		var merged = {}, args, key;
		for (var i = 0, l = arguments.length; args = arguments[i], i < l; ++i) {
			for (key in args) {
				if (hasOwnProperty(args, key)) merged[key] = args[key];
			}
		}
		return merged;
	}
	
	function process(font, text, style, options, node, el) {
		var separate = options.separate;
		if (separate == 'none') return engines[options.engine].apply(null, arguments);
		var fragment = document.createDocumentFragment(), processed;
		var parts = text.split(separators[separate]), needsAligning = (separate == 'words');
		if (needsAligning && HAS_BROKEN_REGEXP) {
			// @todo figure out a better way to do this
			if (/^\s/.test(text)) parts.unshift('');
			if (/\s$/.test(text)) parts.push('');
		}
		for (var i = 0, l = parts.length; i < l; ++i) {
			processed = engines[options.engine](font,
				needsAligning ? CSS.textAlign(parts[i], style, i, l) : parts[i],
				style, options, node, el, i < l - 1);
			if (processed) fragment.appendChild(processed);
		}
		return fragment;
	}
	
	function replaceElement(el, options) {
		var font, style, node, nodeType, nextNode, redraw;
		for (node = attach(el, options).firstChild; node; node = nextNode) {
			nodeType = node.nodeType;
			nextNode = node.nextSibling;
			redraw = false;
			if (nodeType == 1) {
				if (!node.firstChild) continue;
				if (!/cufon/.test(node.className)) {
					arguments.callee(node, options);
					continue;
				}
				else redraw = true;
			}
			else if (nodeType != 3) continue;
			if (!style) style = CSS.getStyle(el).extend(options);
			if (!font) font = getFont(el, style);
			if (!font) continue;
			if (redraw) {
				engines[options.engine](font, null, style, options, node, el);
				continue;
			}
			var text = node.data;
			if (text === '') continue;
			var processed = process(font, text, style, options, node, el);
			if (processed) node.parentNode.replaceChild(processed, node);
			else node.parentNode.removeChild(node);
		}
	}
	
	var HAS_BROKEN_REGEXP = ' '.split(/\s+/).length == 0;
	
	var sharedStorage = new Storage();
	var hoverHandler = new HoverHandler();
	var replaceHistory = [];
	
	var engines = {}, fonts = {}, defaultOptions = {
		enableTextDecoration: false,
		engine: null,
		//fontScale: 1,
		//fontScaling: false,
		hover: false,
		hoverables: {
			a: true
		},
		printable: true,
		//rotation: 0,
		//selectable: false,
		selector: (
				window.Sizzle
			||	(window.jQuery && function(query) { return jQuery(query); }) // avoid noConflict issues
			||	(window.dojo && dojo.query)
			||	(window.$$ && function(query) { return $$(query); })
			||	(window.$ && function(query) { return $(query); })
			||	(document.querySelectorAll && function(query) { return document.querySelectorAll(query); })
			||	elementsByTagName
		),
		separate: 'words', // 'none' and 'characters' are also accepted
		textShadow: 'none'
	};
	
	var separators = {
		words: /\s+/,
		characters: ''
	};
	
	api.now = function() {
		DOM.ready();
		return api;
	};
	
	api.refresh = function() {
		var currentHistory = replaceHistory.splice(0, replaceHistory.length);
		for (var i = 0, l = currentHistory.length; i < l; ++i) {
			api.replace.apply(null, currentHistory[i]);
		}
		return api;
	};
	
	api.registerEngine = function(id, engine) {
		if (!engine) return api;
		engines[id] = engine;
		return api.set('engine', id);
	};
	
	api.registerFont = function(data) {
		var font = new Font(data), family = font.family;
		if (!fonts[family]) fonts[family] = new FontFamily();
		fonts[family].add(font);
		return api.set('fontFamily', '"' + family + '"');
	};
	
	api.replace = function(elements, options, ignoreHistory) {
		options = merge(defaultOptions, options);
		if (!options.engine) return api; // there's no browser support so we'll just stop here
		if (typeof options.textShadow == 'string')
			options.textShadow = CSS.textShadow(options.textShadow);
		if (!ignoreHistory) replaceHistory.push(arguments);
		if (elements.nodeType || typeof elements == 'string') elements = [ elements ];
		CSS.ready(function() {
			for (var i = 0, l = elements.length; i < l; ++i) {
				var el = elements[i];
				if (typeof el == 'string') api.replace(options.selector(el), options, true);
				else replaceElement(el, options);
			}
		});
		return api;
	};
	
	api.set = function(option, value) {
		defaultOptions[option] = value;
		return api;
	};
	
	return api;
	
})();

Cufon.registerEngine('canvas', (function() {

	// Safari 2 doesn't support .apply() on native methods
	
	var check = document.createElement('canvas');
	if (!check || !check.getContext || !check.getContext.apply) return;
	check = null;
	
	var HAS_INLINE_BLOCK = Cufon.CSS.supports('display', 'inline-block');
	
	// Firefox 2 w/ non-strict doctype (almost standards mode)
	var HAS_BROKEN_LINEHEIGHT = !HAS_INLINE_BLOCK && (document.compatMode == 'BackCompat' || /frameset|transitional/i.test(document.doctype.publicId));
	
	var styleSheet = document.createElement('style');
	styleSheet.type = 'text/css';
	styleSheet.appendChild(document.createTextNode(
		'.cufon-canvas{text-indent:0}' +
		'@media screen,projection{' +
			'.cufon-canvas{display:inline;display:inline-block;position:relative;vertical-align:middle' + 
			(HAS_BROKEN_LINEHEIGHT
				? ''
				: ';font-size:1px;line-height:1px') +
			'}.cufon-canvas .cufon-alt{display:-moz-inline-box;display:inline-block;width:0;height:0;overflow:hidden}' +
			(HAS_INLINE_BLOCK
				? '.cufon-canvas canvas{position:relative}'
				: '.cufon-canvas canvas{position:absolute}') +
		'}' +
		'@media print{' +
			'.cufon-canvas{padding:0 !important}' +
			'.cufon-canvas canvas{display:none}' +
			'.cufon-canvas .cufon-alt{display:inline}' +
		'}'
	));
	document.getElementsByTagName('head')[0].appendChild(styleSheet);

	function generateFromVML(path, context) {
		var atX = 0, atY = 0;
		var code = [], re = /([mrvxe])([^a-z]*)/g, match;
		generate: for (var i = 0; match = re.exec(path); ++i) {
			var c = match[2].split(',');
			switch (match[1]) {
				case 'v':
					code[i] = { m: 'bezierCurveTo', a: [ atX + ~~c[0], atY + ~~c[1], atX + ~~c[2], atY + ~~c[3], atX += ~~c[4], atY += ~~c[5] ] };
					break;
				case 'r':
					code[i] = { m: 'lineTo', a: [ atX += ~~c[0], atY += ~~c[1] ] };
					break;
				case 'm':
					code[i] = { m: 'moveTo', a: [ atX = ~~c[0], atY = ~~c[1] ] };
					break;
				case 'x':
					code[i] = { m: 'closePath' };
					break;
				case 'e':
					break generate;
			}
			context[code[i].m].apply(context, code[i].a);
		}
		return code;
	}
	
	function interpret(code, context) {
		for (var i = 0, l = code.length; i < l; ++i) {
			var line = code[i];
			context[line.m].apply(context, line.a);
		}
	}
	
	return function(font, text, style, options, node, el) {
		
		var redraw = (text === null);
		
		var viewBox = font.viewBox;
		
		var size = style.getSize('fontSize', font.baseSize);
		
		var letterSpacing = style.get('letterSpacing');
		letterSpacing = (letterSpacing == 'normal') ? 0 : size.convertFrom(parseInt(letterSpacing, 10));
		
		var expandTop = 0, expandRight = 0, expandBottom = 0, expandLeft = 0;
		var shadows = options.textShadow, shadowOffsets = [];
		if (shadows) {
			for (var i = shadows.length; i--;) {
				var shadow = shadows[i];
				var x = size.convertFrom(parseFloat(shadow.offX));
				var y = size.convertFrom(parseFloat(shadow.offY));
				shadowOffsets[i] = [ x, y ];
				if (y < expandTop) expandTop = y;
				if (x > expandRight) expandRight = x;
				if (y > expandBottom) expandBottom = y;
				if (x < expandLeft) expandLeft = x;
			}
		}
		
		var chars = Cufon.CSS.textTransform(redraw ? node.alt : text, style).split('');
		
		var width = 0, lastWidth = null;
		
		for (var i = 0, l = chars.length; i < l; ++i) {
			var glyph = font.glyphs[chars[i]] || font.missingGlyph;
			if (!glyph) continue;
			width += lastWidth = Number(glyph.w || font.w) + letterSpacing;
		}
		
		if (lastWidth === null) return null; // there's nothing to render
		
		expandRight += (viewBox.width - lastWidth);
		expandLeft += viewBox.minX;
		
		var wrapper, canvas;
		
		if (redraw) {
			wrapper = node;
			canvas = node.firstChild;
		}
		else {
			wrapper = document.createElement('span');
			wrapper.className = 'cufon cufon-canvas';
			wrapper.alt = text;
			
			canvas = document.createElement('canvas');
			wrapper.appendChild(canvas);
			
			if (options.printable) {
				var print = document.createElement('span');
				print.className = 'cufon-alt';
				print.appendChild(document.createTextNode(text));
				wrapper.appendChild(print);
			}
		}
		
		var wStyle = wrapper.style;
		var cStyle = canvas.style;
		
		var height = size.convert(viewBox.height);
		var roundedHeight = Math.ceil(height);
		var roundingFactor = roundedHeight / height;
		
		canvas.width = Math.ceil(size.convert(width * roundingFactor + expandRight - expandLeft));
		canvas.height = Math.ceil(size.convert(viewBox.height - expandTop + expandBottom));
		
		// minY has no part in canvas.height
		expandTop += viewBox.minY;
		
		cStyle.top = Math.round(size.convert(expandTop - font.ascent)) + 'px';
		cStyle.left = Math.round(size.convert(expandLeft)) + 'px';
		
		var wrapperWidth = Math.ceil(size.convert(width * roundingFactor)) + 'px';
		
		if (HAS_INLINE_BLOCK) {
			wStyle.width = wrapperWidth;
			wStyle.height = size.convert(font.height) + 'px';
		}
		else {
			wStyle.paddingLeft = wrapperWidth;
			wStyle.paddingBottom = (size.convert(font.height) - 1) + 'px';
		}
		
		var g = canvas.getContext('2d'), scale = height / viewBox.height;
		
		// proper horizontal scaling is performed later
		g.scale(scale, scale * roundingFactor);
		g.translate(-expandLeft, -expandTop);
		
		g.lineWidth = font.face['underline-thickness'];
		
		g.save();
		
		function line(y, color) {
			g.strokeStyle = color;
			
			g.beginPath();
			
			g.moveTo(0, y);
			g.lineTo(width, y);
			
			g.stroke();
		}
		
		var textDecoration = options.enableTextDecoration ? Cufon.CSS.textDecoration(el, style) : {};
		
		if (textDecoration.underline) line(-font.face['underline-position'], textDecoration.underline);
		if (textDecoration.overline) line(font.ascent, textDecoration.overline);
		
		g.fillStyle = style.get('color');
		
		function renderText() {
			g.scale(roundingFactor, 1);
			for (var i = 0, l = chars.length; i < l; ++i) {
				var glyph = font.glyphs[chars[i]] || font.missingGlyph;
				if (!glyph) continue;
				g.beginPath();
				if (glyph.d) {
					if (glyph.code) interpret(glyph.code, g);
					else glyph.code = generateFromVML('m' + glyph.d, g);
				}
				g.fill();
				g.translate(Number(glyph.w || font.w) + letterSpacing, 0);
			}
			g.restore();
		}
		
		if (shadows) {
			for (var i = shadows.length; i--;) {
				var shadow = shadows[i];
				g.save();
				g.fillStyle = shadow.color;
				g.translate.apply(g, shadowOffsets[i]);
				renderText();
			}
		}
		
		renderText();
		
		if (textDecoration['line-through']) line(-font.descent, textDecoration['line-through']);
		
		return wrapper;
			
	};
	
})());

Cufon.registerEngine('vml', (function() {

	if (!document.namespaces) return;
	
	if (document.namespaces.cvml == null) {
		document.namespaces.add('cvml', 'urn:schemas-microsoft-com:vml');
	}
	
	var check = document.createElement('cvml:shape');
	check.style.behavior = 'url(#default#VML)';
	if (!check.coordsize) return; // VML isn't supported
	check = null;
	
	document.write('<style type="text/css">' +
		'.cufon-vml-canvas{text-indent:0}' +
		'@media screen{' + 
			'cvml\\:shape,cvml\\:shadow{behavior:url(#default#VML);display:block;antialias:true;position:absolute}' +
			'.cufon-vml-canvas{position:absolute;text-align:left}' +
			'.cufon-vml{display:inline-block;position:relative;vertical-align:middle}' +
			'.cufon-vml .cufon-alt{position:absolute;left:-10000in;font-size:1px}' +
			'a .cufon-vml{cursor:pointer}' +
		'}' +
		'@media print{' + 
			'.cufon-vml *{display:none}' +
			'.cufon-vml .cufon-alt{display:inline}' +
		'}' +
	'</style>');

	function getFontSizeInPixels(el, value) {
		return getSizeInPixels(el, /(?:em|ex|%)$/i.test(value) ? '1em' : value);
	}
	
	// Original by Dead Edwards.
	// Combined with getFontSizeInPixels it also works with relative units.
	function getSizeInPixels(el, value) {
		if (/px$/i.test(value)) return parseFloat(value);
		var style = el.style.left, runtimeStyle = el.runtimeStyle.left;
		el.runtimeStyle.left = el.currentStyle.left;
		el.style.left = value;
		var result = el.style.pixelLeft;
		el.style.left = style;
		el.runtimeStyle.left = runtimeStyle;
		return result;
	}
	
	return function(font, text, style, options, node, el, hasNext) {
		
		var redraw = (text === null);
		
		if (redraw) text = node.alt;
		
		// @todo word-spacing, text-decoration
	
		var viewBox = font.viewBox;
		
		var size = style.computedFontSize || (style.computedFontSize = new Cufon.CSS.Size(getFontSizeInPixels(el, style.get('fontSize')) + 'px', font.baseSize));
		
		var letterSpacing = style.computedLSpacing;
		
		if (letterSpacing == undefined) {
			letterSpacing = style.get('letterSpacing');
			style.computedLSpacing = letterSpacing = (letterSpacing == 'normal') ? 0 : ~~size.convertFrom(getSizeInPixels(el, letterSpacing));
		}
		
		var wrapper, canvas;
		
		if (redraw) {
			wrapper = node;
			canvas = node.firstChild;
		}
		else {
			wrapper = document.createElement('span');
			wrapper.className = 'cufon cufon-vml';
			wrapper.alt = text;
			
			canvas = document.createElement('span');
			canvas.className = 'cufon-vml-canvas';
			wrapper.appendChild(canvas);
			
			if (options.printable) {
				var print = document.createElement('span');
				print.className = 'cufon-alt';
				print.appendChild(document.createTextNode(text));
				wrapper.appendChild(print);
			}
			
			// ie6, for some reason, has trouble rendering the last VML element in the document.
			// we can work around this by injecting a dummy element where needed.
			// @todo find a better solution
			if (!hasNext) wrapper.appendChild(document.createElement('cvml:shape'));
		}
		
		var wStyle = wrapper.style;
		var cStyle = canvas.style;
		
		var height = size.convert(viewBox.height), roundedHeight = Math.ceil(height);
		var roundingFactor = roundedHeight / height;
		var minX = viewBox.minX, minY = viewBox.minY;
		
		cStyle.height = roundedHeight;
		cStyle.top = Math.round(size.convert(minY - font.ascent));
		cStyle.left = Math.round(size.convert(minX));
		
		wStyle.height = size.convert(font.height) + 'px';
		
		var textDecoration = options.enableTextDecoration ? Cufon.CSS.textDecoration(el, style) : {};
		
		var color = style.get('color');
		var chars = Cufon.CSS.textTransform(text, style).split('');
		
		var width = 0, offsetX = 0, advance = null;
		
		var glyph, shape, shadows = options.textShadow;
		
		// pre-calculate width
		for (var i = 0, k = 0, l = chars.length; i < l; ++i) {
			glyph = font.glyphs[chars[i]] || font.missingGlyph;
			if (glyph) width += advance = ~~(glyph.w || font.w) + letterSpacing;
		}
		
		if (advance === null) return null;
		
		var fullWidth = -minX + width + (viewBox.width - advance);
	
		var shapeWidth = size.convert(fullWidth * roundingFactor), roundedShapeWidth = Math.round(shapeWidth);
		
		var coordSize = fullWidth + ',' + viewBox.height, coordOrigin;
		var stretch = 'r' + coordSize + 'nsnf';
		
		for (i = 0; i < l; ++i) {
			
			glyph = font.glyphs[chars[i]] || font.missingGlyph;
			if (!glyph) continue;
			
			if (redraw) {
				// some glyphs may be missing so we can't use i
				shape = canvas.childNodes[k];
				if (shape.firstChild) shape.removeChild(shape.firstChild); // shadow
			}
			else { 
				shape = document.createElement('cvml:shape');
				canvas.appendChild(shape);
			}
			
			shape.stroked = 'f';
			shape.coordsize = coordSize;
			shape.coordorigin = coordOrigin = (minX - offsetX) + ',' + minY;
			shape.path = (glyph.d ? 'm' + glyph.d + 'xe' : '') + 'm' + coordOrigin + stretch;
			shape.fillcolor = color;
			
			// it's important to not set top/left or IE8 will grind to a halt
			var sStyle = shape.style;
			sStyle.width = roundedShapeWidth;
			sStyle.height = roundedHeight;
			
			if (shadows) {
				// due to the limitations of the VML shadow element there
				// can only be two visible shadows. opacity is shared
				// for all shadows.
				var shadow1 = shadows[0], shadow2 = shadows[1];
				var color1 = Cufon.CSS.color(shadow1.color), color2;
				var shadow = document.createElement('cvml:shadow');
				shadow.on = 't';
				shadow.color = color1.color;
				shadow.offset = shadow1.offX + ',' + shadow1.offY;
				if (shadow2) {
					color2 = Cufon.CSS.color(shadow2.color);
					shadow.type = 'double';
					shadow.color2 = color2.color;
					shadow.offset2 = shadow2.offX + ',' + shadow2.offY;
				}
				shadow.opacity = color1.opacity || (color2 && color2.opacity) || 1;
				shape.appendChild(shadow);
			}
			
			offsetX += ~~(glyph.w || font.w) + letterSpacing;
			
			++k;
			
		}
		
		wStyle.width = Math.max(Math.ceil(size.convert(width * roundingFactor)), 0);
		
		return wrapper;
		
	};
	
})());

