// script.aculo.us effects.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009

// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// Contributors:
//  Justin Palmer (http://encytemedia.com/)
//  Mark Pilgrim (http://diveintomark.org/)
//  Martin Bialasinki
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/

// converts rgb() and #xxx to #xxxxxx format,
// returns self (or first argument) if not convertable
String.prototype.parseColor = function() {
  var color = '#';
  if (this.slice(0,4) == 'rgb(') {
    var cols = this.slice(4,this.length-1).split(',');
    var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
  } else {
    if (this.slice(0,1) == '#') {
      if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
      if (this.length==7) color = this.toLowerCase();
    }
  }
  return (color.length==7 ? color : (arguments[0] || this));
};

/*--------------------------------------------------------------------------*/

Element.collectTextNodes = function(element) {
  return $A($(element).childNodes).collect( function(node) {
    return (node.nodeType==3 ? node.nodeValue :
      (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
  }).flatten().join('');
};

Element.collectTextNodesIgnoreClass = function(element, className) {
  return $A($(element).childNodes).collect( function(node) {
    return (node.nodeType==3 ? node.nodeValue :
      ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
        Element.collectTextNodesIgnoreClass(node, className) : ''));
  }).flatten().join('');
};

Element.setContentZoom = function(element, percent) {
  element = $(element);
  element.setStyle({fontSize: (percent/100) + 'em'});
  if (Prototype.Browser.WebKit) window.scrollBy(0,0);
  return element;
};

Element.getInlineOpacity = function(element){
  return $(element).style.opacity || '';
};

Element.forceRerendering = function(element) {
  try {
    element = $(element);
    var n = document.createTextNode(' ');
    element.appendChild(n);
    (function(){n.parentNode.removeChild(n)}).defer();
    return element;
  } catch(e) { }
};

/*--------------------------------------------------------------------------*/

var Effect = {
  _elementDoesNotExistError: {
    name: 'ElementDoesNotExistError',
    message: 'The specified DOM element does not exist, but is required for this effect to operate'
  },
  Transitions: {
    linear: Prototype.K,
    sinoidal: function(pos) {
      return (-Math.cos(pos*Math.PI)/2) + .5;
    },
    reverse: function(pos) {
      return 1-pos;
    },
    flicker: function(pos) {
      var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4;
      return pos > 1 ? 1 : pos;
    },
    wobble: function(pos) {
      return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5;
    },
    pulse: function(pos, pulses) {
      return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5;
    },
    spring: function(pos) {
      return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
    },
    none: function(pos) {
      return 0;
    },
    full: function(pos) {
      return 1;
    }
  },
  DefaultOptions: {
    duration:   1.0,   // seconds
    fps:        100,   // 100= assume 66fps max.
    sync:       false, // true for combining
    from:       0.0,
    to:         1.0,
    delay:      0.0,
    queue:      'parallel'
  },
  tagifyText: function(element) {
    var tagifyStyle = 'position:relative';
    if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';

    element = $(element);
    $A(element.childNodes).each( function(child) {
      if (child.nodeType==3) {
        child.nodeValue.toArray().each( function(character) {
          element.insertBefore(
            new Element('span', {style: tagifyStyle}).update(
              character == ' ' ? String.fromCharCode(160) : character),
              child);
        });
        Element.remove(child);
      }
    });
  },
  multiple: function(element, effect) {
    var elements;
    if (((typeof element == 'object') ||
        Object.isFunction(element)) &&
       (element.length))
      elements = element;
    else
      elements = $(element).childNodes;

    var options = Object.extend({
      speed: 0.1,
      delay: 0.0
    }, arguments[2] || { });
    var masterDelay = options.delay;

    $A(elements).each( function(element, index) {
      new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
    });
  },
  PAIRS: {
    'slide':  ['SlideDown','SlideUp'],
    'blind':  ['BlindDown','BlindUp'],
    'appear': ['Appear','Fade']
  },
  toggle: function(element, effect, options) {
    element = $(element);
    effect  = (effect || 'appear').toLowerCase();
    
    return Effect[ Effect.PAIRS[ effect ][ element.visible() ? 1 : 0 ] ](element, Object.extend({
      queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
    }, options || {}));
  }
};

Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;

/* ------------- core effects ------------- */

Effect.ScopedQueue = Class.create(Enumerable, {
  initialize: function() {
    this.effects  = [];
    this.interval = null;
  },
  _each: function(iterator) {
    this.effects._each(iterator);
  },
  add: function(effect) {
    var timestamp = new Date().getTime();

    var position = Object.isString(effect.options.queue) ?
      effect.options.queue : effect.options.queue.position;

    switch(position) {
      case 'front':
        // move unstarted effects after this effect
        this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
            e.startOn  += effect.finishOn;
            e.finishOn += effect.finishOn;
          });
        break;
      case 'with-last':
        timestamp = this.effects.pluck('startOn').max() || timestamp;
        break;
      case 'end':
        // start effect after last queued effect has finished
        timestamp = this.effects.pluck('finishOn').max() || timestamp;
        break;
    }

    effect.startOn  += timestamp;
    effect.finishOn += timestamp;

    if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
      this.effects.push(effect);

    if (!this.interval)
      this.interval = setInterval(this.loop.bind(this), 15);
  },
  remove: function(effect) {
    this.effects = this.effects.reject(function(e) { return e==effect });
    if (this.effects.length == 0) {
      clearInterval(this.interval);
      this.interval = null;
    }
  },
  loop: function() {
    var timePos = new Date().getTime();
    for(var i=0, len=this.effects.length;i<len;i++)
      this.effects[i] && this.effects[i].loop(timePos);
  }
});

Effect.Queues = {
  instances: $H(),
  get: function(queueName) {
    if (!Object.isString(queueName)) return queueName;

    return this.instances.get(queueName) ||
      this.instances.set(queueName, new Effect.ScopedQueue());
  }
};
Effect.Queue = Effect.Queues.get('global');

Effect.Base = Class.create({
  position: null,
  start: function(options) {
    if (options && options.transition === false) options.transition = Effect.Transitions.linear;
    this.options      = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
    this.currentFrame = 0;
    this.state        = 'idle';
    this.startOn      = this.options.delay*1000;
    this.finishOn     = this.startOn+(this.options.duration*1000);
    this.fromToDelta  = this.options.to-this.options.from;
    this.totalTime    = this.finishOn-this.startOn;
    this.totalFrames  = this.options.fps*this.options.duration;

    this.render = (function() {
      function dispatch(effect, eventName) {
        if (effect.options[eventName + 'Internal'])
          effect.options[eventName + 'Internal'](effect);
        if (effect.options[eventName])
          effect.options[eventName](effect);
      }

      return function(pos) {
        if (this.state === "idle") {
          this.state = "running";
          dispatch(this, 'beforeSetup');
          if (this.setup) this.setup();
          dispatch(this, 'afterSetup');
        }
        if (this.state === "running") {
          pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from;
          this.position = pos;
          dispatch(this, 'beforeUpdate');
          if (this.update) this.update(pos);
          dispatch(this, 'afterUpdate');
        }
      };
    })();

    this.event('beforeStart');
    if (!this.options.sync)
      Effect.Queues.get(Object.isString(this.options.queue) ?
        'global' : this.options.queue.scope).add(this);
  },
  loop: function(timePos) {
    if (timePos >= this.startOn) {
      if (timePos >= this.finishOn) {
        this.render(1.0);
        this.cancel();
        this.event('beforeFinish');
        if (this.finish) this.finish();
        this.event('afterFinish');
        return;
      }
      var pos   = (timePos - this.startOn) / this.totalTime,
          frame = (pos * this.totalFrames).round();
      if (frame > this.currentFrame) {
        this.render(pos);
        this.currentFrame = frame;
      }
    }
  },
  cancel: function() {
    if (!this.options.sync)
      Effect.Queues.get(Object.isString(this.options.queue) ?
        'global' : this.options.queue.scope).remove(this);
    this.state = 'finished';
  },
  event: function(eventName) {
    if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
    if (this.options[eventName]) this.options[eventName](this);
  },
  inspect: function() {
    var data = $H();
    for(property in this)
      if (!Object.isFunction(this[property])) data.set(property, this[property]);
    return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
  }
});

Effect.Parallel = Class.create(Effect.Base, {
  initialize: function(effects) {
    this.effects = effects || [];
    this.start(arguments[1]);
  },
  update: function(position) {
    this.effects.invoke('render', position);
  },
  finish: function(position) {
    this.effects.each( function(effect) {
      effect.render(1.0);
      effect.cancel();
      effect.event('beforeFinish');
      if (effect.finish) effect.finish(position);
      effect.event('afterFinish');
    });
  }
});

Effect.Tween = Class.create(Effect.Base, {
  initialize: function(object, from, to) {
    object = Object.isString(object) ? $(object) : object;
    var args = $A(arguments), method = args.last(),
      options = args.length == 5 ? args[3] : null;
    this.method = Object.isFunction(method) ? method.bind(object) :
      Object.isFunction(object[method]) ? object[method].bind(object) :
      function(value) { object[method] = value };
    this.start(Object.extend({ from: from, to: to }, options || { }));
  },
  update: function(position) {
    this.method(position);
  }
});

Effect.Event = Class.create(Effect.Base, {
  initialize: function() {
    this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
  },
  update: Prototype.emptyFunction
});

Effect.Opacity = Class.create(Effect.Base, {
  initialize: function(element) {
    this.element = $(element);
    if (!this.element) throw(Effect._elementDoesNotExistError);
    // make this work on IE on elements without 'layout'
    if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
      this.element.setStyle({zoom: 1});
    var options = Object.extend({
      from: this.element.getOpacity() || 0.0,
      to:   1.0
    }, arguments[1] || { });
    this.start(options);
  },
  update: function(position) {
    this.element.setOpacity(position);
  }
});

Effect.Move = Class.create(Effect.Base, {
  initialize: function(element) {
    this.element = $(element);
    if (!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({
      x:    0,
      y:    0,
      mode: 'relative'
    }, arguments[1] || { });
    this.start(options);
  },
  setup: function() {
    this.element.makePositioned();
    this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
    this.originalTop  = parseFloat(this.element.getStyle('top')  || '0');
    if (this.options.mode == 'absolute') {
      this.options.x = this.options.x - this.originalLeft;
      this.options.y = this.options.y - this.originalTop;
    }
  },
  update: function(position) {
    this.element.setStyle({
      left: (this.options.x  * position + this.originalLeft).round() + 'px',
      top:  (this.options.y  * position + this.originalTop).round()  + 'px'
    });
  }
});

// for backwards compatibility
Effect.MoveBy = function(element, toTop, toLeft) {
  return new Effect.Move(element,
    Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
};

Effect.Scale = Class.create(Effect.Base, {
  initialize: function(element, percent) {
    this.element = $(element);
    if (!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({
      scaleX: true,
      scaleY: true,
      scaleContent: true,
      scaleFromCenter: false,
      scaleMode: 'box',        // 'box' or 'contents' or { } with provided values
      scaleFrom: 100.0,
      scaleTo:   percent
    }, arguments[2] || { });
    this.start(options);
  },
  setup: function() {
    this.restoreAfterFinish = this.options.restoreAfterFinish || false;
    this.elementPositioning = this.element.getStyle('position');

    this.originalStyle = { };
    ['top','left','width','height','fontSize'].each( function(k) {
      this.originalStyle[k] = this.element.style[k];
    }.bind(this));

    this.originalTop  = this.element.offsetTop;
    this.originalLeft = this.element.offsetLeft;

    var fontSize = this.element.getStyle('font-size') || '100%';
    ['em','px','%','pt'].each( function(fontSizeType) {
      if (fontSize.indexOf(fontSizeType)>0) {
        this.fontSize     = parseFloat(fontSize);
        this.fontSizeType = fontSizeType;
      }
    }.bind(this));

    this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;

    this.dims = null;
    if (this.options.scaleMode=='box')
      this.dims = [this.element.offsetHeight, this.element.offsetWidth];
    if (/^content/.test(this.options.scaleMode))
      this.dims = [this.element.scrollHeight, this.element.scrollWidth];
    if (!this.dims)
      this.dims = [this.options.scaleMode.originalHeight,
                   this.options.scaleMode.originalWidth];
  },
  update: function(position) {
    var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
    if (this.options.scaleContent && this.fontSize)
      this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
    this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
  },
  finish: function(position) {
    if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
  },
  setDimensions: function(height, width) {
    var d = { };
    if (this.options.scaleX) d.width = width.round() + 'px';
    if (this.options.scaleY) d.height = height.round() + 'px';
    if (this.options.scaleFromCenter) {
      var topd  = (height - this.dims[0])/2;
      var leftd = (width  - this.dims[1])/2;
      if (this.elementPositioning == 'absolute') {
        if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
        if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
      } else {
        if (this.options.scaleY) d.top = -topd + 'px';
        if (this.options.scaleX) d.left = -leftd + 'px';
      }
    }
    this.element.setStyle(d);
  }
});

Effect.Highlight = Class.create(Effect.Base, {
  initialize: function(element) {
    this.element = $(element);
    if (!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
    this.start(options);
  },
  setup: function() {
    // Prevent executing on elements not in the layout flow
    if (this.element.getStyle('display')=='none') { this.cancel(); return; }
    // Disable background image during the effect
    this.oldStyle = { };
    if (!this.options.keepBackgroundImage) {
      this.oldStyle.backgroundImage = this.element.getStyle('background-image');
      this.element.setStyle({backgroundImage: 'none'});
    }
    if (!this.options.endcolor)
      this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
    if (!this.options.restorecolor)
      this.options.restorecolor = this.element.getStyle('background-color');
    // init color calculations
    this._base  = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
    this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
  },
  update: function(position) {
    this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
      return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
  },
  finish: function() {
    this.element.setStyle(Object.extend(this.oldStyle, {
      backgroundColor: this.options.restorecolor
    }));
  }
});

Effect.ScrollTo = function(element) {
  var options = arguments[1] || { },
  scrollOffsets = document.viewport.getScrollOffsets(),
  elementOffsets = $(element).cumulativeOffset();

  if (options.offset) elementOffsets[1] += options.offset;

  return new Effect.Tween(null,
    scrollOffsets.top,
    elementOffsets[1],
    options,
    function(p){ scrollTo(scrollOffsets.left, p.round()); }
  );
};

/* ------------- combination effects ------------- */

Effect.Fade = function(element) {
  element = $(element);
  var oldOpacity = element.getInlineOpacity();
  var options = Object.extend({
    from: element.getOpacity() || 1.0,
    to:   0.0,
    afterFinishInternal: function(effect) {
      if (effect.options.to!=0) return;
      effect.element.hide().setStyle({opacity: oldOpacity});
    }
  }, arguments[1] || { });
  return new Effect.Opacity(element,options);
};

Effect.Appear = function(element) {
  element = $(element);
  var options = Object.extend({
  from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
  to:   1.0,
  // force Safari to render floated elements properly
  afterFinishInternal: function(effect) {
    effect.element.forceRerendering();
  },
  beforeSetup: function(effect) {
    effect.element.setOpacity(effect.options.from).show();
  }}, arguments[1] || { });
  return new Effect.Opacity(element,options);
};

Effect.Puff = function(element) {
  element = $(element);
  var oldStyle = {
    opacity: element.getInlineOpacity(),
    position: element.getStyle('position'),
    top:  element.style.top,
    left: element.style.left,
    width: element.style.width,
    height: element.style.height
  };
  return new Effect.Parallel(
   [ new Effect.Scale(element, 200,
      { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
     new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
     Object.extend({ duration: 1.0,
      beforeSetupInternal: function(effect) {
        Position.absolutize(effect.effects[0].element);
      },
      afterFinishInternal: function(effect) {
         effect.effects[0].element.hide().setStyle(oldStyle); }
     }, arguments[1] || { })
   );
};

Effect.BlindUp = function(element) {
  element = $(element);
  element.makeClipping();
  return new Effect.Scale(element, 0,
    Object.extend({ scaleContent: false,
      scaleX: false,
      restoreAfterFinish: true,
      afterFinishInternal: function(effect) {
        effect.element.hide().undoClipping();
      }
    }, arguments[1] || { })
  );
};

Effect.BlindDown = function(element) {
  element = $(element);
  var elementDimensions = element.getDimensions();
  return new Effect.Scale(element, 100, Object.extend({
    scaleContent: false,
    scaleX: false,
    scaleFrom: 0,
    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
    restoreAfterFinish: true,
    afterSetup: function(effect) {
      effect.element.makeClipping().setStyle({height: '0px'}).show();
    },
    afterFinishInternal: function(effect) {
      effect.element.undoClipping();
    }
  }, arguments[1] || { }));
};

Effect.SwitchOff = function(element) {
  element = $(element);
  var oldOpacity = element.getInlineOpacity();
  return new Effect.Appear(element, Object.extend({
    duration: 0.4,
    from: 0,
    transition: Effect.Transitions.flicker,
    afterFinishInternal: function(effect) {
      new Effect.Scale(effect.element, 1, {
        duration: 0.3, scaleFromCenter: true,
        scaleX: false, scaleContent: false, restoreAfterFinish: true,
        beforeSetup: function(effect) {
          effect.element.makePositioned().makeClipping();
        },
        afterFinishInternal: function(effect) {
          effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
        }
      });
    }
  }, arguments[1] || { }));
};

Effect.DropOut = function(element) {
  element = $(element);
  var oldStyle = {
    top: element.getStyle('top'),
    left: element.getStyle('left'),
    opacity: element.getInlineOpacity() };
  return new Effect.Parallel(
    [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
      new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
    Object.extend(
      { duration: 0.5,
        beforeSetup: function(effect) {
          effect.effects[0].element.makePositioned();
        },
        afterFinishInternal: function(effect) {
          effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
        }
      }, arguments[1] || { }));
};

Effect.Shake = function(element) {
  element = $(element);
  var options = Object.extend({
    distance: 20,
    duration: 0.5
  }, arguments[1] || {});
  var distance = parseFloat(options.distance);
  var split = parseFloat(options.duration) / 10.0;
  var oldStyle = {
    top: element.getStyle('top'),
    left: element.getStyle('left') };
    return new Effect.Move(element,
      { x:  distance, y: 0, duration: split, afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: -distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x:  distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: -distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x:  distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
        effect.element.undoPositioned().setStyle(oldStyle);
  }}); }}); }}); }}); }}); }});
};

Effect.SlideDown = function(element) {
  element = $(element).cleanWhitespace();
  // SlideDown need to have the content of the element wrapped in a container element with fixed height!
  var oldInnerBottom = element.down().getStyle('bottom');
  var elementDimensions = element.getDimensions();
  return new Effect.Scale(element, 100, Object.extend({
    scaleContent: false,
    scaleX: false,
    scaleFrom: window.opera ? 0 : 1,
    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
    restoreAfterFinish: true,
    afterSetup: function(effect) {
      effect.element.makePositioned();
      effect.element.down().makePositioned();
      if (window.opera) effect.element.setStyle({top: ''});
      effect.element.makeClipping().setStyle({height: '0px'}).show();
    },
    afterUpdateInternal: function(effect) {
      effect.element.down().setStyle({bottom:
        (effect.dims[0] - effect.element.clientHeight) + 'px' });
    },
    afterFinishInternal: function(effect) {
      effect.element.undoClipping().undoPositioned();
      effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
    }, arguments[1] || { })
  );
};

Effect.SlideUp = function(element) {
  element = $(element).cleanWhitespace();
  var oldInnerBottom = element.down().getStyle('bottom');
  var elementDimensions = element.getDimensions();
  return new Effect.Scale(element, window.opera ? 0 : 1,
   Object.extend({ scaleContent: false,
    scaleX: false,
    scaleMode: 'box',
    scaleFrom: 100,
    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
    restoreAfterFinish: true,
    afterSetup: function(effect) {
      effect.element.makePositioned();
      effect.element.down().makePositioned();
      if (window.opera) effect.element.setStyle({top: ''});
      effect.element.makeClipping().show();
    },
    afterUpdateInternal: function(effect) {
      effect.element.down().setStyle({bottom:
        (effect.dims[0] - effect.element.clientHeight) + 'px' });
    },
    afterFinishInternal: function(effect) {
      effect.element.hide().undoClipping().undoPositioned();
      effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
    }
   }, arguments[1] || { })
  );
};

// Bug in opera makes the TD containing this element expand for a instance after finish
Effect.Squish = function(element) {
  return new Effect.Scale(element, window.opera ? 1 : 0, {
    restoreAfterFinish: true,
    beforeSetup: function(effect) {
      effect.element.makeClipping();
    },
    afterFinishInternal: function(effect) {
      effect.element.hide().undoClipping();
    }
  });
};

Effect.Grow = function(element) {
  element = $(element);
  var options = Object.extend({
    direction: 'center',
    moveTransition: Effect.Transitions.sinoidal,
    scaleTransition: Effect.Transitions.sinoidal,
    opacityTransition: Effect.Transitions.full
  }, arguments[1] || { });
  var oldStyle = {
    top: element.style.top,
    left: element.style.left,
    height: element.style.height,
    width: element.style.width,
    opacity: element.getInlineOpacity() };

  var dims = element.getDimensions();
  var initialMoveX, initialMoveY;
  var moveX, moveY;

  switch (options.direction) {
    case 'top-left':
      initialMoveX = initialMoveY = moveX = moveY = 0;
      break;
    case 'top-right':
      initialMoveX = dims.width;
      initialMoveY = moveY = 0;
      moveX = -dims.width;
      break;
    case 'bottom-left':
      initialMoveX = moveX = 0;
      initialMoveY = dims.height;
      moveY = -dims.height;
      break;
    case 'bottom-right':
      initialMoveX = dims.width;
      initialMoveY = dims.height;
      moveX = -dims.width;
      moveY = -dims.height;
      break;
    case 'center':
      initialMoveX = dims.width / 2;
      initialMoveY = dims.height / 2;
      moveX = -dims.width / 2;
      moveY = -dims.height / 2;
      break;
  }

  return new Effect.Move(element, {
    x: initialMoveX,
    y: initialMoveY,
    duration: 0.01,
    beforeSetup: function(effect) {
      effect.element.hide().makeClipping().makePositioned();
    },
    afterFinishInternal: function(effect) {
      new Effect.Parallel(
        [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
          new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
          new Effect.Scale(effect.element, 100, {
            scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
            sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
        ], Object.extend({
             beforeSetup: function(effect) {
               effect.effects[0].element.setStyle({height: '0px'}).show();
             },
             afterFinishInternal: function(effect) {
               effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
             }
           }, options)
      );
    }
  });
};

Effect.Shrink = function(element) {
  element = $(element);
  var options = Object.extend({
    direction: 'center',
    moveTransition: Effect.Transitions.sinoidal,
    scaleTransition: Effect.Transitions.sinoidal,
    opacityTransition: Effect.Transitions.none
  }, arguments[1] || { });
  var oldStyle = {
    top: element.style.top,
    left: element.style.left,
    height: element.style.height,
    width: element.style.width,
    opacity: element.getInlineOpacity() };

  var dims = element.getDimensions();
  var moveX, moveY;

  switch (options.direction) {
    case 'top-left':
      moveX = moveY = 0;
      break;
    case 'top-right':
      moveX = dims.width;
      moveY = 0;
      break;
    case 'bottom-left':
      moveX = 0;
      moveY = dims.height;
      break;
    case 'bottom-right':
      moveX = dims.width;
      moveY = dims.height;
      break;
    case 'center':
      moveX = dims.width / 2;
      moveY = dims.height / 2;
      break;
  }

  return new Effect.Parallel(
    [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
      new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
      new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
    ], Object.extend({
         beforeStartInternal: function(effect) {
           effect.effects[0].element.makePositioned().makeClipping();
         },
         afterFinishInternal: function(effect) {
           effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
       }, options)
  );
};

Effect.Pulsate = function(element) {
  element = $(element);
  var options    = arguments[1] || { },
    oldOpacity = element.getInlineOpacity(),
    transition = options.transition || Effect.Transitions.linear,
    reverser   = function(pos){
      return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5);
    };

  return new Effect.Opacity(element,
    Object.extend(Object.extend({  duration: 2.0, from: 0,
      afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
    }, options), {transition: reverser}));
};

Effect.Fold = function(element) {
  element = $(element);
  var oldStyle = {
    top: element.style.top,
    left: element.style.left,
    width: element.style.width,
    height: element.style.height };
  element.makeClipping();
  return new Effect.Scale(element, 5, Object.extend({
    scaleContent: false,
    scaleX: false,
    afterFinishInternal: function(effect) {
    new Effect.Scale(element, 1, {
      scaleContent: false,
      scaleY: false,
      afterFinishInternal: function(effect) {
        effect.element.hide().undoClipping().setStyle(oldStyle);
      } });
  }}, arguments[1] || { }));
};

Effect.Morph = Class.create(Effect.Base, {
  initialize: function(element) {
    this.element = $(element);
    if (!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({
      style: { }
    }, arguments[1] || { });

    if (!Object.isString(options.style)) this.style = $H(options.style);
    else {
      if (options.style.include(':'))
        this.style = options.style.parseStyle();
      else {
        this.element.addClassName(options.style);
        this.style = $H(this.element.getStyles());
        this.element.removeClassName(options.style);
        var css = this.element.getStyles();
        this.style = this.style.reject(function(style) {
          return style.value == css[style.key];
        });
        options.afterFinishInternal = function(effect) {
          effect.element.addClassName(effect.options.style);
          effect.transforms.each(function(transform) {
            effect.element.style[transform.style] = '';
          });
        };
      }
    }
    this.start(options);
  },

  setup: function(){
    function parseColor(color){
      if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
      color = color.parseColor();
      return $R(0,2).map(function(i){
        return parseInt( color.slice(i*2+1,i*2+3), 16 );
      });
    }
    this.transforms = this.style.map(function(pair){
      var property = pair[0], value = pair[1], unit = null;

      if (value.parseColor('#zzzzzz') != '#zzzzzz') {
        value = value.parseColor();
        unit  = 'color';
      } else if (property == 'opacity') {
        value = parseFloat(value);
        if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
          this.element.setStyle({zoom: 1});
      } else if (Element.CSS_LENGTH.test(value)) {
          var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
          value = parseFloat(components[1]);
          unit = (components.length == 3) ? components[2] : null;
      }

      var originalValue = this.element.getStyle(property);
      return {
        style: property.camelize(),
        originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
        targetValue: unit=='color' ? parseColor(value) : value,
        unit: unit
      };
    }.bind(this)).reject(function(transform){
      return (
        (transform.originalValue == transform.targetValue) ||
        (
          transform.unit != 'color' &&
          (isNaN(transform.originalValue) || isNaN(transform.targetValue))
        )
      );
    });
  },
  update: function(position) {
    var style = { }, transform, i = this.transforms.length;
    while(i--)
      style[(transform = this.transforms[i]).style] =
        transform.unit=='color' ? '#'+
          (Math.round(transform.originalValue[0]+
            (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
          (Math.round(transform.originalValue[1]+
            (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
          (Math.round(transform.originalValue[2]+
            (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
        (transform.originalValue +
          (transform.targetValue - transform.originalValue) * position).toFixed(3) +
            (transform.unit === null ? '' : transform.unit);
    this.element.setStyle(style, true);
  }
});

Effect.MorphClass = Class.create(Effect.Morph, {
  initialize: function(element, options) {
    this.element = $(element);
    if (!this.element) throw(Effect._elementDoesNotExistError);
    
    var to   = this.deltaClasses(options.toClass);
    var from = options.fromClass;
    
    this.modifyClasses(to, from);
    this.style = $H(this.element.getStyles());    
    this.modifyClasses(from, to);
    
    var css = this.element.getStyles();
    this.style = this.style.reject(function(style) {
      return style.value == css[style.key];
    });
    
    options.afterFinishInternal = function(effect) {
      effect.modifyClasses(to, from);
      effect.transforms.each(function(transform) {
        effect.element.style[transform.style] = '';
      });
    };
    
    this.start(options);
  },
  
  modifyClasses: function (add, remove) {
    if (add) add.split(' ').each(function (klass) { this.element.addClassName(klass); }, this);
    if (remove) remove.split(' ').each(function (klass) { this.element.removeClassName(klass); }, this);
  },
  
  deltaClasses: function (klass) {
    if (klass)
      return klass.split(' ').findAll(function (k) { return !this.element.hasClassName(k); }, this).join(' ');
    else
      return null;
  }
});

Effect.Transform = Class.create({
  initialize: function(tracks){
    this.tracks  = [];
    this.options = arguments[1] || { };
    this.addTracks(tracks);
  },
  addTracks: function(tracks){
    tracks.each(function(track){
      track = $H(track);
      var data = track.values().first();
      this.tracks.push($H({
        ids:     track.keys().first(),
        effect:  Effect.Morph,
        options: { style: data }
      }));
    }.bind(this));
    return this;
  },
  play: function(){
    return new Effect.Parallel(
      this.tracks.map(function(track){
        var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
        var elements = [$(ids) || $$(ids)].flatten();
        return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
      }).flatten(),
      this.options
    );
  }
});

Element.CSS_PROPERTIES = $w(
  'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
  'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
  'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
  'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
  'fontSize fontWeight height left letterSpacing lineHeight ' +
  'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
  'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
  'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
  'right textIndent top width wordSpacing zIndex');

Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;

String.__parseStyleElement = document.createElement('div');
String.prototype.parseStyle = function(){
  var style, styleRules = $H();
  if (Prototype.Browser.WebKit)
    style = new Element('div',{style:this}).style;
  else {
    String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
    style = String.__parseStyleElement.childNodes[0].style;
  }

  Element.CSS_PROPERTIES.each(function(property){
    if (style[property]) styleRules.set(property, style[property]);
  });

  if (Prototype.Browser.IE && this.include('opacity'))
    styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);

  return styleRules;
};

if (document.defaultView && document.defaultView.getComputedStyle) {
  Element.getStyles = function(element) {
    var css = document.defaultView.getComputedStyle($(element), null);
    return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
      styles[property] = css[property];
      return styles;
    });
  };
} else {
  Element.getStyles = function(element) {
    element = $(element);
    var css = element.currentStyle, styles;
    styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
      results[property] = css[property];
      return results;
    });
    if (!styles.opacity) styles.opacity = element.getOpacity();
    return styles;
  };
}

Effect.Methods = {
  morph: function(element, style) {
    element = $(element);
    new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
    return element;
  },
  visualEffect: function(element, effect, options) {
    element = $(element);
    var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
    new Effect[klass](element, options);
    return element;
  },
  highlight: function(element, options) {
    element = $(element);
    new Effect.Highlight(element, options);
    return element;
  }
};

$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
  'pulsate shake puff squish switchOff dropOut').each(
  function(effect) {
    Effect.Methods[effect] = function(element, options){
      element = $(element);
      Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
      return element;
    };
  }
);

$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
  function(f) { Effect.Methods[f] = Element[f]; }
);

Element.addMethods(Effect.Methods);

LowPro = {};
LowPro.Version = '0.5';
LowPro.CompatibleWithPrototype = '1.6';

if (Prototype.Version.indexOf(LowPro.CompatibleWithPrototype) != 0 && console && console.warn)
  console.warn("This version of Low Pro is tested with Prototype " + LowPro.CompatibleWithPrototype + 
                  " it may not work as expected with this version (" + Prototype.Version + ")");

if (!Element.addMethods) 
  Element.addMethods = function(o) { Object.extend(Element.Methods, o) };

// Simple utility methods for working with the DOM
DOM = {};

// DOMBuilder for prototype
DOM.Builder = {
  tagFunc : function(tag) {
    return function() {
      var attrs, children; 
      if (arguments.length>0) { 
        if (arguments[0].nodeName || 
          typeof arguments[0] == "string") 
          children = arguments; 
        else { 
          attrs = arguments[0]; 
          children = Array.prototype.slice.call(arguments, 1); 
        };
      }
      return DOM.Builder.create(tag, attrs, children);
    };
  },
  create : function(tag, attrs, children) {
    attrs = attrs || {}; children = children || []; tag = tag.toLowerCase();
    var el = new Element(tag, attrs);
    
    for (var i=0; i<children.length; i++) {
      if (typeof children[i] == 'string') 
        children[i] = document.createTextNode(children[i]);
      el.appendChild(children[i]);
    }
    return $(el);
  }
};

// Automatically create node builders as $tagName.
(function() { 
  var els = ("p|div|span|strong|em|img|table|tr|td|th|thead|tbody|tfoot|pre|code|" + 
             "h1|h2|h3|h4|h5|h6|ul|ol|li|form|input|textarea|legend|fieldset|" + 
             "select|option|blockquote|cite|br|hr|dd|dl|dt|address|a|button|abbr|acronym|" +
             "script|link|style|bdo|ins|del|object|param|col|colgroup|optgroup|caption|" + 
             "label|dfn|kbd|samp|var").split("|");
  var el, i=0;
  while (el = els[i++]) 
    window['$' + el] = DOM.Builder.tagFunc(el);
})();

DOM.Builder.fromHTML = function(html) {
  var root;
  if (!(root = arguments.callee._root))
    root = arguments.callee._root = document.createElement('div');
  root.innerHTML = html;
  return root.childNodes[0];
};



// Wraps the 1.6 contentloaded event for backwards compatibility
//
// Usage:
//
// Event.onReady(callbackFunction);
Object.extend(Event, {
  onReady : function(f) {
    if (document.body) f();
    else document.observe('dom:loaded', f);
  }
});

// Based on event:Selectors by Justin Palmer
// http://encytemedia.com/event-selectors/
//
// Usage:
//
// Event.addBehavior({
//      "selector:event" : function(event) { /* event handler.  this refers to the element. */ },
//      "selector" : function() { /* runs function on dom ready.  this refers to the element. */ }
//      ...
// });
//
// Multiple calls will add to exisiting rules.  Event.addBehavior.reassignAfterAjax and
// Event.addBehavior.autoTrigger can be adjusted to needs.
Event.addBehavior = function(rules) {
  var ab = this.addBehavior;
  Object.extend(ab.rules, rules);
  
  if (!ab.responderApplied) {
    Ajax.Responders.register({
      onComplete : function() {
        if (Event.addBehavior.reassignAfterAjax) 
          setTimeout(function() { ab.reload() }, 10);
      }
    });
    ab.responderApplied = true;
  }
  
  if (ab.autoTrigger) {
    this.onReady(ab.load.bind(ab, rules));
  }
  
};

Object.extend(Event.addBehavior, {
  rules : {}, cache : [],
  reassignAfterAjax : false,
  autoTrigger : true,
  
  load : function(rules) {
    for (var selector in rules) {
      var observer = rules[selector];
      var sels = selector.split(',');
      sels.each(function(sel) {
        var parts = sel.split(/:(?=[a-z]+$)/), css = parts[0], event = parts[1];
        $$(css).each(function(element) {
          if (event) {
            observer = Event.addBehavior._wrapObserver(observer);
            $(element).observe(event, observer);
            Event.addBehavior.cache.push([element, event, observer]);
          } else {
            if (!element.$$assigned || !element.$$assigned.include(observer)) {
              if (observer.attach) observer.attach(element);
              
              else observer.call($(element));
              element.$$assigned = element.$$assigned || [];
              element.$$assigned.push(observer);
            }
          }
        });
      });
    }
  },
  
  unload : function() {
    this.cache.each(function(c) {
      Event.stopObserving.apply(Event, c);
    });
    this.cache = [];
  },
  
  reload: function() {
    var ab = Event.addBehavior;
    ab.unload(); 
    ab.load(ab.rules);
  },
  
  _wrapObserver: function(observer) {
    return function(event) {
      if (observer.call(this, event) === false) event.stop(); 
    }
  }
  
});

Event.observe(window, 'unload', Event.addBehavior.unload.bind(Event.addBehavior));

// A silly Prototype style shortcut for the reckless
$$$ = Event.addBehavior.bind(Event);

// Behaviors can be bound to elements to provide an object orientated way of controlling elements
// and their behavior.  Use Behavior.create() to make a new behavior class then use attach() to
// glue it to an element.  Each element then gets it's own instance of the behavior and any
// methods called onxxx are bound to the relevent event.
// 
// Usage:
// 
// var MyBehavior = Behavior.create({
//   onmouseover : function() { this.element.addClassName('bong') } 
// });
//
// Event.addBehavior({ 'a.rollover' : MyBehavior });
// 
// If you need to pass additional values to initialize use:
//
// Event.addBehavior({ 'a.rollover' : MyBehavior(10, { thing : 15 }) })
//
// You can also use the attach() method.  If you specify extra arguments to attach they get passed to initialize.
//
// MyBehavior.attach(el, values, to, init);
//
// Finally, the rawest method is using the new constructor normally:
// var draggable = new Draggable(element, init, vals);
//
// Each behaviour has a collection of all its instances in Behavior.instances
//
var Behavior = {
  create: function() {
    var parent = null, properties = $A(arguments);
    if (Object.isFunction(properties[0]))
      parent = properties.shift();

      var behavior = function() { 
        var behavior = arguments.callee;
        if (!this.initialize) {
          var args = $A(arguments);

          return function() {
            var initArgs = [this].concat(args);
            behavior.attach.apply(behavior, initArgs);
          };
        } else {
          var args = (arguments.length == 2 && arguments[1] instanceof Array) ? 
                      arguments[1] : Array.prototype.slice.call(arguments, 1);

          this.element = $(arguments[0]);
          this.initialize.apply(this, args);
          behavior._bindEvents(this);
          behavior.instances.push(this);
        }
      };

    Object.extend(behavior, Class.Methods);
    Object.extend(behavior, Behavior.Methods);
    behavior.superclass = parent;
    behavior.subclasses = [];
    behavior.instances = [];

    if (parent) {
      var subclass = function() { };
      subclass.prototype = parent.prototype;
      behavior.prototype = new subclass;
      parent.subclasses.push(behavior);
    }

    for (var i = 0; i < properties.length; i++)
      behavior.addMethods(properties[i]);

    if (!behavior.prototype.initialize)
      behavior.prototype.initialize = Prototype.emptyFunction;

    behavior.prototype.constructor = behavior;

    return behavior;
  },
  Methods : {
    attach : function(element) {
      return new this(element, Array.prototype.slice.call(arguments, 1));
    },
    _bindEvents : function(bound) {
      for (var member in bound)
        if (member.match(/^on(.+)/) && typeof bound[member] == 'function')
          bound.element.observe(RegExp.$1, Event.addBehavior._wrapObserver(bound[member].bindAsEventListener(bound)));
    }
  }
};

Remote = Behavior.create({
  initialize: function(options) {
    if (this.element.nodeName == 'FORM') new Remote.Form(this.element, options);
    else new Remote.Link(this.element, options);
  }
});

Remote.Base = {
  initialize : function(options) {
    this.options = Object.extend({
      evaluateScripts : true
    }, options || {});
  },
  _makeRequest : function(options) {
    if (options.update) new Ajax.Updater(options.update, options.url, options);
    else new Ajax.Request(options.url, options);
    return false;
  }
}

Remote.Link = Behavior.create(Remote.Base, {
  onclick : function() {
    var options = Object.extend({ url : this.element.href, method : 'get' }, this.options);
    return this._makeRequest(options);
  }
});


Remote.Form = Behavior.create(Remote.Base, {
  onclick : function(e) {
    var sourceElement = e.element();
    
    if (['input', 'button'].include(sourceElement.nodeName.toLowerCase()) && 
        sourceElement.type == 'submit')
      this._submitButton = sourceElement;
  },
  onsubmit : function() {
    var options = Object.extend({
      url : this.element.action,
      method : this.element.method || 'get',
      parameters : this.element.serialize({ submit: this._submitButton.name })
    }, this.options);
    this._submitButton = null;
    return this._makeRequest(options);
  }
});

Observed = Behavior.create({
  initialize : function(callback, options) {
    this.callback = callback.bind(this);
    this.options = options || {};
    this.observer = (this.element.nodeName == 'FORM') ? this._observeForm() : this._observeField();
  },
  stop: function() {
    this.observer.stop();
  },
  _observeForm: function() {
    return (this.options.frequency) ? new Form.Observer(this.element, this.options.frequency, this.callback) :
                                      new Form.EventObserver(this.element, this.callback);
  },
  _observeField: function() {
    return (this.options.frequency) ? new Form.Element.Observer(this.element, this.options.frequency, this.callback) :
                                      new Form.Element.EventObserver(this.element, this.callback);
  }
});



/*jslint onevar: true, browser: true, undef: true, nomen: false, eqeqeq: true, plusplus: true, regexp: true */
/*global window, Event, Element, $, $$ */

var _loadedScripts = new Array();
var _load = function (name, callback) {
  if (_loadedScripts.include(name)) { if (callback) { callback(); } return; }
  _loadedScripts.push(name);
  
  var script = new Element('script', {'src': '/javascripts/' + name + '.js', type: 'text/javascript'});
  
  if (callback) {
    script.onload = callback;
    script.onreadystatechange = function () { if (this.readyState === 'complete' || this.readyState === 'loaded') { callback(); } };
  }
  
  $('body').insert({bottom: script});
};

var autoload = function (name, selector, callback) {
  Event.onReady(function () {
    
    if ($$(selector).length > 0) {
      _load(name, callback);
    }
  });
};

/*jslint onevar: true, browser: true, undef: true, nomen: false, eqeqeq: true, plusplus: true, regexp: true */
/*global Element, Event, Form, Prototype, ResizableTextarea, $, $$, $F, $break */

Object.extend(Form, {
  invalidFields: ['hideous', 'unlovely', 'horrible', 'frightful', 'awful', 'ghastly', 'vile', 'revolting'],
  
  findFirstElement: function(form) {
    var elements = Form.getElements(form).findAll(function(element) {
      return !('hidden' === element.type || element.disabled || Form.invalidFields.any(function (id) { return element.id === id; }));
    });
    
    return elements.findAll(function(element) {
      return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()) && !['radio', 'checkbox', 'submit'].include(element.type) && element.readAttribute('rel') !== 'nofocus';
    }).sortBy(function(element) { return element.tabIndex; }).first();
  },
  
  focusFirstElement: function(form) {
    return Form.Element.activate(Form.findFirstElement(form));
  },
  
  focusFirstElementBySelectors: function(form, selectors) {
    var input, focusElements;
    
    selectors.each(function (selector) {
      focusElements = $$(selector);
      if (focusElements.size() > 0) {
        input = focusElements[0];
        throw $break;
      }
    });

    if (input) {
      return Form.Element.activate(input);
    }
    
    return Form.focusFirstElement(form);
  },
  
  focusFirst: function (parentSelector) {
    var selector, forms;
    
    selector = 'form:not([rel~="nofocus"])';
    if (parentSelector) {
      selector = parentSelector + ' ' + selector;
    }
    
    forms = $$(selector);
    if (forms.size() > 0) {
      Form.focusFirstElementBySelectors(forms[0], ['input[class~=field-with-errors]','input[rel~=focus]']);
    }
  }
});


Object.extend(Form.Element, {
  getCaretPosition: function (el) {
    var selection;
    el = $(el);
    
    if (Prototype.Browser.IE) {
      selection = document.selection.createRange();
      selection.moveStart('character', -el.value.length);
      return el.value.length;
    }
    
    return el.selectionEnd;
  },
  
  setCaretPosition: function (el, position) {
    var selection;
    el = $(el);
    
    if (Prototype.Browser.IE) {
      selection = document.selection.createRange();
      selection.moveStart('character', -el.value.length);
      selection.moveStart('character', position);
      selection.moveEnd('character', 0);
      return selection.select();
    }
    
    el.selectionStart = position;
    el.selectionEnd = position;
    el.focus();
  },
  
  setValue: function (element, value) {
    var options = $(element).select('option');
    options.each(function (option) {
      if (option.value == value) {
        option.selected = '1';
        throw $break;
      }
    });
  }
});

Event.onReady(function () {
  Form.focusFirst();
});

var _writeAd = function (content) {
  var zone = content.match(/zoneid=(\d+)/);
  if (!zone) { return; }
  
  content = content.replace(/<script type='text\/javascript'><!--/, "<script type='text\/javascript'>");
  content = content.replace(/ox_swf\.write/, "ox_swf.addParam('wmode','opaque'); ox_swf.write"); //OpenX bug fix
  content = content.replace(/(ox_[0-9a-f]{32})/ig, '$1' + zone[1]); //OpenX bug fix
  
  zone = $$('.ad[zone=' + zone[1] + ']')[0];  
  zone.insert(content);
  
  if (zone.select('img').length > 0 && !zone.down('img[alt^=house], img[alt^=House]')) zone.next('p').show();
};

Event.addBehavior({
  '.ad.placeholder:click' : function () {
    $$('.ad.placeholder, .ad.placeholder + p').invoke('remove');
  },

  '.ad[zone]' : function () {
    document.write = _writeAd;

    var url = location.protocol + '//ads.alliancehealth.com/www/delivery/ajs.php';
    url += '?zoneid=' + this.readAttribute('zone');
    url += '&amp;n=' + this.readAttribute('named_cookie');
    url += '&amp;ugc=' + this.readAttribute('ugc_safe');
    url += '&amp;logged_in=' + (this.readAttribute('logged_in') || 'false');
    url += '&amp;cb=' + this.readAttribute('cache_hash');
    url += (document.charset ? '&amp;charset=' + document.charset : (document.characterSet ? '&amp;charset=' + document.characterSet : ''));
    url += ('&amp;loc=' + escape(window.location));

    if (!document.MAX_used) document.MAX_used = ',';
    if (document.MAX_used != ',') { url += ('&amp;exclude=' + document.MAX_used); }
    if (document.referrer) { url += ('&amp;referer=' + escape(document.referrer)); }
    if (document.context) { url += ('&amp;context=' + escape(document.context)); }
    if (document.mmm_fo) { url += '&amp;mmm_fo=1'; }

    this.appendChild(new Element('script', {'src': url, type: 'text/javascript'}));
  }
});

/*jslint onevar: true, browser: true, undef: true, nomen: false, eqeqeq: true, plusplus: true, regexp: true */
/*global Prototype, Class, Effect, Element, Event, Form, Ajax, $, $A, window */

var Modal = {};
Modal.Element = Class.create({
  initialize: function (name, options) {
    this.name = name;
    this.options = options;
  },
  
  element: function () {
    if (!this._element) {
      this._element = $$('div.modal.' + this.name)[0];

      if (!this._element) {
        this._element = new Element('div', {'class': 'modal ' + this.name, style: 'display:none;'});
        $(document.body).insert(this._element);
      }
      
      if (this.options.onClick) { this._element.observe('click', this.options.onClick); }
    }
    return this._element;
  },
  
  show: function (callback) {
    Effect.Appear(this.element(), { duration: this.options.duration, to: this.options.opacity, afterFinish: callback });
  },
  
  hide: function (callback) {
    Effect.Fade(this.element(), { duration: this.options.duration, from: this.options.opacity, afterFinish: callback });
  }
});

Modal.Window = new Modal.Element('window', { duration: 0.3, opacity: 1.0 });
Modal.Window.close = function () {
  var args = $A(arguments);
  if (args.last() && args.last().stop) { args.pop().stop(); }
  if (Modal.Window.request) { Modal.Window.request.abort(); }
  document.stopObserving('keydown', Modal.Window.onKeyDown);
  Modal.Window.hide();
  Modal.Overlay.hide(Modal.Overlay.reset);
};
Modal.Window.open = function (href) {
  var args = $A(arguments);
  if (args.last() && args.last().stop) { args.pop().stop(); }
  
  Modal.Window.onKeyDown = function (e) { if (e.keyCode == Event.KEY_ESC) { Modal.Window.close(); } };
  document.observe('keydown', Modal.Window.onKeyDown);
  
  Modal.Window.request = new Ajax.Updater(Modal.Window.element(), args.shift(), {
    method: 'get',
    evalScripts: true,
    onCreate: function () { Modal.Overlay.show(); },
    onFailure: function () { window.location = href.replace(/[?&]layout=dialog/, ''); },
    onSuccess: function (response) {
      Modal.Window.position();
      if (_gaq) { _gaq.push(['_trackPageview', href]); }
      Modal.Window.show(args.pop());
      Modal.Overlay.loaded();
    },
    onComplete: function(response)
    {
      if (Cufon) { Cufon.refresh(); }      
    }
  });
};
Modal.Window.position = function () {
  Modal.Window.element().setStyle({top: document.viewport.getScrollOffsets().top + 60 + 'px'});
};

Modal.Overlay = new Modal.Element('overlay', { duration: 0.5, opacity: 0.75, onClick: Modal.Window.close });
Modal.Overlay.loaded = function () { Modal.Overlay.element().addClassName('loaded'); };
Modal.Overlay.reset = function () { Modal.Overlay.element().removeClassName('loaded'); };

Ajax.Request.prototype.abort = function () {
  this.transport.onreadystatechange = Prototype.emptyFunction;
  this.transport.abort();
  if (Ajax.activeRequestCount > 0) { Ajax.activeRequestCount -= 1; }
};

Event.addBehavior({
  '.modal.window a[rel~=close]:click': function (e) { e.stop(); Modal.Window.close(); },
  'a[rel~=window]': function () {
    var href = this.href + (this.href.match(/\?/) ? '&' : '?') + 'layout=dialog';
    this.observe('click', Modal.Window.open.curry(href, Form.focusFirst.curry('.modal.window')));
  }
});

// Copyright (c) 2005-2009 Marty Haught, Thomas Fuchs
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/

if (!Control) var Control = { };

// options:
//  axis: 'vertical', or 'horizontal' (default)
//
// callbacks:
//  onChange(value)
//  onSlide(value)
Control.Slider = Class.create({
  initialize: function(handle, track, options) {
    var slider = this;

    if (Object.isArray(handle)) {
      this.handles = handle.collect( function(e) { return $(e) });
    } else {
      this.handles = [$(handle)];
    }

    this.track   = $(track);
    this.options = options || { };

    this.axis      = this.options.axis || 'horizontal';
    this.increment = this.options.increment || 1;
    this.step      = parseInt(this.options.step || '1');
    this.range     = this.options.range || $R(0,1);
    this.snapAfter = this.options.snapAfter;

    this.value     = 0; // assure backwards compat
    this.values    = this.handles.map( function() { return 0 });
    this.spans     = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
    this.options.startSpan = $(this.options.startSpan || null);
    this.options.endSpan   = $(this.options.endSpan || null);

    this.restricted = this.options.restricted || false;

    this.maximum   = this.options.maximum || this.range.end;
    this.minimum   = this.options.minimum || this.range.start;

    // Will be used to align the handle onto the track, if necessary
    this.alignX = parseInt(this.options.alignX || '0');
    this.alignY = parseInt(this.options.alignY || '0');

    this.trackLength = this.maximumOffset() - this.minimumOffset();

    this.handleLength = this.isVertical() ?
      (this.handles[0].offsetHeight != 0 ?
        this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
      (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
        this.handles[0].style.width.replace(/px$/,""));

    this.active   = false;
    this.dragging = false;
    this.disabled = false;

    if (this.options.disabled) this.setDisabled();

    // Allowed values array
    this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
    if (this.allowedValues) {
      this.minimum = this.allowedValues.min();
      this.maximum = this.allowedValues.max();
    }

    this.eventMouseDown = this.startDrag.bindAsEventListener(this);
    this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
    this.eventMouseMove = this.update.bindAsEventListener(this);

    // Initialize handles in reverse (make sure first handle is active)
    this.handles.each( function(h,i) {
      i = slider.handles.length-1-i;
      slider.setValue(parseFloat(
        (Object.isArray(slider.options.sliderValue) ?
          slider.options.sliderValue[i] : slider.options.sliderValue) ||
         slider.range.start), i);
      h.makePositioned().observe("mousedown", slider.eventMouseDown);
    });

    this.track.observe("mousedown", this.eventMouseDown);
    document.observe("mouseup", this.eventMouseUp);
    document.observe("mousemove", this.eventMouseMove);

    this.initialized = true;
  },
  dispose: function() {
    var slider = this;
    Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
    Event.stopObserving(document, "mouseup", this.eventMouseUp);
    Event.stopObserving(document, "mousemove", this.eventMouseMove);
    this.handles.each( function(h) {
      Event.stopObserving(h, "mousedown", slider.eventMouseDown);
    });
  },
  setDisabled: function(){
    this.disabled = true;
  },
  setEnabled: function(){
    this.disabled = false;
  },
  getNearestValue: function(value){
    if (this.allowedValues){
      if (value >= this.allowedValues.max()) return(this.allowedValues.max());
      if (value <= this.allowedValues.min()) return(this.allowedValues.min());

      var offset = Math.abs(this.allowedValues[0] - value);
      var newValue = this.allowedValues[0];
      this.allowedValues.each( function(v) {
        var currentOffset = Math.abs(v - value);
        if (currentOffset <= offset){
          newValue = v;
          offset = currentOffset;
        }
      });
      return newValue;
    }
    if (this.snapAfter && value >= this.snapAfter + 1) return this.range.end;
    if (value > this.range.end) return this.range.end;
    if (value < this.range.start) return this.range.start;
    return value;
  },
  setValue: function(sliderValue, handleIdx){
    if (!this.active) {
      this.activeHandleIdx = handleIdx || 0;
      this.activeHandle    = this.handles[this.activeHandleIdx];
      this.updateStyles();
    }
    handleIdx = handleIdx || this.activeHandleIdx || 0;
    if (this.initialized && this.restricted) {
      if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
        sliderValue = this.values[handleIdx-1];
      if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
        sliderValue = this.values[handleIdx+1];
    }
    sliderValue = this.getNearestValue(sliderValue);
    this.values[handleIdx] = sliderValue;
    this.value = this.values[0]; // assure backwards compat

    this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
      this.translateToPx(sliderValue);

    this.drawSpans();
    if (!this.dragging || !this.event) this.updateFinished();
  },
  setValueBy: function(delta, handleIdx) {
    this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
      handleIdx || this.activeHandleIdx || 0);
  },
  translateToPx: function(value) {
    return Math.round(
      ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
      (value - this.range.start)) + "px";
  },
  translateToValue: function(offset) {
    return ((offset/(this.trackLength-this.handleLength) *
      (this.range.end-this.range.start)) + this.range.start);
  },
  getRange: function(range) {
    var v = this.values.sortBy(Prototype.K);
    range = range || 0;
    return $R(v[range],v[range+1]);
  },
  minimumOffset: function(){
    return(this.isVertical() ? this.alignY : this.alignX);
  },
  maximumOffset: function(){
    return(this.isVertical() ?
      (this.track.offsetHeight != 0 ? this.track.offsetHeight :
        this.track.style.height.replace(/px$/,"")) - this.alignY :
      (this.track.offsetWidth != 0 ? this.track.offsetWidth :
        this.track.style.width.replace(/px$/,"")) - this.alignX);
  },
  isVertical:  function(){
    return (this.axis == 'vertical');
  },
  drawSpans: function() {
    var slider = this;
    if (this.spans)
      $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
    if (this.options.startSpan)
      this.setSpan(this.options.startSpan,
        $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
    if (this.options.endSpan)
      this.setSpan(this.options.endSpan,
        $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
  },
  setSpan: function(span, range) {
    if (this.isVertical()) {
      span.style.top = this.translateToPx(range.start);
      span.style.height = this.translateToPx(range.end - range.start + this.range.start);
    } else {
      span.style.left = this.translateToPx(range.start);
      span.style.width = this.translateToPx(range.end - range.start + this.range.start);
    }
  },
  updateStyles: function() {
    this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
    Element.addClassName(this.activeHandle, 'selected');
  },
  startDrag: function(event) {
    if (Event.isLeftClick(event)) {
      if (!this.disabled){
        this.active = true;

        var handle = Event.element(event);
        var pointer  = [Event.pointerX(event), Event.pointerY(event)];
        var track = handle;
        if (track==this.track) {
          var offsets  = this.track.cumulativeOffset();
          this.event = event;
          this.setValue(this.translateToValue(
           (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
          ));
          var offsets  = this.activeHandle.cumulativeOffset();
          this.offsetX = (pointer[0] - offsets[0]);
          this.offsetY = (pointer[1] - offsets[1]);
        } else {
          // find the handle (prevents issues with Safari)
          while((this.handles.indexOf(handle) == -1) && handle.parentNode)
            handle = handle.parentNode;

          if (this.handles.indexOf(handle)!=-1) {
            this.activeHandle    = handle;
            this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
            this.updateStyles();

            var offsets  = this.activeHandle.cumulativeOffset();
            this.offsetX = (pointer[0] - offsets[0]);
            this.offsetY = (pointer[1] - offsets[1]);
          }
        }
      }
      Event.stop(event);
    }
  },
  update: function(event) {
   if (this.active) {
      if (!this.dragging) this.dragging = true;
      this.draw(event);
      if (Prototype.Browser.WebKit) window.scrollBy(0,0);
      Event.stop(event);
   }
  },
  draw: function(event) {
    var pointer = [Event.pointerX(event), Event.pointerY(event)];
    var offsets = this.track.cumulativeOffset();
    pointer[0] -= this.offsetX + offsets[0];
    pointer[1] -= this.offsetY + offsets[1];
    this.event = event;
    this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
    if (this.initialized && this.options.onSlide)
      this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
  },
  endDrag: function(event) {
    if (this.active && this.dragging) {
      this.finishDrag(event, true);
      Event.stop(event);
    }
    this.active = false;
    this.dragging = false;
  },
  finishDrag: function(event, success) {
    this.active = false;
    this.dragging = false;
    this.updateFinished();
  },
  updateFinished: function() {
    if (this.initialized && this.options.onChange)
      this.options.onChange(this.values.length>1 ? this.values : this.value, this);
    this.event = null;
  }
});

String.prototype.truncateWords = function (length) {
  var words, joined_words;
  
  words = this.split(/\s+/);
  joined_words = words.slice(0, length).join(' ');
  
  if (words.length > length) {
    joined_words = joined_words.replace(/[^.!?)a-z"']$/, '');
    if (joined_words.match(/[^\.!?]$/)) {
      joined_words += 'â€¦';
    }
  }
  
  return joined_words;
};

Event.addBehavior({
  'input[truncate], textarea[truncate]' : function () {
    var handle, track, text, callback, slider, maximum, buffer;
    
    wrapper = new Element('div', {'class': 'slider'});
    handle  = new Element('div', {'class': 'handle'});
    track   = new Element('div', {'class': 'track'});
    text    = new Element('span', {'class': 'text'});
    
    track.insert(handle);
    wrapper.insert(text);
    wrapper.insert(track);
    
    this.insert({ after: wrapper });
    this.writeAttribute('originalValue', $F(this));

    maximum = Math.min(this.readAttribute('originalValue').split(/\s+/).length, 150);
    buffer  = 2;
    
    callback = function (length) {
      length = parseInt(length, 10);
      
      if (length > maximum) {
        // slider.setValue(maximum + buffer, null, true);
        this.value = this.readAttribute('originalValue');
        text.innerHTML = 'All words';
        
      } else {
        this.value = this.readAttribute('originalValue').truncateWords(length);
        text.innerHTML = length + ' words';
      }
    }.bind(this);
    
    // all.observe('click', function (e) {
    //   e.stop();
    //   slider.setValue(maximum);
    //   this.value = this.readAttribute('originalValue');
    //   text.hide();
    //   all.hide();
    // }.bind(this));
    
    (function () {
      slider = new Control.Slider(handle, track, { range: $R(5, maximum + buffer), onSlide: callback, onChange: callback, snapAfter: maximum});
      slider.setValue(this.readAttribute('truncate'));
    }.bind(this)).delay(0.1);
  }
});

Event.addBehavior({
  '.HwFAQQuestion:click' : function () {
    var parent = this.up();
    parent[parent.hasClassName('open') ? 'removeClassName' : 'addClassName']('open');
  },
  
  'ul.slider li:click, li.HwAnswer:click, .HwBooleanQuestion input:click' : function () {
    if (this.hasClassName('selected')) { return; }
    this.up().select(this.tagName).invoke('removeClassName', 'selected');
    this.addClassName('selected');
  }
});

// see, you can encapsulate all of this behavior in one function...
function buildURL(obj) {
  var path = "";
  if(obj.doc_hwid != "search") {
    path = "/health-center/documents/" + obj.doc_hwid + "?section=" + obj.sect_hwid;
  } 
  else {
    // Redirect to index for 'searching'
    path = "/health-center/";
  }
  return path;
}

function GetSymptomCheckerURL(docHWID, sectHWID) {
  var obj = { "doc_hwid" : docHWID, "sect_hwid" : sectHWID };
  return buildURL(obj);
}

function hwGenerateContentLink(obj) {
  var collection = { "doc_hwid" : obj.documentHref, "sect_hwid" : obj.sectionHref };
  return buildURL(collection);
}

// HOW MANY OF THESE DO WE NEED?!
var org = { healthwise: {} };
org["healthwise"] = {};
org.healthwise["sx"] = {};
org.healthwise["public"] = {};

org.healthwise.sx.displayLink = function(link) {
  var path = "";
  var obj = { "doc_hwid" : link.documentHref, "sect_hwid" : link.sectionHref };
  path = buildURL(obj);
  document.location.href = path;
}

org.healthwise.public.getURL = function (docType, docHwid, sectHwid) {
  var obj = { "doc_hwid" : docHwid, "sect_hwid" : sectHwid };
  return buildURL(obj); 
}

// Hack to fix flash unloading on IE
if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) {
  window.attachEvent("onbeforeunload",fcRemoveFlash);
  function fcRemoveFlash() {
    var arr = document.all.tags("object");
    if (arr && arr.length) {
      for (var i=arr.length-1; 0<=i; i--) {
        arr[i].removeNode(true);
      }
    }
  }
}


   
// Some Healthwise engineer was a dumbass.
var getIToolConfig = function () {
  return {
    "fetalDevelopment" : {
    "months": {
      "month": [
          {
              "name": "month1",
              "linkContent": [
                  {
                      "documentType": "MedicalTest",
                      "description": "Pregnancy test/hCG",
                      "rank": "1",
                      "documentHref": "hw42062",
                      "sectionHref": "hw42065"
                  },
                  {
                      "documentType": "MedicalTest",
                      "description": "Home pregnancy tests",
                      "rank": "1",
                      "documentHref": "hw227606",
                      "sectionHref": "hw227609"
                  },
                  {
                      "documentType": "Special",
                      "description": "Pregnancy",
                      "rank": "1",
                      "documentHref": "hw197814",
                      "sectionHref": "hw197816"
                  },
                  {
                      "documentType": "Frame",
                      "description": "Preparing for a healthy pregnancy",
                      "rank": "3",
                      "documentHref": "hw195050",
                      "sectionHref": "hw195050-sec"
                  },
                  {
                      "documentType": "Definition",
                      "description": "How to count the weeks",
                      "rank": "4",
                      "documentHref": "tn10321",
                      "sectionHref": "tn10321-sec"
                  }
              ]
          },
          {
              "name": "month2",
              "linkContent": [
                  {
                      "documentType": "MedicalTest",
                      "description": "Pregnancy test/hCG",
                      "rank": "1",
                      "documentHref": "hw42062",
                      "sectionHref": "hw42065"
                  },
                  {
                      "documentType": "MedicalTest",
                      "description": "Home pregnancy tests",
                      "rank": "1",
                      "documentHref": "hw227606",
                      "sectionHref": "hw227609"
                  },
                  {
                      "documentType": "Special",
                      "description": "Pregnancy",
                      "rank": "1",
                      "documentHref": "hw197814",
                      "sectionHref": "hw197816"
                  },
                  {
                      "documentType": "Frame",
                      "description": "Preparing for a healthy pregnancy",
                      "rank": "3",
                      "documentHref": "hw195050",
                      "sectionHref": "hw195050-sec"
                  },
                  {
                      "documentType": "Definition",
                      "description": "How to count the weeks",
                      "rank": "4",
                      "documentHref": "tn10321",
                      "sectionHref": "tn10321-sec"
                  }
              ]
          },
          {
              "name": "month3",
              "linkContent": [
                  {
                      "documentType": "Special",
                      "description": "Birth defects testing",
                      "rank": "1",
                      "documentHref": "uf6260",
                      "sectionHref": "uf6261"
                  },
                  {
                      "documentType": "MedicalTest",
                      "description": "Chorionic villus sampling (CVS)",
                      "rank": "1",
                      "documentHref": "hw4104",
                      "sectionHref": "hw4107"
                  },
                  {
                      "documentType": "DecisionPoint",
                      "description": "Should I have chorionic villus sampling (CVS)?",
                      "rank": "2",
                      "documentHref": "tb1905",
                      "sectionHref": "tb1905-Intro"
                  },
                  {
                      "documentType": "Definition",
                      "description": "How to count the weeks",
                      "rank": "4",
                      "documentHref": "tn10321",
                      "sectionHref": "tn10321-sec"
                  }
              ]
          },
          {
              "name": "month4",
              "linkContent": [
                  {
                      "documentType": "Special",
                      "description": "Birth defects testing",
                      "rank": "1",
                      "documentHref": "uf6260",
                      "sectionHref": "uf6261"
                  },
                  {
                      "documentType": "Frame",
                      "description": "Maternal serum triple or quadruple screen",
                      "rank": "3",
                      "documentHref": "ta7038",
                      "sectionHref": "ta7038-sec"
                  },
                  {
                      "documentType": "MedicalTest",
                      "description": "Amniocentesis",
                      "rank": "1",
                      "documentHref": "hw1810",
                      "sectionHref": "hw1813"
                  },
                  {
                      "documentType": "DecisionPoint",
                      "description": "Should I have the maternal serum triple or quadruple test (triple or quad screen)?",
                      "rank": "2",
                      "documentHref": "aa21828",
                      "sectionHref": "aa21828-Intro"
                  },
                  {
                      "documentType": "DecisionPoint",
                      "description": "Should I have an amniocentesis?",
                      "rank": "2",
                      "documentHref": "aa103080",
                      "sectionHref": "aa103080-Intro"
                  },
                  {
                      "documentType": "Definition",
                      "description": "How to count the weeks",
                      "rank": "4",
                      "documentHref": "tn10321",
                      "sectionHref": "tn10321-sec"
                  }
              ]
          },
          {
              "name": "month5",
              "linkContent": [
                  {
                      "documentType": "Special",
                      "description": "Birth defects testing",
                      "rank": "1",
                      "documentHref": "uf6260",
                      "sectionHref": "uf6261"
                  },
                  {
                      "documentType": "Frame",
                      "description": "Maternal serum triple or quadruple screen",
                      "rank": "3",
                      "documentHref": "ta7038",
                      "sectionHref": "ta7038-sec"
                  },
                  {
                      "documentType": "MedicalTest",
                      "description": "Amniocentesis",
                      "rank": "1",
                      "documentHref": "hw1810",
                      "sectionHref": "hw1813"
                  },
                  {
                      "documentType": "MedicalTest",
                      "description": "Fetal ultrasound",
                      "rank": "1",
                      "documentHref": "hw4693",
                      "sectionHref": "hw4696"
                  },
                  {
                      "documentType": "DecisionPoint",
                      "description": "Should I have an early fetal ultrasound?",
                      "rank": "2",
                      "documentHref": "aa22092",
                      "sectionHref": "aa22092-Intro"
                  },
                  {
                      "documentType": "DecisionPoint",
                      "description": "Should I have an amniocentesis?",
                      "rank": "2",
                      "documentHref": "aa103080",
                      "sectionHref": "aa103080-Intro"
                  },
                  {
                      "documentType": "DecisionPoint",
                      "description": "Should I have the maternal serum triple or quadruple test (triple or quad screen)?",
                      "rank": "2",
                      "documentHref": "aa21828",
                      "sectionHref": "aa21828-Intro"
                  },
                  {
                      "documentType": "Definition",
                      "description": "How to count the weeks",
                      "rank": "4",
                      "documentHref": "tn10321",
                      "sectionHref": "tn10321-sec"
                  }
              ]
          },
          {
              "name": "month6",
              "linkContent": [
                  {
                      "documentType": "Special",
                      "description": "Premature infant",
                      "rank": "1",
                      "documentHref": "tn5684",
                      "sectionHref": "tn5687"
                  },
                  {
                      "documentType": "Special",
                      "description": "What to Expect When You Have an Extremely Premature Infant",
                      "rank": "1",
                      "documentHref": "zx3825",
                      "sectionHref": "zx3826"
                  },
                  {
                      "documentType": "Definition",
                      "description": "How to count the weeks",
                      "rank": "4",
                      "documentHref": "tn10321",
                      "sectionHref": "tn10321-sec"
                  }
              ]
          },
          {
              "name": "month7",
              "linkContent": [
                  {
                      "documentType": "Special",
                      "description": "Premature infant",
                      "rank": "1",
                      "documentHref": "tn5684",
                      "sectionHref": "tn5687"
                  },
                  {
                      "documentType": "Special",
                      "description": "What to Expect When You Have an Extremely Premature Infant",
                      "rank": "1",
                      "documentHref": "zx3825",
                      "sectionHref": "zx3826"
                  },
                  {
                      "documentType": "Frame",
                      "description": "Kick counts",
                      "rank": "3",
                      "documentHref": "aa107042",
                      "sectionHref": "aa107042-sec"
                  },
                  {
                      "documentType": "Definition",
                      "description": "How to count the weeks",
                      "rank": "4",
                      "documentHref": "tn10321",
                      "sectionHref": "tn10321-sec"
                  }
              ]
          },
          {
              "name": "month8",
              "linkContent": [
                  {
                      "documentType": "Special",
                      "description": "Premature infant",
                      "rank": "1",
                      "documentHref": "tn5684",
                      "sectionHref": "tn5687"
                  },
                  {
                      "documentType": "Frame",
                      "description": "Kick counts",
                      "rank": "3",
                      "documentHref": "aa107042",
                      "sectionHref": "aa107042-sec"
                  },
                  {
                      "documentType": "Definition",
                      "description": "How to count the weeks",
                      "rank": "4",
                      "documentHref": "tn10321",
                      "sectionHref": "tn10321-sec"
                  }
              ]
          },
          {
              "name": "month9",
              "linkContent": [
                  {
                      "documentType": "Frame",
                      "description": "Kick counts",
                      "rank": "3",
                      "documentHref": "aa107042",
                      "sectionHref": "aa107042-sec"
                  },
                  {
                      "documentType": "Special",
                      "description": "Premature infant",
                      "rank": "1",
                      "documentHref": "tn5684",
                      "sectionHref": "tn5687"
                  },
                  {
                      "documentType": "Special",
                      "description": "Labor, delivery, and postpartum period",
                      "rank": "1",
                      "documentHref": "tn9759",
                      "sectionHref": "tn9760"
                  },
                  {
                      "documentType": "Definition",
                      "description": "How to count the weeks",
                      "rank": "4",
                      "documentHref": "tn10321",
                      "sectionHref": "tn10321-sec"
                  }
              ]
          },
          {
              "name": "month10",
              "linkContent": [
                  {
                      "documentType": "Frame",
                      "description": "Kick counts",
                      "rank": "3",
                      "documentHref": "aa107042",
                      "sectionHref": "aa107042-sec"
                  },
                  {
                      "documentType": "Special",
                      "description": "Labor, delivery, and postpartum period",
                      "rank": "1",
                      "documentHref": "tn9759",
                      "sectionHref": "tn9760"
                  },
                  {
                      "documentType": "Definition",
                      "description": "How to count the weeks",
                      "rank": "4",
                      "documentHref": "tn10321",
                      "sectionHref": "tn10321-sec"
                  }
              ]
          } 
      ]
    }
    }
  };
};

/*jslint onevar: true, browser: true, undef: true, nomen: false, eqeqeq: true, plusplus: true, regexp: true */
/*global Event, Form, Control, Tabs, Modal, $, $$, autoload */

Event.addBehavior.reassignAfterAjax = true;

Event.addBehavior({
  'a.flash:click' : function () { this.hide(); return false; },
  '#logo:focus, a.button:focus' : function () { this.blur(); },
  
  'form.search input.query:keyup' : function () {
    var button = this.next('input.button');
    if (button.hasClassName('close')) {
      button.removeClassName('close');
      button.addClassName('search');
    }
  },
  
  'form.search:submit' : function () {
    if (this.down('input.button').hasClassName('close')) {
      var label = this.down('label.default');
      label.innerHTML = 'Clearing your search&hellip;';
      
      this.down('input.query').clear().disable();
      this.down('input[name=by]').remove();
      label.show();
    }
  },
  
  'span.user-link:mouseover' : function () {
    if (true) return;
    if (this.up('.tooltip')) return;

    userLink = function () {
      var href = this.down('a').href;
      var insertUserTooltip = function () {
        userLinkRemover = (new PeriodicalExecuter(function () { $$('span.user-link .tooltip').invoke('remove'); }, 1));
        this.insert(userTooltips[href]);
      }.bind(this);
      
      if (userTooltips[href]) { return insertUserTooltip(); }
      
      new Ajax.Request(href, { method: 'get', onSuccess: function (response) {
        userTooltips[href] = response.responseText;
        insertUserTooltip();
      }});
    }.bind(this).delay(0.5);
  },
  
  'span.user-link:mouseout' : function () {
    if (false) clearTimeout(userLink);
  },
  
  '.pull-tab:click' : function () {
    var handler, toggle = function (show) {
      this[show ? 'addClassName' : 'removeClassName']('active');
      setTimeout(function () { document[show ? 'observe' : 'stopObserving']('click', handler); }, 0.1);
    }.bind(this);
    
    handler = toggle.curry(false);
    toggle(true);
  },
  
  '.container.featured:click, .grid.featured:click, table.featured tr:click, p.notification.show-comments:click' : function () {
    var url = this.down('a.title').href;
    if (url) window.location = url;
  }
});

userTooltips = {};

Event.onReady(function () {
  document.cookie = 'timezone=' + (new Date()).getTimezoneOffset() + '; path=/';
});


autoload('forms', 'form.bling, textarea[default]');
autoload('bling/datetime-basic', "select[name$='(1i)]']");
autoload('resizable-textarea', 'textarea.resizable');
autoload('blurb', '.blurb');
autoload('iphone-style-checkboxes', 'input[type=checkbox].slider');



function highlight () {
  var terms = $$($A(arguments).map(function (term) { return 'span[term="' + term + '"]' }).join(', '));
  $$('span.highlight.active').each(function (span) { if (terms.include(span)) { return; } new Effect.MorphClass(span, { fromClass: 'active', duration: 0.1 }); });
  terms.each(function (span) { new Effect.MorphClass(span, { toClass: 'active magnified', duration: 0.1, afterFinish: function () { new Effect.MorphClass(span, { fromClass: 'magnified', duration: 0.2 }); } }); });
}

/*jslint onevar: true, browser: true, undef: true, nomen: false, eqeqeq: true, plusplus: true, regexp: true */
/*global $, $$, $H, $F, Class, Element, Event, Form, Ajax, Prototype */

var TagsList = Class.create({
  modifierKeys: [9, 16, 17, 18, 27, 32, 37, 39, 46, 109, 224],

  initialize: function (formInput, options) {
    this.options = {
      sources: [TagsList.Sources.Default],
      
      separator: ',',
      fieldSeparator: ';',
      charWidth: 9,
      maximum: null,
      unique: true,
      
      containerClass: 'tags-list',
      tagsClass: 'tags',
      tagClass: 'tag',
      closeButtonClass: 'close',
      selectedClass: 'selected',
      messageClass: 'message',

      errorClass: 'field-with-errors',
      modifierKeys: [],
      message: null
    };
    Object.extend(this.options, options || {});
    
    this.modifierKeys = this.modifierKeys.concat(this.options.modifierKeys);
    
    this.tags = $H();
    this.els = {};
    this.els.formInput = $(formInput);
    
    this.createElements();
    this.initializeSources();    
    this.attachEvents();
    this.prepopulate();
    this.select(this.els.inputWrapper);
  },
  
  initializeSources: function () {
    if (this.options.formatters) { this.options.sources.unshift(TagsList.Sources.Formatter); }
    
    this.sources = [];
    this.options.sources.each(function (source) {
      this.sources.push(new source(this, this.options));
    }, this);
  },
  
  createElements: function () {
    this.els.container = new Element('div', { 'class' : this.options.containerClass });
    this.els.tags = new Element('ul', { 'class': this.options.tagsClass });
    this.els.input = new Element('input', { 'type': 'text' });
    this.els.inputWrapper = new Element('li');
    
    if (this.els.formInput.hasClassName(this.options.errorClass)) {
      this.els.input.addClassName(this.options.errorClass);
    }
    
    var hiddenInput = new Element('input', { type: 'hidden', name: this.els.formInput.name, id: this.els.formInput.id, value: $F(this.els.formInput) });
    this.els.formInput.replace(hiddenInput);
    this.els.formInput = hiddenInput;
    this.els.formInput.insert({ after: this.els.container });
    
    if (this.options.message) {
      this.els.message = new Element('div', { 'class': this.options.messageClass, 'style': 'display:none;' });
      this.els.message.insert((new Element('p')).update(this.options.message));
      this.els.container.insert(this.els.message);
    }
    
    this.els.tags.insert(this.els.inputWrapper);
    this.els.inputWrapper.insert(this.els.input);
    this.resize();
    
    this.els.container.insert(this.els.tags);
    
    if (!Prototype.Browser.IE) { return; } // IE has some strange z-index issues
    this.els.container.ancestors().each(function (a) { a.style.zIndex = 100; });
  },
  
  prepopulate: function () {
    var entry, text;
    if ((text = $F(this.els.formInput)).blank()) { return; }
  
    text.split(this.options.separator).each(function (pair) {
      entry = pair.split(this.options.fieldSeparator);
      this.add(entry[0], (entry[1] || entry[0]));
    }, this);
  },
  
  attachEvents: function () {
    this.els.input.observe('keydown', this.keydown.bind(this));    
    this.els.input.observe((Prototype.Browser.Gecko ? 'keypress' : 'keydown'), this.keypress.bind(this));
    this.els.input.observe('keyup', this.resize.bind(this));
    this.els.container.observe('click', this.els.input.activate.bindAsEventListener(this.els.input));
    this.els.input.observe('blur', this.accept.bind(this));
    
    if (!this.els.message) { return; }
    this.els.input.observe('focus', this.els.message.show.bind(this.els.message));
    this.els.input.observe('blur', this.els.message.hide.bind(this.els.message));
  },
  
  keydown: function (event) {
    switch (event.keyCode) {
      case Event.KEY_COMMA:
      case Event.KEY_RETURN:
        event.stop();
        return this.accept(event);
              
      case Event.KEY_BACKSPACE:
        if (!this.caretAtFront()) { return; }
        event.stop();
        
        if (this.tagSelected()) {
          return this.reject(event);
        }
        
        return this.select(this.current.previous());
      case Event.KEY_RIGHT:
      case Event.KEY_LEFT:
        return;
        
      default:
        if (this.invalidKeyCode(event.keyCode)) {
          return event.stop();
        } else if (this.tagSelected()) {
          this.select(this.els.inputWrapper);
        }
    }
  },
  
  keypress: function (event) {
    switch (event.keyCode) {
      case Event.KEY_RIGHT:
        if (this.caretAtFront() && this.tagSelected()) {
          event.stop();
          this.select(this.current.next());
        }
        return;
      case Event.KEY_LEFT:
        if (this.caretAtFront()) {
          event.stop();
          this.select(this.current.previous());
        }
        return;
    }
  },
  
  accept: function (event) {
    var result;

    this.sources.each(function (source) {
      if (!source.add) { return; }
      result = result || source.add(event);
    }, this);
    
    if (result) { this.add(result.name, result.value); }
  },
  
  reject: function (event) {
    var result;
    this.sources.each(function (source) {
      if (!source.remove) { return; }
      result = result || source.remove(event);
    }, this);
    result = result || this.current;
    if (result) { this.remove(result); }
  },
  
  resize: function () {
    this.els.input.style.width = Math.min(($F(this.els.input).length + 3) * this.options.charWidth, this.els.container.getWidth() - 12) + 'px';
  },
  
  add: function (name, value) {
    if (!this.allowAdd(name, value)) { return; }
    
    var tag, closeButton;
    
    closeButton = new Element('a', { 'class': this.options.closeButtonClass });
    closeButton.observe('click', function (event) { event.stop(); this.remove(tag); }.bind(this));
    
    tag = new Element('li', { 'class': this.options.tagClass }).update(name);
    tag.writeAttribute('value', value);
    tag.observe('click', this.select.bind(this, tag));
    tag.insert(closeButton);

    this.query = null;
    this.els.input.value = '';
    
    this.tags.set(value, tag);
    this.els.tags.insert(tag);
    this.els.tags.insert(this.els.inputWrapper);
    
    this.els.input.activate();
    this.updateInput();
    
    this.sources.each(function (source) {
      if (!source.added) { return; }
      source.added(name, value);
    });
  },
  
  remove: function (tag) {
    if (this.current === tag) {
      this.select(tag.previous() || tag.next());
    }
    tag.remove();
    this.tags.unset(tag.readAttribute('value'));
    this.els.input.activate();
    this.updateInput();
    
    this.sources.each(function (source) {
      if (!source.removed) { return; }
      source.removed(tag.readAttribute('name'), tag.readAttribute('value'));
    }, this);
  },
  
  allowAdd: function (name, value) {
    if (this.options.maximum && this.tags.keys().length >= this.options.maximum) { return false; }
    if (this.options.unique && this.tags.get(value)) { return false; }
    return true;
  },
  
  select: function (tag) {
    if (!tag) { return; }
    this.current = tag;
    this.els.container.select('li').invoke('removeClassName', this.options.selectedClass);
    tag.addClassName(this.options.selectedClass);
  },

  updateInput: function () {
    this.els.formInput.value = this.tags.keys().join(this.options.separator);
  },
  
  invalidKeyCode: function (keyCode) {
    return (keyCode < 48 || (keyCode > 57 && keyCode < 65) || keyCode > 90) && !this.modifierKeys.include(keyCode);
  },
  
  caretAtFront: function () {
    return Form.Element.getCaretPosition(this.els.input) === 0;
  },
  
  tagSelected: function () {
    return this.current.hasClassName(this.options.tagClass);
  }
});

TagsList.Sources = {};
TagsList.Sources.Default = Class.create({
  initialize: function (tagsList) {
    this.tagsList = tagsList;
  },
  
  add: function () {
    if ($F(this.tagsList.els.input).blank()) { return; }
    return { name: $F(this.tagsList.els.input), value: $F(this.tagsList.els.input) };
  }
});

TagsList.Sources.Formatter = Class.create({
  initialize: function (tagsList, options) {
    this.tagsList = tagsList;
    this.formatters = options.formatters;
  },
  
  add: function () {
    var value = $F(this.tagsList.els.input);
    if (value.blank()) { return; }

    value = this.formatters.inject(value, function (result, formatter) {
      if (formatter instanceof Function)
        return formatter(result);
      else if (formatter instanceof Array)
        return result.replace(formatter[0], formatter[1]);
      else if (formatter instanceof RegExp)
        return result.replace(formatter, '');
      
      return result;  
    });
    
    this.tagsList.els.input.value = value;
  }
});

TagsList.Sources.Cloud = Class.create({
  initialize: function (tagsList, options) {
    this.options = {
      cloudTagSelector: 'li.tag'
    };
    Object.extend(this.options, options || {});
    
    this.tagsList = tagsList;
    this.tags = $$(this.options.cloudTagSelector);
    
    this.attachEvents();
  },
  
  attachEvents: function () {
    this.tags.each(function (tag) {
      tag.observe('click', this.toggle.bind(this, tag));
    }, this);
  },
  
  added: function (name, value) {
    this.tags.each(function (tag) {
      if (tag.innerHTML === value) {
        tag.addClassName(this.options.selectedClass);
      }
    }, this);
  },
  
  removed: function (name, value) {
    this.tags.each(function (tag) {
      if (tag.innerHTML === value) {
        tag.removeClassName(this.options.selectedClass);
      }
    }, this);
  },
  
  toggle: function (tag) {
    if (tag.hasClassName(this.options.selectedClass)) {
      return this.tagsList.remove(this.tagsList.tags.get(tag.innerHTML));
    }
    this.tagsList.add(tag.innerHTML, tag.innerHTML);
  }
});

TagsList.Sources.Remote = Class.create({
  initialize: function (tagsList, options) {
    this.options = {
      remotePath: '/',
      remoteName: 'name',
      remoteValue: 'value',
      remoteParameters: Prototype.emptyFunction,

      spinnerPath: '/images/platform/icons/spinner.gif',
      spinnerClass: 'spinner',

      maxResults: 6,
      delay: 0.2,
      
      resultsClass: 'results',
      highlightTag: '<strong>#{1}</strong>'
    };  
    Object.extend(this.options, options || {});
    
    this.els = {};
    this.tagsList = tagsList;
    
    this.createElements();
    this.attachEvents();
  },
  
  createElements: function () {
    this.els.results = new Element('ul', { 'class': this.options.resultsClass, 'style': 'display:none;' });
    this.els.spinner = new Element('img', { 'src' : this.options.spinnerPath, 'class': this.options.spinnerClass, 'style': 'display:none;' });
    
    this.tagsList.els.container.insert({ top: this.els.results });
    this.tagsList.els.container.insert({ top: this.els.spinner });
  },
  
  attachEvents: function () {
    this.tagsList.els.input.observe((Prototype.Browser.Gecko ? 'keypress' : 'keydown'), this.keypress.bind(this));
    this.tagsList.els.input.observe('keyup', this.keyup.bind(this));
    document.observe('mousedown', this.findBlurTarget.bind(this));
    this.tagsList.els.input.observe('blur', this.blur.bind(this));
  },

  blur: function (event) {
    if (!this.hasFocus) { this.hide(); }
    this.hasFocus = false;
  },
  
  findBlurTarget: function(event) {
    if (event.element().up('.' + this.options.containerClass)) {
      this.hasFocus = true;
    }
  },
  
  keyup: function (event) {
    var query = $F(this.tagsList.els.input);
    
    if (this.query !== query) {
      if (this.searchTimeout) { clearTimeout(this.searchTimeout); }
      this.searchTimeout = this.search.bind(this).delay(this.options.delay, query);
    }
    this.query = query;
  },
  
  keypress: function (event) {
    switch (event.keyCode) {
      case Event.KEY_DOWN:
        event.stop();
        if (this.current) { this.select(this.current.next()); }
        return;

      case Event.KEY_UP:
        event.stop();
        if (this.current) { this.select(this.current.previous()); }
        return;
    }
  },
  
  add: function (event) {
    if (!(this.els.results.visible() && this.current)) { return; }
    this.hide();
    
    if (event.keyCode === Event.KEY_COMMA) { return; }
    return { name: this.current.readAttribute('name'), value: this.current.readAttribute('value') };
  },
  
  search: function (query) {
    if (query.blank()) { return this.hide(); }
    if (this.request) { this.request.abort(); }
    this.els.spinner.show();
    this.request = new Ajax.Request(this.options.remotePath, { parameters: this.options.remoteParameters.bind(this)(query), method: 'get', onSuccess: this.show.bind(this) });
  },
  
  show: function (transport) {
    var results, el;
    
    this.els.results.update('');
    
    results = transport.responseText.evalJSON().slice(0, this.options.maxResults);
    if (results.length === 0) { return this.hide(); }

    results.each(function (result) {
      el = (new Element('li')).update(this.highlight(result[this.options.remoteName]));
      el.writeAttribute('name', result[this.options.remoteName]);
      el.writeAttribute('value', result[this.options.remoteValue]);
      el.observe('mouseover', this.select.bind(this, el));
      el.observe('click', this.tagsList.accept.bind(this.tagsList));
      this.els.results.insert(el);
    }, this);
    
    this.select(this.els.results.down('li'));
    this.els.results.show();
    this.els.spinner.hide();
    if (this.tagsList.els.message) {
      this.tagsList.els.message.hide();
    }
  },
  
  hide: function () {
    this.els.results.hide();
    this.els.spinner.hide();
  },
  
  highlight: function (text) {
    if (this.query.blank()) { return text; }
    var query = this.query.replace(/&(?:amp;)?/, '&(?:amp;)?');
    return text.sub(new RegExp('(' + query + ')','i'), this.options.highlightTag);
  },
  
  select: function (result) {
    if (!result) { return; }
    this.current = result;
    this.els.results.select('li').invoke('removeClassName', this.options.selectedClass);
    result.addClassName(this.options.selectedClass);
  }
});

Event.KEY_COMMA = 188;
Ajax.Request.prototype.abort = function () {
  this.transport.onreadystatechange = Prototype.emptyFunction;
  this.transport.abort();
  if (Ajax.activeRequestCount > 0) { Ajax.activeRequestCount -= 1; }
};

/*!
 * The following copyright notice may not be removed under any circumstances.
 * 
 * Copyright:
 * Copyright © 1991, 1992, 2002 Adobe Systems Incorporated.  All Rights Reserved.
 * © 1981, 2002 Heidelberger Druckmaschinen AG. All rights reserved.
 * 
 * Trademark:
 * PMN Caecilia is a trademark of Heidelberger Druckmaschinen AG, exclusively
 * licensed through Linotype Library GmbH, and may be registered in certain
 * jurisdictions.
 * 
 * Full name:
 * CaeciliaLTStd-Bold
 * 
 * Designer:
 * Peter Matthias Noordzij
 * 
 * Vendor URL:
 * http://www.adobe.com/type
 * 
 * License information:
 * http://www.adobe.com/type/legal.html
 */
Cufon.registerFont({"w":234,"face":{"font-family":"Caecilia LT Std","font-weight":700,"font-stretch":"normal","units-per-em":"396","panose-1":"0 0 8 0 0 0 0 0 0 0","ascent":"305","descent":"-91","x-height":"5","bbox":"-29 -334 437 108","underline-thickness":"19.8","underline-position":"-19.8","stemh":"32","stemv":"40","unicode-range":"U+0020-U+2122"},"glyphs":{" ":{"w":117,"k":{"\u201c":22,"\u2018":22,"T":29,"V":29,"W":22,"Y":36,"A":15}},"!":{"d":"80,-91r-42,0r-5,-214r51,0xm28,-25v0,-17,14,-30,31,-30v17,0,30,13,30,30v0,17,-13,31,-30,31v-17,0,-31,-14,-31,-31","w":117},"\"":{"d":"133,-175v-29,-4,-15,-86,-23,-112v0,-12,11,-22,23,-22v43,0,14,75,14,120v0,11,-8,14,-14,14xm58,-175v-28,-6,-14,-86,-22,-112v0,-12,10,-22,22,-22v43,0,14,75,14,120v0,11,-8,14,-14,14","w":190},"#":{"d":"139,-111r8,-55r-52,0r-7,55r51,0xm124,0r11,-83r-51,0r-12,83r-28,0r12,-83r-36,0r0,-28r40,0r7,-55r-36,0r0,-28r40,0r12,-83r28,0r-12,83r52,0r12,-83r27,0r-11,83r36,0r0,28r-40,0r-8,55r36,0r0,28r-40,0r-12,83r-27,0"},"$":{"d":"102,-248v-61,7,-60,76,-1,82xm179,-73v0,-28,-23,-35,-47,-41r-2,85v32,-4,49,-19,49,-44xm12,-74r40,0r0,39v10,3,29,6,49,6r0,-93v-43,-11,-90,-29,-90,-77v0,-55,46,-82,91,-84r1,-51r30,0r-1,51v30,1,57,8,74,13r0,61r-38,0r0,-33v-8,-3,-22,-6,-36,-6r-1,90v47,13,92,23,92,82v0,49,-38,77,-93,82r-1,48r-30,0r1,-48v-35,0,-71,-5,-88,-12r0,-68"},"%":{"d":"248,-95v-21,0,-32,14,-32,36v0,22,11,37,32,37v22,0,32,-15,32,-37v0,-22,-9,-36,-32,-36xm250,-123v36,0,62,21,62,64v0,39,-25,65,-64,65v-38,0,-65,-24,-65,-64v0,-36,26,-65,67,-65xm82,-255v-21,0,-32,14,-32,36v0,22,11,37,32,37v22,0,32,-15,32,-37v0,-22,-9,-36,-32,-36xm84,-283v36,0,63,21,63,64v0,39,-26,65,-65,65v-38,0,-65,-24,-65,-64v0,-36,26,-65,67,-65xm59,7r182,-307r26,16r-183,307","w":329},"&":{"d":"284,-169r0,30r-26,0v0,29,-13,65,-28,83v14,15,30,29,54,22r0,33v-34,6,-62,-5,-78,-28v-19,19,-41,34,-88,34v-105,1,-121,-113,-51,-151r14,-10v-49,-37,-54,-126,42,-126v86,0,76,93,26,118r-15,11r72,73v11,-14,17,-43,17,-59r-27,0r0,-30r88,0xm105,-183v4,7,9,7,15,2v31,-12,49,-71,-1,-71v-46,0,-42,49,-14,69xm182,-52r-78,-80v-19,11,-39,26,-39,51v0,54,93,66,117,29","w":300},"\u2019":{"d":"43,-175v-6,-9,-28,-17,-13,-26v11,-11,20,-23,20,-36v0,-22,-21,-30,-21,-47v0,-10,10,-25,29,-25v24,0,36,23,36,45v0,27,-24,71,-51,89","w":117,"k":{"\u2019":30,"t":7,"r":10,"d":36,"s":29}},"(":{"d":"122,90r-31,18v-42,-49,-72,-134,-72,-211v0,-84,35,-159,74,-210r31,18v-74,94,-78,289,-2,385","w":117},")":{"d":"-4,-295r31,-18v40,51,71,133,71,210v0,84,-35,160,-74,211r-30,-18v72,-96,77,-286,2,-385","w":117},"*":{"d":"55,-181r7,-49r-39,29r-14,-24r45,-19r-45,-16r14,-27r39,30r-7,-48r31,0r-7,48r37,-30r15,27r-44,16r44,19r-15,24r-37,-29r7,49r-31,0","w":139},"+":{"d":"103,0r0,-84r-84,0r0,-32r84,0r0,-84r32,0r0,84r84,0r0,32r-84,0r0,84r-32,0","w":237},",":{"d":"38,80v-6,-9,-28,-18,-13,-27v11,-11,20,-23,20,-36v0,-22,-21,-30,-21,-47v0,-10,10,-25,29,-25v24,0,36,23,36,45v0,27,-23,72,-51,90","w":117,"k":{"\u201d":22,"\u2019":22," ":15}},"-":{"d":"26,-93r0,-39r109,0r0,39r-109,0","w":161},".":{"d":"28,-25v0,-17,14,-30,31,-30v17,0,30,13,30,30v0,17,-13,31,-30,31v-17,0,-31,-14,-31,-31","w":117,"k":{"\u201d":22,"\u2019":22," ":15}},"\/":{"d":"-1,21r119,-330r29,11r-118,330","w":146},"0":{"d":"63,-134v0,58,13,105,53,105v41,0,55,-51,55,-110v0,-72,-16,-109,-52,-109v-40,0,-56,49,-56,114xm17,-133v0,-73,26,-150,103,-150v80,0,98,79,98,138v0,81,-26,151,-104,151v-68,0,-97,-51,-97,-139"},"1":{"d":"53,0r0,-32r54,0r2,-204v-21,17,-45,31,-67,47r-18,-30r94,-58r35,0r-2,245r58,0r0,32r-156,0"},"2":{"d":"19,0v0,-17,-3,-37,10,-41v39,-31,131,-103,131,-162v0,-25,-13,-43,-46,-43v-40,0,-50,36,-50,50r-44,0v0,-29,20,-87,96,-87v50,0,89,27,89,79v0,65,-76,130,-123,168v39,-2,91,0,133,-1r0,37r-196,0"},"3":{"d":"80,-125r0,-33v35,1,73,-10,75,-53v0,-23,-16,-37,-41,-37v-39,0,-48,29,-48,44r-45,0v0,-24,20,-79,96,-79v58,0,85,31,85,69v1,41,-30,58,-58,68v39,3,69,26,69,67v0,48,-34,85,-112,85v-43,0,-65,-10,-78,-16r0,-42v31,23,145,40,143,-27v-1,-45,-48,-47,-86,-46"},"4":{"d":"10,-78r0,-34r116,-165r53,0r-1,165r52,0r0,34r-52,0r-1,46r33,0r0,32r-104,0r0,-32r29,0r1,-46r-126,0xm136,-112r0,-123r-83,123r83,0"},"5":{"d":"34,-277r161,0r0,35r-116,0r-2,66v53,-1,130,11,130,88v0,54,-43,94,-108,94v-29,0,-53,-5,-72,-12r0,-37v9,3,29,12,65,12v44,0,68,-20,68,-54v0,-52,-63,-56,-127,-56"},"6":{"d":"208,-276r-3,35v-7,-2,-23,-7,-45,-7v-62,-1,-91,41,-95,103v11,-13,30,-30,64,-30v51,0,86,33,86,84v0,61,-38,97,-95,97v-76,0,-100,-69,-100,-129v0,-82,34,-160,140,-160v18,0,36,2,48,7xm119,-140v-33,0,-42,16,-55,27v0,48,19,82,57,82v60,-1,72,-109,-2,-109"},"7":{"d":"25,-240r0,-37r184,0r0,28r-86,174v-15,30,-30,55,-42,75r-49,0v45,-65,88,-172,132,-240r-139,0"},"8":{"d":"71,-211v0,30,27,39,49,49v22,-10,46,-24,46,-50v0,-25,-20,-36,-47,-36v-31,0,-48,16,-48,37xm174,-72v-1,-33,-36,-38,-58,-52v-23,11,-53,26,-53,54v0,23,16,41,55,41v39,0,56,-19,56,-43xm16,-66v0,-49,38,-62,67,-76v-83,-22,-73,-141,37,-141v57,0,91,24,91,68v1,37,-29,57,-58,71v28,8,65,29,65,72v0,56,-41,78,-104,78v-48,0,-98,-17,-98,-72"},"9":{"d":"26,-2r3,-34v7,2,23,7,45,7v62,1,91,-41,95,-104v-11,13,-30,30,-64,30v-51,0,-85,-32,-85,-83v0,-61,38,-97,95,-97v76,0,100,69,100,129v0,82,-35,160,-141,160v-18,0,-36,-3,-48,-8xm116,-137v33,0,42,-15,54,-27v0,-48,-18,-82,-56,-82v-62,1,-72,109,2,109"},":":{"d":"28,-180v0,-17,14,-31,31,-31v17,0,30,14,30,31v0,17,-13,30,-30,30v-17,0,-31,-13,-31,-30xm28,-25v0,-17,14,-30,31,-30v17,0,30,13,30,30v0,17,-13,31,-30,31v-17,0,-31,-14,-31,-31","w":117},";":{"d":"38,80v-6,-9,-28,-18,-13,-27v11,-11,20,-23,20,-36v0,-22,-21,-30,-21,-47v0,-10,10,-25,29,-25v24,0,36,23,36,45v0,27,-23,72,-51,90xm27,-180v0,-17,14,-31,31,-31v17,0,30,14,30,31v0,17,-13,30,-30,30v-17,0,-31,-13,-31,-30","w":117},"<":{"d":"19,-85r0,-30r200,-90r0,33r-161,72r161,72r0,32","w":237},"=":{"d":"19,-122r0,-32r200,0r0,32r-200,0xm19,-46r0,-32r200,0r0,32r-200,0","w":237},">":{"d":"219,-115r0,30r-200,89r0,-32r160,-72r-160,-72r0,-33","w":237},"?":{"d":"32,-122v-2,-51,98,-62,90,-112v6,-42,-70,-46,-96,-32r-2,-35v5,-2,25,-8,55,-8v103,0,119,100,50,142v-22,14,-74,37,-43,68r-39,15v-7,-9,-14,-20,-15,-38xm32,-25v0,-17,14,-30,31,-30v17,0,30,13,30,30v0,17,-13,31,-30,31v-17,0,-31,-14,-31,-31","w":190},"@":{"d":"193,-154v0,-26,-12,-36,-31,-36v-32,0,-55,38,-55,70v0,23,12,36,30,36v33,0,56,-42,56,-70xm240,-213r-33,124v0,5,3,8,13,8v20,0,47,-35,47,-78v0,-54,-48,-90,-102,-90v-68,0,-115,52,-115,112v0,109,144,138,207,77r32,0v-20,38,-64,65,-127,65v-82,0,-147,-54,-147,-144v0,-80,61,-143,150,-143v78,0,137,48,137,118v0,77,-61,111,-98,111v-20,1,-26,-12,-29,-23v-28,40,-100,25,-100,-40v0,-76,88,-146,130,-74r7,-23r28,0","w":316},"A":{"d":"185,-136r-36,-104v-7,34,-27,72,-38,104r74,0xm5,0r0,-32r24,0r100,-245r49,0r93,245r25,0r0,32r-102,0r0,-32r26,0r-24,-69r-97,0r-26,69r28,0r0,32r-96,0","w":300,"k":{"v":22,"w":22,"y":22,"C":15,"G":15,"O":15,"Q":15,"T":29,"u":12,"U":18,"V":29,"W":29,"Y":29,"\u201d":29,"\u2019":36}},"B":{"d":"88,-32v48,2,95,-1,95,-47v0,-45,-47,-48,-94,-45xm15,-277v88,3,199,-20,200,68v1,33,-22,58,-55,64v37,0,72,25,72,67v0,47,-34,78,-101,78r-116,0r0,-32r28,0r2,-213r-30,0r0,-32xm168,-204v0,-43,-36,-42,-79,-41r0,86v43,3,79,-4,79,-45","w":249,"k":{"A":10}},"C":{"d":"253,-196r-40,0r0,-44v-76,-24,-148,15,-148,103v0,82,64,122,144,103r2,-50r40,0r-2,76v-18,6,-53,13,-86,13v-99,0,-147,-62,-147,-141v0,-86,58,-146,150,-146v35,0,68,7,87,15r0,71","w":271,"k":{"A":10}},"D":{"d":"15,0r0,-32r29,0r1,-213r-30,0r0,-32r132,0v89,0,140,52,140,132v0,82,-51,145,-140,145r-132,0xm88,-32v93,9,150,-25,150,-111v0,-79,-59,-111,-149,-102","w":308,"k":{"V":22,"W":18,"Y":29,"A":26,",":15,".":15}},"E":{"d":"18,0r0,-32r28,0r2,-213r-33,0r0,-32r195,0r2,73r-37,0r-2,-41r-81,0r-1,86r80,0r0,35r-80,0r0,92r84,0r3,-46r37,0r-3,78r-194,0"},"F":{"d":"18,0r0,-32r28,0r2,-213r-33,0r0,-32r195,0r2,73r-37,0r-2,-41r-81,0r-1,86r87,0r0,35r-87,0r0,92r34,0r0,32r-107,0","w":227,"k":{"A":22,",":51,".":51,"a":29,"e":18,"i":12,"o":22,"r":12}},"G":{"d":"253,-196r-40,0r0,-44v-76,-24,-148,15,-148,103v0,81,62,125,142,101r1,-61r-32,0r0,-32r102,0r0,32r-28,0r-1,89v-19,7,-55,13,-85,13v-101,0,-148,-62,-148,-141v0,-86,58,-146,150,-146v32,0,68,7,87,15r0,71","w":285},"H":{"d":"190,0r0,-32r27,0r1,-90r-129,0r0,90r29,0r0,32r-102,0r0,-32r28,0r2,-213r-30,0r0,-32r102,0r0,32r-28,0r-1,89r129,0r1,-89r-29,0r0,-32r102,0r0,32r-28,0r-2,213r30,0r0,32r-102,0","w":308},"I":{"d":"19,0r0,-32r28,0r1,-213r-29,0r0,-32r102,0r0,32r-28,0r-2,213r30,0r0,32r-102,0","w":139},"J":{"d":"-4,75r-14,-32v100,-43,58,-166,67,-288r-30,0r0,-32r102,0r0,32r-28,0r-1,167v1,87,-29,123,-96,153","w":131,"k":{"u":10,"A":12,",":10,".":10,"a":5,"e":5,"o":5}},"K":{"d":"15,0r0,-32r28,0r1,-213r-29,0r0,-32r102,0r0,32r-28,0r-1,97r110,-97r-30,0r0,-32r103,0r0,32r-22,0r-114,100r117,113r23,0r0,32r-111,0r0,-32r29,0r-105,-101r0,101r29,0r0,32r-102,0","w":278,"k":{"y":22,"O":12,"u":15}},"L":{"d":"15,0r0,-32r29,0r1,-213r-30,0r0,-32r103,0r0,32r-29,0r-1,213r82,0r4,-47r37,0r-3,79r-193,0","k":{"y":36,"T":36,"V":44,"W":44,"Y":44,"\u201d":36,"\u2019":44}},"M":{"d":"13,0r0,-32r29,0r1,-213r-31,0r0,-32r91,0r80,206v4,6,3,17,7,23v24,-81,58,-152,86,-229r86,0r0,32r-32,0r2,213r30,0r0,32r-101,0r0,-32r27,0r1,-189v-23,78,-55,147,-82,221r-44,0v-27,-73,-61,-140,-82,-219v-4,59,0,126,-2,187r31,0r0,32r-97,0","w":373},"N":{"d":"17,0r0,-32r27,0r2,-213r-35,0r0,-32r73,0r128,167v8,11,20,30,28,42r-1,-177r-31,0r0,-32r97,0r0,32r-27,0r-2,245r-36,0r-139,-180v-9,-9,-15,-26,-20,-28r2,176r30,0r0,32r-96,0","w":315,"k":{"A":10}},"O":{"d":"16,-134v0,-87,54,-148,140,-148v80,0,128,53,128,139v0,73,-43,148,-136,148v-81,0,-132,-54,-132,-139xm65,-136v0,54,27,104,85,104v73,0,85,-71,85,-109v0,-50,-17,-104,-82,-104v-46,0,-88,32,-88,109","w":300,"k":{"T":12,"V":18,"W":18,"Y":29,"A":15,",":15,".":15,"X":12}},"P":{"d":"222,-197v0,67,-55,96,-134,87r0,78r34,0r0,32r-107,0r0,-32r29,0r1,-213r-30,0r0,-32r105,0v74,-3,102,24,102,80xm175,-195v0,-45,-37,-54,-86,-50r-1,102v50,5,87,-9,87,-52","k":{"A":22,",":51,".":51,"a":15,"e":12,"o":12}},"Q":{"d":"16,-134v0,-87,54,-148,140,-148v155,0,171,244,36,281v42,5,85,53,136,39r0,35v-76,14,-137,-47,-198,-68v-70,-8,-114,-61,-114,-139xm65,-136v0,54,27,104,85,104v73,0,85,-71,85,-109v0,-50,-17,-104,-82,-104v-46,0,-88,32,-88,109","w":300,"k":{",":-6}},"R":{"d":"15,0r0,-32r28,0r1,-213r-29,0r0,-32r124,0v57,0,84,33,84,73v1,49,-34,67,-67,74v34,6,47,55,66,81v11,17,16,18,35,17r0,32v-40,-1,-56,7,-76,-29r-38,-65v-15,-29,-24,-23,-55,-24r0,86r32,0r0,32r-105,0xm88,-153v46,3,88,-3,88,-46v0,-43,-41,-49,-87,-46","w":256,"k":{"T":7,"V":15,"W":15,"Y":18}},"S":{"d":"21,-77r44,0r0,37v31,16,117,15,109,-36v3,-38,-60,-42,-92,-53v-32,-10,-60,-28,-60,-72v0,-88,124,-92,188,-67r0,61r-42,0r0,-33v-6,-2,-20,-7,-41,-7v-41,0,-58,19,-58,40v-1,40,53,40,85,50v32,9,67,25,67,74v0,90,-116,104,-200,73r0,-67","w":241},"T":{"d":"84,0r0,-32r28,0r2,-213r-64,0r-2,41r-40,0r2,-73r251,0r2,73r-40,0r-1,-41r-64,0r-1,213r32,0r0,32r-105,0","w":271,"k":{"w":59,"y":51,"O":12,"u":44,"A":29,"h":10,",":36,".":36,"a":36,"e":36,"i":15,"o":44,"r":36,"-":44,":":22,";":22}},"U":{"d":"149,5v-78,0,-109,-27,-109,-100v0,-53,1,-102,1,-150r-29,0r0,-32r101,0r0,32r-28,0v7,90,-32,213,65,213v104,0,60,-126,70,-213r-33,0r0,-32r102,0r0,32r-27,0r-1,149v0,72,-43,101,-112,101","w":300,"k":{"A":18,",":10,".":10}},"V":{"d":"2,-245r0,-32r104,0r0,32r-28,0r66,184v4,8,3,18,7,24v20,-73,48,-138,71,-208r-32,0r0,-32r101,0r0,32r-24,0r-96,245r-49,0r-96,-245r-24,0","w":293,"k":{"G":10,"O":18,"u":22,"A":29,",":36,".":36,"a":36,"e":36,"i":15,"o":36,"-":36,":":29,";":29}},"W":{"d":"3,-245r0,-32r104,0r0,32r-28,0r69,208v15,-58,38,-108,57,-163r-15,-45r-27,0r0,-32r101,0r0,32r-28,0r55,175v4,9,3,24,8,33v19,-73,47,-138,69,-208r-30,0r0,-32r99,0r0,32r-24,0r-93,245r-49,0r-48,-147r-55,147r-50,0r-90,-245r-25,0","w":439,"k":{"y":15,"O":18,"u":22,"A":29,"h":10,",":36,".":44,"a":29,"e":29,"i":12,"o":29,"-":29,":":22,";":22}},"X":{"d":"164,0r0,-32r28,0r-57,-79r-60,79r28,0r0,32r-97,0r0,-32r23,0r85,-107r-77,-106r-26,0r0,-32r108,0r0,32r-30,0v20,23,37,50,56,74r59,-74r-30,0r0,-32r92,0r0,32r-21,0r-79,102r82,111r24,0r0,32r-108,0","w":278},"Y":{"d":"93,0r0,-32r27,0r2,-82r-96,-131r-24,0r0,-32r101,0r0,32r-27,0r72,97r71,-97r-31,0r0,-32r96,0r0,32r-24,0r-94,131r-1,82r29,0r0,32r-101,0","w":285,"k":{"O":29,"u":36,"A":29,",":44,".":44,"a":40,"e":40,"i":15,"o":40,"-":44,":":29,";":29}},"Z":{"d":"17,0r0,-31r166,-214r-114,0r-3,40r-40,0r3,-72r208,0r0,33r-163,212r122,0r4,-40r39,0r-3,72r-219,0","w":256},"[":{"d":"111,67r0,32r-79,0r1,-404r79,0r0,33r-37,0r-1,339r37,0","w":117},"\\":{"d":"118,32r-119,-330r30,-11r118,330","w":146},"]":{"d":"6,-272r0,-33r80,0r-2,404r-79,0r0,-32r37,0r2,-339r-38,0","w":117},"^":{"d":"171,-133r-52,-105r-52,105r-33,0r72,-144r25,0r73,144r-33,0","w":237},"_":{"d":"0,50r0,-20r198,0r0,20r-198,0","w":198},"\u2018":{"d":"74,-309v5,9,27,17,14,26v-11,11,-21,23,-21,36v0,22,21,30,21,47v0,10,-10,25,-29,25v-24,0,-36,-23,-36,-45v0,-27,24,-71,51,-89","w":117,"k":{"\u2018":30,"A":29}},"a":{"d":"32,-141r0,-51v11,-5,37,-19,81,-19v103,0,78,93,79,179r28,0r0,32r-66,0v-1,-12,4,-31,3,-43v-9,23,-25,48,-68,48v-50,0,-66,-33,-66,-59v0,-71,74,-60,131,-66v1,-35,-2,-57,-45,-58v-15,0,-31,4,-38,7r0,30r-39,0xm67,-58v0,15,12,28,33,28v37,-2,56,-27,53,-61v-46,0,-86,3,-86,33"},"b":{"d":"118,-32v77,0,91,-142,14,-141v-62,0,-55,71,-55,132v8,4,21,9,41,9xm2,-272r0,-33r77,0r-4,142v8,-20,28,-48,70,-48v54,0,84,39,84,94v0,61,-28,122,-117,122v-36,0,-59,-8,-79,-16r2,-261r-33,0","w":241,"k":{"y":10}},"c":{"d":"147,-142r0,-30v-49,-16,-88,16,-88,66v0,36,17,74,72,74v20,0,42,-6,52,-12r-2,38v-8,4,-30,11,-56,11v-82,0,-111,-56,-111,-107v0,-63,39,-109,111,-109v31,0,50,7,59,11r0,58r-37,0","w":198,"k":{"h":7,"k":7}},"d":{"d":"235,-32r0,32r-69,0v0,-15,1,-30,3,-42v-11,28,-34,47,-69,47v-50,0,-86,-37,-86,-98v0,-82,65,-136,152,-113r0,-66r-37,0r0,-33r80,0r-1,273r27,0xm111,-32v55,0,56,-73,53,-135v-48,-27,-103,11,-103,67v0,38,17,68,50,68","w":249,"k":{"v":10,"w":12,"y":15}},"e":{"d":"198,-46r-3,36v-14,6,-41,15,-72,15v-68,0,-109,-42,-109,-107v0,-61,34,-109,101,-109v64,0,95,47,93,115r-147,0v-5,69,89,79,137,50xm61,-126r101,0v1,-22,-9,-52,-49,-52v-38,0,-50,27,-52,52","w":220,"k":{"v":10,"w":10,"y":10}},"f":{"d":"17,0r0,-32r25,0r1,-141r-31,0r0,-33r31,0v-9,-85,53,-116,128,-99r-2,35v-6,-2,-16,-4,-33,-4v-43,1,-50,28,-48,68r48,0r0,33r-48,0r-1,141r31,0r0,32r-101,0","w":139,"k":{"\u201d":-15,"\u2019":-15}},"g":{"d":"222,-206r-1,33r-40,-3v7,8,17,20,17,45v-2,49,-45,77,-100,73v-11,0,-23,8,-23,16v26,33,143,-1,143,71v0,56,-54,75,-108,75v-56,0,-97,-20,-97,-54v-1,-29,24,-43,48,-50v-15,-3,-30,-11,-30,-30v-1,-22,24,-29,39,-35v-83,-23,-61,-155,40,-146v37,3,71,6,112,5xm60,-133v0,30,19,43,52,43v31,0,49,-18,49,-45v0,-28,-19,-43,-51,-43v-31,0,-50,18,-50,45xm176,37v0,-28,-61,-23,-88,-31v-20,9,-33,18,-33,34v0,24,25,32,59,32v30,0,62,-9,62,-35","w":227},"h":{"d":"19,0r0,-32r23,0r2,-240r-30,0r0,-33r76,0v-2,51,3,99,-6,145v8,-27,32,-51,73,-51v86,0,71,98,70,179r27,0r0,32r-95,0r0,-32r24,0v-3,-55,19,-140,-40,-141v-30,0,-54,24,-55,62r-1,79r27,0r0,32r-95,0","w":264,"k":{"y":15}},"i":{"d":"15,0r0,-32r27,0r1,-141r-31,0r0,-33r76,0r-1,174r27,0r0,32r-99,0xm35,-279v0,-17,13,-30,30,-30v17,0,31,13,31,30v0,17,-14,31,-31,31v-17,0,-30,-14,-30,-31","w":124,"k":{"v":7}},"j":{"d":"12,-173r0,-33r76,0r-1,168v0,83,-37,132,-110,142r-6,-35v55,-13,71,-40,71,-125r1,-117r-31,0xm35,-279v0,-17,13,-30,30,-30v17,0,31,13,31,30v0,17,-14,31,-31,31v-17,0,-30,-14,-30,-31","w":131},"k":{"d":"17,0r0,-32r25,0r2,-240r-36,0r0,-33r80,0r-1,189r73,-57r-30,0r0,-33r97,0r0,33r-21,0r-73,61r79,80r24,0r0,32r-99,0r0,-32r24,0r-74,-73r0,73r25,0r0,32r-95,0","w":241,"k":{"e":7}},"l":{"d":"17,0r0,-32r25,0r2,-240r-36,0r0,-33r80,0r-1,273r27,0r0,32r-97,0","w":124,"k":{"w":7,"y":10}},"m":{"d":"19,0r0,-32r23,0r1,-141r-29,0r0,-33r74,0v0,14,-1,29,-4,46v8,-30,37,-51,71,-51v42,-1,57,23,64,47v10,-30,35,-47,70,-47v85,0,72,98,70,179r27,0r0,32r-95,0r0,-32r23,0v-1,-55,20,-139,-40,-141v-57,-2,-51,81,-51,141r26,0r0,32r-93,0r0,-32r23,0v-4,-56,20,-139,-40,-141v-27,0,-51,24,-51,62r-1,79r27,0r0,32r-95,0","w":396,"k":{"y":10,"u":7}},"n":{"d":"19,0r0,-32r23,0r1,-141r-29,0r0,-33r74,0v0,14,-1,29,-4,46v8,-27,32,-51,73,-51v86,0,71,98,70,179r27,0r0,32r-95,0r0,-32r24,0v-3,-55,19,-140,-40,-141v-30,0,-54,24,-55,62r-1,79r27,0r0,32r-95,0","w":264,"k":{"v":10,"y":10}},"o":{"d":"120,-173v-80,0,-82,140,-3,141v40,0,58,-35,58,-75v0,-46,-24,-66,-55,-66xm13,-99v0,-67,45,-112,108,-112v76,0,101,58,101,109v0,59,-36,107,-106,107v-74,0,-103,-52,-103,-104","k":{"v":10,"w":10,"y":10,"x":5}},"p":{"d":"10,-173r0,-33r71,0v1,15,-4,32,-3,42v11,-28,34,-47,69,-47v50,0,86,37,86,98v0,82,-68,138,-152,111r-1,69r33,0r0,32r-98,0r0,-32r23,0r1,-240r-29,0xm136,-173v-55,0,-56,72,-53,134v48,27,103,-10,103,-67v0,-38,-17,-67,-50,-67","w":249,"k":{"y":15,",":10,".":10}},"q":{"d":"111,-32v62,0,55,-72,55,-133v-8,-4,-20,-8,-40,-8v-78,0,-92,141,-15,141xm139,99r0,-32r25,0r1,-66v-1,-14,5,-31,3,-44v-8,20,-28,48,-70,48v-54,0,-84,-39,-84,-94v0,-61,28,-122,117,-122v36,0,58,8,79,16r-1,262r29,0r0,32r-99,0","w":249},"r":{"d":"17,0r0,-32r25,0r1,-141r-31,0r0,-33r73,0v1,14,-2,40,-1,58v9,-48,41,-72,85,-58r-5,39v-73,-18,-81,59,-77,135r30,0r0,32r-100,0","w":168,"k":{",":22,".":22,"a":10,"o":5,"-":15}},"s":{"d":"177,-147r-39,0r-1,-24v-16,-10,-78,-13,-75,18v4,32,49,25,76,33v22,7,50,14,50,56v0,84,-118,75,-167,56r-1,-55r40,0r1,27v18,8,87,18,85,-21v-1,-28,-38,-27,-62,-32v-32,-7,-67,-18,-67,-57v0,-77,115,-72,160,-51r0,50","w":205,"k":{"w":10}},"t":{"d":"12,-173r0,-33r31,0r1,-46r45,-3r-2,49r59,0r0,33r-59,0v0,33,-1,65,-1,96v0,59,32,50,64,39r-2,32v-43,22,-106,14,-106,-53v0,-27,1,-78,1,-114r-31,0","w":146},"u":{"d":"14,-173r0,-33r72,0v5,63,-27,174,39,174v29,0,53,-25,53,-63r1,-78r-27,0r0,-33r71,0r-1,174r28,0r0,32r-71,0v-1,-13,3,-32,3,-46v-8,30,-40,51,-72,51v-44,0,-70,-31,-70,-79v0,-34,1,-66,2,-99r-28,0","w":264},"v":{"d":"90,0r-71,-173r-20,0r0,-33r92,0r0,33r-22,0r48,136v11,-49,31,-90,46,-136r-26,0r0,-33r91,0r0,33r-21,0r-70,173r-47,0","w":227,"k":{",":29,".":29,"a":10,"e":7}},"w":{"d":"213,0r-36,-103v-9,39,-27,68,-40,103r-44,0r-69,-173r-22,0r0,-33r92,0r0,33r-24,0r48,133v11,-37,28,-71,42,-106r-10,-27r-22,0r0,-33r91,0r0,33r-24,0r46,133v11,-48,31,-89,46,-133r-29,0r0,-33r92,0r0,33r-21,0r-69,173r-47,0","w":352,"k":{"h":7,",":29,".":29,"a":7,"e":10,"o":10}},"x":{"d":"139,0r0,-32r25,0r-44,-50r-47,50r28,0r0,32r-89,0r0,-32r22,0r66,-72r-61,-69r-24,0r0,-33r99,0r0,33r-25,0v16,13,27,30,41,45v14,-15,26,-32,42,-45r-27,0r0,-33r87,0r0,33r-22,0r-61,64r66,77r23,0r0,32r-99,0","w":249,"k":{"e":5}},"y":{"d":"-1,-173r0,-33r94,0r0,33r-23,0r40,105v5,10,5,24,10,31v12,-47,31,-91,45,-136r-27,0r0,-33r87,0r0,33r-20,0v-32,81,-51,172,-95,244v-20,33,-60,39,-99,29r0,-35v45,13,64,2,86,-54r-76,-184r-22,0","k":{",":29,".":29,"a":15,"e":12,"o":15}},"z":{"d":"16,0r0,-32r114,-131v4,-4,8,-7,11,-10r-80,0r-3,30r-37,0r3,-63r171,0r0,33r-111,127v-4,5,-10,9,-15,14r87,0r4,-32r37,0r-3,64r-178,0","w":212},"{":{"d":"120,-305r0,31v-53,-8,-33,67,-33,110v0,34,-21,53,-42,62v23,7,42,27,42,60v0,42,-22,116,33,111r0,30v-46,4,-73,-10,-75,-59v-2,-52,11,-125,-37,-128r0,-30v48,-3,35,-77,37,-128v2,-49,29,-64,75,-59","w":117},"|":{"d":"28,99r0,-396r32,0r0,396r-32,0","w":87},"}":{"d":"-3,99r0,-30v53,9,33,-68,33,-111v0,-34,21,-52,42,-61v-48,-9,-43,-81,-42,-141v1,-24,-9,-33,-33,-30r0,-31v46,-4,73,10,75,59v2,52,-11,125,37,128r0,30v-48,3,-35,77,-37,128v-2,49,-29,64,-75,59","w":117},"~":{"d":"77,-130v27,-1,60,27,84,27v16,0,26,-15,35,-29r14,28v-9,17,-22,34,-49,34v-28,1,-60,-27,-85,-28v-16,0,-25,16,-34,30r-15,-29v9,-17,23,-33,50,-33","w":237},"'":{"d":"59,-175v-29,-4,-15,-86,-23,-112v0,-12,11,-22,23,-22v43,0,14,75,14,120v0,11,-8,14,-14,14","w":117},"\u201c":{"d":"67,-309v6,9,28,18,13,26v-11,11,-20,23,-20,36v0,22,21,30,21,47v0,10,-10,25,-29,25v-24,0,-36,-23,-36,-45v0,-27,24,-71,51,-89xm154,-309v6,9,29,18,14,26v-11,11,-20,23,-20,36v0,22,20,30,20,47v0,10,-9,25,-28,25v-24,0,-37,-23,-37,-45v0,-27,24,-71,51,-89","w":190,"k":{"A":22}},"\u2013":{"d":"0,-95r0,-35r198,0r0,35r-198,0","w":198},"\u201d":{"d":"124,-175v-6,-9,-29,-17,-14,-26v11,-11,20,-23,20,-36v0,-22,-20,-30,-20,-47v0,-10,9,-25,28,-25v24,0,37,23,37,45v0,27,-24,71,-51,89xm36,-175v-6,-9,-28,-17,-13,-26v11,-11,20,-23,20,-36v0,-22,-21,-30,-21,-47v0,-10,10,-25,29,-25v24,0,36,23,36,45v0,27,-24,71,-51,89","w":190},"\u2026":{"d":"36,-25v0,-17,13,-30,30,-30v17,0,31,13,31,30v0,17,-14,31,-31,31v-17,0,-30,-14,-30,-31xm168,-25v0,-17,13,-30,30,-30v17,0,30,13,30,30v0,17,-13,31,-30,31v-17,0,-30,-14,-30,-31xm299,-25v0,-17,14,-30,31,-30v17,0,30,13,30,30v0,17,-13,31,-30,31v-17,0,-31,-14,-31,-31","w":396},"`":{"d":"67,-230r-79,-63r24,-22r80,66","w":110},"\u2014":{"d":"0,-95r0,-35r396,0r0,35r-396,0","w":396},"\u2122":{"d":"61,-112r0,-137r-48,0r0,-28r131,0r0,28r-48,0r0,137r-35,0xm328,-112r-1,-130r-48,130r-22,0r-49,-130r0,130r-32,0r0,-165r48,0r44,117r44,-117r48,0r0,165r-32,0","w":392},"\u00d7":{"d":"188,-9r-69,-69r-70,69r-22,-21r70,-70r-70,-70r22,-22r70,70r69,-70r22,22r-69,70r69,70","w":237},"\u00a0":{"w":117,"k":{"\u201c":22,"\u2018":22,"T":29,"V":29,"W":22,"Y":36,"A":15}}}});
/*!
 * The following copyright notice may not be removed under any circumstances.
 * 
 * Copyright:
 * Copyright © 1991, 1992, 1995, 2002 Adobe Systems Incorporated.  All Rights
 * Reserved. © 1981, 2002 Heidelberger Druckmaschinen AG. All rights reserved.
 * 
 * Trademark:
 * PMN Caecilia is a trademark of Heidelberger Druckmaschinen AG, exclusively
 * licensed through Linotype Library GmbH, and may be registered in certain
 * jurisdictions.
 * 
 * Full name:
 * CaeciliaLTStd-BoldItalic
 * 
 * Designer:
 * Peter Matthias Noordzij
 * 
 * Vendor URL:
 * http://www.adobe.com/type
 * 
 * License information:
 * http://www.adobe.com/type/legal.html
 */
Cufon.registerFont({"w":234,"face":{"font-family":"Caecilia LT Std","font-weight":700,"font-style":"italic","font-stretch":"normal","units-per-em":"396","panose-1":"0 0 8 0 0 0 0 0 0 0","ascent":"305","descent":"-91","x-height":"4","bbox":"-46 -331 425 108","underline-thickness":"19.8","underline-position":"-19.8","slope":"-5","stemh":"32","stemv":"42","unicode-range":"U+0020-U+2122"},"glyphs":{" ":{"w":117,"k":{"T":15,"V":36,"W":15,"Y":44,"A":15}},"!":{"d":"36,-89r14,-216r47,0r-22,216r-39,0xm20,-21v0,-18,11,-28,29,-28v20,0,29,12,29,26v0,17,-10,28,-30,28v-12,0,-28,-5,-28,-26","w":117},"\"":{"d":"133,-177v-29,-4,-15,-85,-23,-110v0,-12,11,-22,23,-22v43,0,14,74,14,118v0,11,-8,14,-14,14xm58,-177v-28,0,-14,-85,-22,-110v0,-12,10,-22,22,-22v43,0,14,74,14,118v0,11,-8,14,-14,14","w":190},"#":{"d":"139,-111r7,-55r-50,0r-8,55r51,0xm44,0r11,-83r-35,0r4,-28r35,0r8,-55r-36,0r4,-28r36,0r12,-83r29,0r-12,83r50,0r12,-83r29,0r-12,83r36,0r-4,28r-36,0r-7,55r35,0r-4,28r-35,0r-12,83r-29,0r12,-83r-51,0r-12,83r-28,0"},"$":{"d":"15,-8r2,-66r34,0r0,37v5,2,22,8,43,8r9,-98v-35,-10,-78,-23,-78,-75v0,-43,35,-81,91,-81r5,-48r32,0r-4,48v23,0,48,6,64,12r-2,63r-34,0r1,-36v-8,-4,-22,-7,-32,-7r-7,89v65,22,80,45,80,85v0,53,-46,81,-95,83r-5,52r-32,0r4,-52v-31,0,-63,-8,-76,-14xm107,-171r7,-80v-25,4,-45,13,-45,42v0,23,18,31,38,38xm135,-118r-8,88v18,-2,48,-11,48,-48v0,-23,-18,-34,-40,-40"},"%":{"d":"173,-53v0,-39,24,-70,67,-70v37,0,57,26,57,58v0,39,-24,71,-66,71v-28,0,-58,-17,-58,-59xm238,-95v-37,-1,-48,72,-6,73v21,0,32,-19,32,-41v0,-17,-6,-32,-26,-32xm92,-255v-38,-1,-48,71,-6,73v21,0,32,-19,32,-41v0,-17,-6,-32,-26,-32xm27,-213v0,-39,24,-70,67,-70v37,0,56,26,56,58v0,39,-23,71,-65,71v-28,0,-58,-17,-58,-59xm15,9r270,-314r22,19r-269,313","w":322},"&":{"d":"131,-157r72,79v12,-13,18,-45,18,-59r-26,0r3,-32r86,0r-2,32r-26,0v-2,35,-16,69,-30,82v9,18,26,26,54,23r-3,32v-39,2,-54,1,-76,-29v-18,17,-44,36,-91,36v-66,0,-95,-39,-95,-79v0,-46,31,-66,67,-86v-53,-39,-37,-127,43,-126v46,0,65,26,65,53v0,39,-36,60,-59,74xm87,-221v0,21,17,35,25,44v23,-15,43,-29,43,-50v0,-13,-8,-27,-32,-27v-21,0,-36,11,-36,33xm180,-51r-79,-86v-13,8,-44,25,-44,59v-1,58,90,67,123,27","w":300},"\u2019":{"d":"38,-177r-14,-25v21,-8,38,-19,38,-40v-5,-27,-34,-67,14,-67v22,0,33,19,33,44v0,48,-41,78,-71,88","w":117,"k":{"\u2019":30,"v":10,"d":44,"s":44,"t":15}},"(":{"d":"125,-313r27,21v-85,100,-108,260,-34,382r-30,18v-35,-49,-60,-120,-60,-181v0,-99,36,-170,97,-240","w":131},")":{"d":"7,108r-28,-21v84,-100,108,-259,35,-382r30,-18v35,49,60,120,60,181v0,99,-36,170,-97,240","w":131},"*":{"d":"29,-202r-14,-26r50,-17r-46,-20r17,-25r36,33r-3,-48r29,0r-12,48r38,-31r15,25r-49,18r45,19r-16,26r-36,-34r4,50r-29,0v3,-16,11,-36,12,-50","w":139},"+":{"d":"99,0r0,-84r-84,0r0,-32r84,0r0,-84r33,0r0,84r84,0r0,32r-84,0r0,84r-33,0","w":237},",":{"d":"14,79r-14,-24v21,-8,38,-19,38,-40v-6,-27,-34,-68,14,-68v22,0,33,20,33,45v0,48,-41,77,-71,87","w":117,"k":{"\u201d":44,"\u2019":44," ":15}},"-":{"d":"23,-94r2,-37r102,0r-3,37r-101,0","w":154},".":{"d":"22,-21v0,-18,11,-28,29,-28v20,0,30,12,30,26v0,17,-11,28,-31,28v-12,0,-28,-5,-28,-26","w":117,"k":{"\u201d":44,"\u2019":44," ":-15}},"\/":{"d":"-31,19r179,-328r29,12r-178,329","w":146},"0":{"d":"15,-117v0,-69,28,-166,113,-166v72,0,91,60,91,125v0,57,-15,164,-114,164v-77,0,-90,-79,-90,-123xm57,-122v0,54,14,93,52,93v59,0,68,-86,68,-127v0,-54,-14,-92,-50,-92v-57,0,-70,84,-70,126"},"1":{"d":"47,0r3,-32r51,0r18,-212v-16,16,-49,33,-70,47r-17,-26r93,-54r39,0r-21,245r55,0r-2,32r-149,0"},"2":{"d":"13,0r2,-32v27,-17,153,-114,153,-178v0,-22,-15,-38,-43,-38v-34,0,-48,22,-52,45r-42,0v0,-10,15,-80,98,-80v44,0,81,25,81,74v0,70,-99,145,-141,175v44,-3,90,0,135,-1r-2,35r-189,0"},"3":{"d":"14,-11r3,-37v46,25,147,35,147,-33v0,-46,-60,-45,-90,-45r3,-33v50,3,88,-23,88,-55v0,-18,-11,-34,-40,-34v-31,0,-47,16,-52,39r-39,0v10,-54,49,-74,96,-74v38,0,77,20,77,63v0,41,-31,66,-73,74v39,0,72,25,72,65v0,41,-31,87,-111,87v-31,0,-66,-7,-81,-17"},"4":{"d":"138,-112r12,-131r-104,132v27,-2,62,0,92,-1xm103,0r2,-32r26,0r4,-48r-127,0r3,-36r129,-161r52,0r-14,165r48,0r-3,32r-48,0r-4,48r31,0r-3,32r-96,0"},"5":{"d":"39,-144r12,-133r151,0r-2,35r-112,0r-6,63v53,1,121,14,121,86v0,31,-15,99,-114,99v-25,0,-45,-4,-68,-11r4,-37v4,4,35,13,63,13v57,0,70,-35,70,-60v0,-46,-43,-52,-119,-55"},"6":{"d":"224,-276r-6,34v-78,-22,-146,15,-152,102v8,-13,29,-33,65,-33v56,0,82,42,82,83v0,54,-33,96,-95,96v-68,0,-97,-49,-97,-115v0,-112,82,-201,203,-167xm171,-86v0,-65,-84,-63,-108,-23v-1,41,12,79,56,80v27,0,52,-18,52,-57"},"7":{"d":"38,-242r3,-35r182,0r-2,27r-115,197v-11,18,-23,38,-35,53r-46,0v54,-69,99,-169,149,-242r-136,0"},"8":{"d":"14,-65v0,-40,35,-65,74,-80v-29,-14,-52,-33,-52,-66v0,-52,48,-72,94,-72v39,0,82,16,82,62v0,40,-29,59,-62,75v50,25,63,45,63,77v0,38,-34,75,-103,75v-39,0,-96,-15,-96,-71xm78,-210v0,19,16,29,44,46v22,-11,51,-26,51,-51v0,-27,-26,-36,-47,-36v-33,0,-48,21,-48,41xm171,-72v1,-31,-33,-43,-55,-56v-30,15,-60,28,-60,60v0,30,32,39,57,39v37,0,58,-18,58,-43"},"9":{"d":"13,-2r6,-33v87,25,149,-28,151,-107v-31,54,-145,38,-145,-47v0,-48,30,-94,93,-94v69,0,95,51,95,115v0,113,-80,202,-200,166xm67,-192v0,60,86,55,104,23v1,-36,-8,-79,-54,-79v-31,0,-50,22,-50,56"},":":{"d":"22,-21v0,-18,11,-28,29,-28v20,0,30,12,30,26v0,17,-11,28,-31,28v-12,0,-28,-5,-28,-26xm36,-180v0,-18,12,-28,30,-28v20,0,29,11,29,25v0,17,-11,29,-31,29v-12,0,-28,-5,-28,-26","w":117},";":{"d":"14,79r-14,-24v21,-8,38,-19,38,-40v-6,-27,-34,-68,14,-68v22,0,33,20,33,45v0,48,-41,77,-71,87xm36,-180v0,-18,12,-28,30,-28v20,0,29,11,29,25v0,17,-11,29,-31,29v-12,0,-28,-5,-28,-26","w":117},"<":{"d":"15,-85r0,-30r201,-90r0,33r-161,72r161,72r0,32","w":237},"=":{"d":"15,-122r0,-32r201,0r0,32r-201,0xm15,-46r0,-32r201,0r0,32r-201,0","w":237},">":{"d":"216,-115r0,30r-201,89r0,-32r161,-72r-161,-72r0,-33","w":237},"?":{"d":"33,-266r2,-35v9,-3,34,-8,57,-8v119,2,105,114,35,148v-24,12,-77,37,-45,66r-37,13v-36,-37,0,-76,39,-94v39,-18,50,-35,50,-58v0,-49,-59,-45,-101,-32xm24,-21v0,-18,11,-28,29,-28v20,0,29,12,29,26v0,17,-11,28,-31,28v-12,0,-27,-5,-27,-26","w":190},"@":{"d":"199,-154v0,-20,-15,-38,-33,-38v-33,0,-58,40,-58,73v0,22,11,39,34,39v33,0,57,-44,57,-74xm13,-139v0,-81,68,-145,152,-145v74,0,139,48,139,119v0,73,-64,112,-96,112v-16,1,-24,-9,-28,-22v-30,42,-109,18,-102,-41v-8,-71,89,-147,133,-75r7,-23r29,0r-35,125v0,5,4,9,10,9v23,0,52,-38,52,-80v0,-59,-51,-96,-109,-96v-72,0,-122,55,-122,119v0,65,54,116,125,116v36,0,73,-17,90,-38r32,0v-26,41,-72,66,-123,66v-86,0,-154,-64,-154,-146","w":316},"A":{"d":"-3,0r3,-32r22,0r114,-248r49,0r71,248r25,0r-3,32r-93,0r3,-32r21,0r-17,-69r-98,0r-30,69r29,0r-3,32r-93,0xm184,-134r-28,-113v-14,40,-32,75,-47,113r75,0","w":293,"k":{"v":22,"w":22,"y":29,"C":12,"G":12,"O":12,"p":5,"Q":12,"T":22,"u":7,"U":15,"V":29,"W":29,"Y":36,"\u201d":22,"\u2019":22}},"B":{"d":"10,0r2,-32r24,0r18,-213r-29,0r3,-32v80,3,186,-19,186,65v0,49,-37,64,-65,69v33,0,70,13,70,61v0,90,-114,85,-209,82xm96,-245r-7,86v44,2,81,-4,83,-49v2,-40,-37,-38,-76,-37xm86,-129r-8,97v50,-1,97,9,97,-52v0,-48,-46,-45,-89,-45","k":{"A":5}},"C":{"d":"231,-71r-6,65v-19,6,-46,13,-77,13v-81,0,-133,-44,-133,-128v0,-51,22,-163,150,-163v33,0,58,7,76,12r-3,65r-34,0r1,-37v-10,-3,-24,-5,-37,-5v-80,0,-106,62,-106,121v0,81,55,115,129,94r5,-37r35,0","w":249,"k":{"A":10}},"D":{"d":"96,-245r-18,213v97,11,154,-34,154,-122v0,-94,-59,-92,-136,-91xm10,0r2,-32r24,0r18,-213r-29,0r3,-32v124,-3,248,-9,248,117v0,108,-66,160,-156,160r-110,0","w":293,"k":{"V":22,"W":22,"Y":29,",":12,".":12,"A":22}},"E":{"d":"10,0r2,-32r24,0r18,-213r-29,0r3,-32r191,0r-6,70r-35,0r1,-38r-83,0r-7,86r84,0r-2,32r-85,0r-8,95r90,0r5,-39r35,0r-6,71r-192,0","w":227},"F":{"d":"10,0r2,-32r24,0r18,-213r-29,0r3,-32r187,0r-5,70r-35,0r0,-38r-79,0r-8,91r84,0r-3,32r-84,0r-7,90r28,0r-3,32r-93,0","w":212,"k":{",":51,".":51,"A":22,"a":22,"e":10,"o":7,"r":7}},"G":{"d":"251,-272r-6,65r-35,0r1,-37v-92,-23,-149,29,-149,116v0,74,61,118,134,93r5,-59r-29,0r3,-32r91,0r-3,32r-24,0r-7,86v-11,5,-46,15,-85,15v-84,0,-132,-46,-132,-136v0,-95,56,-155,151,-155v34,0,62,7,85,12","w":271},"H":{"d":"10,0r2,-32r24,0r18,-213r-29,0r3,-32r94,0r-3,32r-23,0r-8,89r127,0r8,-89r-29,0r3,-32r94,0r-3,32r-23,0r-18,213r29,0r-3,32r-94,0r3,-32r23,0r7,-90r-127,0r-7,90r28,0r-3,32r-93,0","w":300},"I":{"d":"10,0r2,-32r24,0r18,-213r-29,0r3,-32r94,0r-3,32r-23,0r-18,213r28,0r-3,32r-93,0","w":131},"J":{"d":"40,-86r14,-159r-29,0r3,-32r94,0r-3,32r-23,0r-11,131v-8,99,-20,139,-111,185r-17,-31v46,-25,76,-50,83,-126","w":131,"k":{"u":12,",":12,".":12,"A":12,"a":12,"e":10,"o":10}},"K":{"d":"10,0r2,-32r24,0r18,-213r-29,0r3,-32r94,0r-3,32r-23,0r-7,96r106,-96r-29,0r3,-32r99,0r-3,32r-20,0r-112,100r102,113r24,0r-2,32r-104,0r3,-32r24,0r-94,-106r-8,106r28,0r-3,32r-93,0","w":271,"k":{"y":18,"O":10,"u":7,"o":5}},"L":{"d":"10,0r2,-32r24,0r18,-213r-29,0r3,-32r94,0r-3,32r-23,0r-18,213r78,0r5,-39r37,0r-7,71r-181,0","w":212,"k":{"y":29,"T":29,"V":29,"W":29,"Y":36,"\u201d":36,"\u2019":36}},"M":{"d":"6,0r3,-32r23,0r21,-213r-31,0r3,-32r87,0r65,233v30,-82,69,-155,103,-233r81,0r-3,32r-26,0r-13,213r28,0r-3,32r-93,0r3,-32r23,0r16,-196v-29,78,-68,153,-101,228r-45,0r-63,-225r-15,193r28,0r-3,32r-88,0","w":366},"N":{"d":"8,0r3,-32r24,0r19,-213r-30,0r3,-32r64,0r132,207r14,-175r-29,0r3,-32r89,0r-3,32r-24,0r-21,245r-36,0r-113,-177v-10,-15,-12,-24,-18,-32r-14,177r29,0r-3,32r-89,0","w":308,"k":{",":10,".":10,"A":5}},"O":{"d":"15,-122v0,-109,68,-162,141,-162v78,0,114,55,114,131v0,76,-35,160,-141,160v-62,0,-114,-38,-114,-129xm62,-123v0,37,9,95,73,95v75,0,89,-86,89,-124v0,-54,-20,-97,-73,-97v-68,0,-89,70,-89,126","w":285,"k":{"V":12,"W":15,"Y":22,",":12,".":12,"A":15,"X":12}},"P":{"d":"96,-245r-9,101v47,6,91,-9,88,-56v-3,-50,-40,-45,-79,-45xm10,0r2,-32r24,0r18,-213r-29,0r3,-32v86,3,189,-21,189,72v0,78,-59,101,-133,94r-6,79r30,0r-3,32r-95,0","w":220,"k":{",":51,".":51,"A":22,"a":10,"e":7,"o":7}},"Q":{"d":"15,-122v0,-109,68,-162,141,-162v149,0,148,237,30,280v40,5,83,58,126,39r-3,33v-73,25,-114,-61,-181,-61v-61,0,-113,-38,-113,-129xm62,-123v0,37,9,95,73,95v75,0,89,-86,89,-124v0,-54,-20,-97,-73,-97v-68,0,-89,70,-89,126","w":285,"k":{",":-4}},"R":{"d":"10,0r2,-32r24,0r18,-213r-29,0r3,-32v83,0,188,-14,188,70v0,50,-38,75,-78,78v31,-5,54,54,68,84v7,14,16,13,33,13r-3,32v-34,-1,-61,6,-69,-24v-24,-32,-24,-103,-82,-93r-7,85r28,0r-3,32r-93,0xm96,-245r-8,95v48,10,91,-15,86,-54v-7,-51,-43,-39,-78,-41","w":249,"k":{"T":7,"U":7,"V":22,"W":15,"Y":22}},"S":{"d":"204,-272r-4,65r-35,0r0,-37v-37,-12,-101,-5,-96,35v-6,31,56,44,84,55v25,10,55,26,55,70v0,86,-119,110,-194,76r3,-67r34,0r-1,37v45,14,113,15,113,-39v0,-39,-49,-44,-79,-54v-91,-30,-78,-156,42,-153v30,0,54,5,78,12","w":227},"T":{"d":"62,0r3,-32r23,0r19,-213r-62,0r-5,38r-34,0r6,-70r236,0r-6,70r-34,0r1,-38r-61,0r-18,213r29,0r-3,32r-94,0","w":241,"k":{"i":22,"w":51,"y":51,"O":7,"u":44,",":51,".":51,"A":36,"h":7,"a":36,"e":36,"o":36,"r":36,"-":44,":":36,";":36}},"U":{"d":"23,-245r2,-32r94,0r-3,32r-23,0r-13,164v0,29,12,53,59,53v61,0,70,-39,74,-90r11,-127r-30,0r3,-32r90,0r-3,32r-23,0v-16,111,13,260,-124,252v-108,-7,-104,-51,-97,-126r11,-126r-28,0","w":293,"k":{",":12,".":12,"A":15}},"V":{"d":"103,0r-70,-245r-25,0r3,-32r95,0r-3,32r-23,0r53,208v25,-72,58,-139,86,-208r-30,0r3,-32r95,0r-3,32r-22,0r-112,245r-47,0","w":278,"k":{"G":12,"O":7,"u":29,",":51,".":51,"A":29,"a":36,"e":29,"i":22,"o":29,"-":36,":":29,";":29}},"W":{"d":"99,0r-65,-245r-25,0r2,-32r94,0r-3,32r-22,0r50,213v19,-59,47,-110,69,-166r-12,-47r-27,0r3,-32r93,0r-3,32r-22,0r49,208v23,-73,52,-138,78,-208r-30,0r3,-32r94,0r-2,32r-23,0r-101,245r-49,0r-38,-147r-64,147r-49,0","w":418,"k":{"y":29,"O":15,"u":29,",":51,".":51,"A":36,"h":7,"a":36,"e":29,"i":22,"o":29,"-":36,":":29,";":29}},"X":{"d":"1,0r3,-32r22,0r92,-111r-66,-102r-25,0r3,-32r98,0r-3,32r-24,0v16,21,31,48,46,71r61,-71r-33,0r3,-32r97,0r-3,32r-21,0r-84,99r71,114r25,0r-3,32r-99,0r3,-32r24,0v-19,-24,-35,-56,-52,-82r-65,82r34,0r-3,32r-101,0","w":278},"Y":{"d":"79,0r3,-32r24,0r7,-78r-81,-135r-25,0r3,-32r98,0r-3,32r-21,0r55,100r74,-100r-30,0r2,-32r95,0r-3,32r-22,0r-99,132r-8,81r30,0r-3,32r-96,0","w":271,"k":{"O":15,"u":44,",":51,".":51,"A":29,"a":44,"e":44,"i":22,"o":44,"-":51,":":36,";":36,"S":7}},"Z":{"d":"6,0r4,-29r158,-196v6,-8,13,-13,19,-20r-117,0r-5,39r-35,0r6,-71r206,0r-4,29r-176,216r125,0r6,-40r36,0r-7,72r-216,0","w":249},"[":{"d":"18,99r34,-404r79,0r-2,33r-38,0r-29,339r35,0r-3,32r-76,0","w":124},"\\":{"d":"19,-309r139,328r-30,13r-139,-329","w":146},"]":{"d":"107,-305r-35,404r-79,0r3,-32r38,0r29,-339r-35,0r2,-33r77,0","w":124},"^":{"d":"171,-133r-52,-105r-52,105r-33,0r72,-144r25,0r73,144r-33,0","w":237},"_":{"d":"0,50r0,-20r198,0r0,20r-198,0","w":198},"\u2018":{"d":"95,-309r14,24v-21,8,-39,19,-39,40v6,27,36,68,-13,68v-22,0,-33,-20,-33,-45v0,-48,41,-77,71,-87","w":117,"k":{"\u2018":30,"A":22}},"a":{"d":"57,-73v0,23,6,38,21,38v38,0,73,-107,73,-138v-6,-2,-14,-4,-25,-4v-54,0,-69,70,-69,104xm208,-32r-3,32r-65,0v1,-21,8,-52,12,-91v-12,43,-33,93,-82,93v-43,0,-55,-35,-55,-76v0,-41,19,-136,114,-136v25,0,41,10,68,9v-9,47,-12,116,-17,169r28,0","w":227},"b":{"d":"10,-272r3,-33r75,0v-6,62,-7,127,-21,182v14,-39,40,-88,87,-87v26,0,51,23,51,73v0,72,-38,141,-113,141v-30,0,-63,-9,-72,-15r24,-261r-34,0xm64,-34v66,26,101,-45,99,-98v0,-30,-6,-41,-20,-41v-37,0,-72,79,-79,139","w":220,"k":{"v":5,"y":10,",":12,".":12}},"c":{"d":"156,-46r-4,37v-63,32,-145,2,-141,-79v6,-114,78,-136,157,-114r-6,55r-35,0r1,-28v-48,-11,-74,31,-73,80v0,38,14,64,52,64v17,0,36,-8,49,-15","w":168,"k":{"h":7,"k":7}},"d":{"d":"127,-272r3,-33r74,0r-24,273r29,0r-3,32r-65,0v1,-23,10,-64,12,-91v-12,40,-38,95,-81,95v-39,0,-57,-32,-57,-78v-1,-75,51,-154,139,-132r6,-66r-33,0xm57,-74v0,21,6,38,21,38v26,0,68,-61,74,-137v-63,-21,-95,45,-95,99","w":227,"k":{"v":7,"w":10,"y":12}},"e":{"d":"164,-48r-6,38v-10,6,-36,14,-66,14v-53,0,-81,-32,-81,-85v0,-57,30,-129,108,-129v30,0,59,15,59,48v0,65,-91,79,-123,82v-6,56,70,59,109,32xm136,-157v0,-11,-7,-20,-24,-20v-39,0,-53,41,-57,70v39,-7,81,-18,81,-50","w":183},"f":{"d":"18,-173r3,-33r29,0v-4,-77,51,-115,128,-95r-3,31v-40,-11,-81,1,-81,45r-3,19r48,0r-2,33r-48,0r-13,155v-4,51,-11,120,-87,120v-13,0,-23,-2,-35,-5r3,-34v57,15,73,-11,79,-87r11,-149r-29,0","w":139,"k":{"\u201d":-10,",":12,".":12,"a":7,"e":7,"i":5,"o":7}},"g":{"d":"57,-73v0,29,10,38,21,38v28,0,67,-61,75,-137v-60,-24,-96,42,-96,99xm10,87r3,-38v13,10,39,18,59,18v88,0,68,-92,82,-156v-13,32,-37,89,-85,89v-41,0,-54,-38,-54,-74v0,-51,23,-136,123,-136v25,0,37,12,62,9v-7,59,-12,125,-18,187v-6,68,-25,116,-106,116v-21,0,-51,-7,-66,-15","w":220,"k":{"y":5,"r":2}},"h":{"d":"30,0r25,-272r-34,0r3,-33r74,0v-7,64,-8,126,-21,186v23,-64,55,-91,92,-91v48,0,46,52,40,93r-11,85r27,0r-2,32r-71,0v9,-49,18,-131,18,-149v0,-12,-1,-24,-14,-24v-42,2,-81,102,-86,173r-40,0","w":241,"k":{"y":10}},"i":{"d":"16,-173r3,-33r70,0r-15,174r27,0r-2,32r-69,0r15,-173r-29,0xm44,-280v0,-20,14,-29,33,-29v15,0,26,10,26,24v0,13,-8,30,-33,30v-19,0,-26,-14,-26,-25","w":117},"j":{"d":"16,-173r3,-33r70,0v-21,129,14,275,-112,310r-13,-29v94,-33,64,-148,81,-248r-29,0xm44,-280v0,-20,14,-29,33,-29v15,0,26,10,26,24v0,13,-8,30,-33,30v-19,0,-26,-14,-26,-25","w":117},"k":{"d":"21,-272r3,-33r74,0r-9,101v-2,19,-6,45,-9,63v9,-27,34,-69,84,-69v29,0,45,21,45,43v0,44,-43,67,-80,80v18,17,32,37,48,55r28,0r-3,32r-54,0r-67,-83v-5,28,-10,62,-12,83r-39,0r25,-272r-34,0xm165,-156v0,-10,-6,-17,-17,-17v-23,0,-56,30,-65,80v15,-4,82,-27,82,-63","w":220},"l":{"d":"13,-272r2,-33r75,0r-23,273r27,0r-3,32r-68,0r23,-272r-33,0","w":110,"k":{"y":5}},"m":{"d":"17,-173r2,-33r70,0v-2,31,-7,57,-11,87v21,-67,55,-91,88,-91v48,0,44,43,40,74v6,-21,34,-74,81,-74v45,-1,45,45,40,85r-12,93r28,0r-3,32r-71,0v9,-49,18,-136,18,-152v0,-9,-2,-21,-14,-21v-35,-1,-78,97,-81,173r-41,0r17,-151v0,-10,-2,-22,-14,-22v-39,2,-79,103,-84,173r-40,0r17,-173r-30,0","w":359},"n":{"d":"17,-173r2,-33r70,0v-2,31,-7,57,-11,87v21,-67,55,-91,91,-91v48,0,46,52,40,93r-11,85r27,0r-2,32r-71,0v9,-49,18,-131,18,-149v0,-12,-1,-24,-14,-24v-42,2,-81,102,-86,173r-40,0r17,-173r-30,0","w":241,"k":{"v":5,"y":7}},"o":{"d":"55,-88v0,25,8,57,41,57v46,0,54,-54,54,-89v0,-18,-5,-55,-40,-55v-46,0,-55,52,-55,87xm11,-88v0,-63,32,-122,103,-122v36,0,80,22,80,92v0,86,-47,122,-99,122v-67,0,-84,-51,-84,-92","w":205,"k":{"v":2,"w":2,"y":5,"x":2}},"p":{"d":"-5,99r3,-32r24,0r21,-240r-30,0r3,-33r70,0r-11,84v8,-27,28,-88,86,-88v43,0,51,46,51,76v0,86,-57,152,-145,133r-6,68r29,0r-2,32r-93,0xm170,-131v0,-19,-3,-42,-21,-42v-30,0,-67,58,-79,136v7,3,19,5,34,5v47,0,66,-58,66,-99","w":227,"k":{"y":10,",":12,".":12}},"q":{"d":"57,-72v0,19,6,37,21,37v24,0,59,-47,76,-136v-65,-29,-97,47,-97,99xm107,99r3,-32r23,0r7,-73v3,-30,6,-55,12,-82v-13,35,-33,90,-83,90v-39,0,-54,-38,-54,-76v0,-92,74,-162,166,-127r18,0v-12,80,-17,183,-26,268r29,0r-2,32r-93,0","w":227},"r":{"d":"17,-173r2,-33r68,0v-1,26,-8,57,-8,80v13,-49,33,-95,90,-82r-6,40v-70,-14,-82,100,-89,168r-42,0r15,-173r-30,0","w":168,"k":{"g":10,"v":5,",":36,".":36,"k":7,"a":12,"e":5,"o":5,"c":7,"d":12,"q":5,"s":5,"-":15}},"s":{"d":"55,-61r0,26v27,9,75,12,76,-23v0,-26,-39,-28,-60,-36v-19,-7,-45,-18,-45,-53v0,-31,23,-63,84,-63v32,0,54,9,61,12r-2,51r-34,0r1,-24v-19,-12,-73,-5,-68,19v7,43,105,22,105,89v0,32,-23,67,-83,67v-32,0,-55,-6,-73,-12r2,-53r36,0","w":190,"k":{"w":5}},"t":{"d":"16,-173r3,-33r29,0r5,-47r42,-3r-5,50r57,0r-2,33r-57,0r-10,118v-3,33,40,23,58,12r-3,35v-12,6,-28,10,-46,10v-90,-4,-37,-100,-41,-175r-30,0","w":146},"u":{"d":"18,-173r3,-33r74,0r-20,147v0,14,6,24,17,24v25,0,67,-62,81,-171r41,0v-10,55,-12,115,-18,174r28,0r-3,32r-67,0v1,-25,11,-62,13,-89v-15,46,-42,91,-89,91v-80,0,-32,-110,-32,-175r-28,0","w":241},"v":{"d":"15,-173r2,-33r72,0v-4,41,-6,95,-6,108v0,32,3,65,22,65v36,0,62,-87,66,-140r-31,0r3,-33r70,0v0,71,-25,210,-116,210v-73,0,-54,-117,-53,-177r-29,0","w":227,"k":{",":36,".":36,"a":2}},"w":{"d":"17,-173r2,-33r74,0r-11,128v0,23,4,45,21,45v30,7,60,-75,63,-173r42,0r-9,116v0,43,7,57,23,57v30,0,55,-67,57,-140r-28,0r3,-33r67,0v-2,107,-33,210,-106,210v-44,1,-46,-47,-49,-74v-3,21,-22,74,-72,74v-78,0,-50,-110,-48,-177r-29,0","w":337,"k":{",":36,".":36,"h":5}},"x":{"d":"6,0r3,-32r77,-73r-40,-68r-28,0r3,-33r56,0r45,78r46,-45r-31,0r3,-33r74,0r-3,33r-76,68r42,73r29,0r-3,32r-56,0r-45,-79r-48,47r30,0r-2,32r-76,0","w":220},"y":{"d":"-3,100r3,-33v51,13,69,-29,86,-64r-54,-176r-26,0r3,-33r61,0v13,54,32,106,40,165r51,-132r-33,0r3,-33r71,0r-3,31v-39,84,-99,295,-177,279v-7,0,-16,-1,-25,-4","w":212,"k":{",":44,".":44,"a":7,"e":5,"o":5}},"z":{"d":"10,0r3,-31r120,-143r-72,1r-3,27r-36,0r5,-60r161,0r-2,30r-123,145r81,-1r4,-30r36,0r-6,62r-168,0","w":198,"k":{"e":-5}},"{":{"d":"68,99v-60,-2,-31,-95,-31,-147v0,-21,-12,-39,-27,-40r3,-30v41,-2,40,-83,47,-128v9,-61,31,-61,82,-59r-3,28v-59,-9,-41,71,-50,114v-9,43,-32,55,-41,61v9,2,29,16,29,46v-1,35,-9,71,-9,107v-3,16,14,24,34,21r-3,27r-31,0","w":124},"|":{"d":"28,99r0,-396r32,0r0,396r-32,0","w":87},"}":{"d":"19,-305v96,-18,62,84,62,148v0,21,12,38,27,39r-3,30v-40,3,-40,83,-46,129v-8,60,-32,59,-82,58r2,-27v59,9,42,-70,50,-114v8,-43,33,-55,42,-61v-9,-2,-29,-16,-29,-46v0,-36,8,-71,8,-107v3,-16,-14,-24,-34,-21","w":124},"~":{"d":"74,-130v27,-1,60,27,84,27v16,0,26,-15,35,-29r14,28v-9,17,-22,34,-49,34v-28,1,-60,-27,-85,-28v-16,0,-26,16,-35,30r-14,-29v9,-17,23,-33,50,-33","w":237},"'":{"d":"59,-177v-29,-4,-15,-85,-23,-110v0,-12,11,-22,23,-22v43,0,14,74,14,118v0,11,-8,14,-14,14","w":117},"\u201c":{"d":"95,-309r14,24v-21,8,-39,19,-39,40v6,27,36,68,-13,68v-22,0,-33,-20,-33,-45v0,-48,41,-77,71,-87xm182,-309r14,24v-21,8,-39,19,-39,40v6,27,36,68,-13,68v-22,0,-34,-20,-34,-45v0,-48,42,-77,72,-87","w":190,"k":{"A":10}},"\u2013":{"d":"-3,-95r3,-35r198,0r-3,35r-198,0","w":198},"\u201d":{"d":"104,-177r-14,-25v21,-8,38,-19,38,-40v-5,-27,-34,-67,14,-67v22,0,33,19,33,44v0,48,-41,78,-71,88xm17,-177r-14,-25v21,-8,39,-19,39,-40v-6,-27,-36,-67,13,-67v22,0,33,19,33,44v0,48,-41,78,-71,88","w":190,"k":{" ":15}},"\u2026":{"d":"33,-21v0,-18,11,-28,29,-28v20,0,29,12,29,26v0,17,-10,28,-30,28v-12,0,-28,-5,-28,-26xm165,-21v0,-18,11,-28,29,-28v20,0,29,12,29,26v0,17,-11,28,-31,28v-12,0,-27,-5,-27,-26xm297,-21v0,-18,11,-28,29,-28v20,0,29,12,29,26v0,17,-11,28,-31,28v-12,0,-27,-5,-27,-26","w":396},"`":{"d":"43,-309r66,61r-26,18r-68,-59","w":110},"\u2014":{"d":"-3,-95r3,-35r396,0r-3,35r-396,0","w":396},"\u2122":{"d":"69,-115r0,-137r-49,0r0,-25r131,0r0,25r-49,0r0,137r-33,0xm335,-115r-1,-130r-48,130r-22,0r-49,-130r0,130r-30,0r0,-162r47,0r44,113r44,-113r45,0r0,162r-30,0","w":392},"\u00d7":{"d":"185,-9r-69,-69r-70,69r-22,-21r70,-70r-70,-70r22,-22r70,70r69,-70r22,22r-70,70r70,70","w":237},"\u00a0":{"w":117,"k":{"T":15,"V":36,"W":15,"Y":44,"A":15}}}});


/*
Copyright (c) 2009 Victor Stanciu - http://www.victorstanciu.ro

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/

Carousel = Class.create(Abstract, {
	initialize: function (scroller, slides, controls, options) {
		this.scrolling	= false;
		this.scroller	= $(scroller);
		this.slides		= slides;
		this.controls	= controls;

		this.options    = Object.extend({
            duration:           1,
            auto:               false,
            frequency:          8,
            visibleSlides:      1,
            controlClassName:   'carousel-control',
            jumperClassName:    'carousel-jumper',
            disabledClassName:  'carousel-disabled',
            selectedClassName:  'carousel-selected',
            circular:           false,
            wheel:              true,
            effect:             'scroll',
            transition:         'sinoidal'
        }, options || {});
        
        if (this.options.effect == 'fade') {
            this.options.circular = true;
        }

		this.slides.each(function(slide, index) {
			slide._index = index;
        });

		if (this.controls) {
            this.controls.invoke('observe', 'click', this.click.bind(this));
        }
        
        if (this.options.wheel) {            
            this.scroller.observe('mousewheel', this.wheel.bindAsEventListener(this)).observe('DOMMouseScroll', this.wheel.bindAsEventListener(this));;
        }

        if (this.options.auto) {
            this.start();
        }

		if (this.options.initial) {
			var initialIndex = this.slides.indexOf($(this.options.initial));
			if (initialIndex > (this.options.visibleSlides - 1) && this.options.visibleSlides > 1) {               
				if (initialIndex > this.slides.length - (this.options.visibleSlides + 1)) {
					initialIndex = this.slides.length - this.options.visibleSlides;
				}
			}
            this.moveTo(this.slides[initialIndex]);
		}
	},

	click: function (event) {
		this.stop();

		var element = event.findElement('a') || event.findElement('li');

		if (!element.hasClassName(this.options.disabledClassName)) {
			if (element.hasClassName(this.options.controlClassName)) {
				eval("this." + element.rel + "()");
            } else if (element.hasClassName(this.options.jumperClassName)) {
                this.moveTo(element.rel);
                if (this.options.selectedClassName) {
                    this.controls.invoke('removeClassName', this.options.selectedClassName);
                    element.addClassName(this.options.selectedClassName);
                }
            }
        }

		this.deactivateControls();

		event.stop();
    },

	moveTo: function (element) {
		if (this.options.beforeMove && (typeof this.options.beforeMove == 'function')) {
			this.options.beforeMove(element);
        }

		this.previous = this.current ? this.current : this.slides[0];
		this.current  = $(element);
    
		var scrollerOffset = this.scroller.cumulativeOffset();
		var elementOffset  = this.current.cumulativeOffset();

		if (this.scrolling) {
			this.scrolling.cancel();
		}

        switch (this.options.effect) {
            case 'fade':               
                this.scrolling = new Effect.Opacity(this.scroller, {
                    from:   1.0,
                    to:     0,
                    duration: this.options.duration,
                    afterFinish: (function () {
                        this.scroller.scrollLeft = elementOffset[0] - scrollerOffset[0];
                        this.scroller.scrollTop  = elementOffset[1] - scrollerOffset[1];

                        new Effect.Opacity(this.scroller, {
                            from: 0,
                            to: 1.0,
                            duration: this.options.duration,
                            afterFinish: (function () {
                                if (this.controls) {
                                    this.activateControls();
                                }
                                if (this.options.afterMove && (typeof this.options.afterMove == 'function')) {
                                    this.options.afterMove();
                                }
                            }).bind(this)
                        });
                    }
                ).bind(this)});
            break;
            case 'scroll':
            default:
                var transition;
                switch (this.options.transition) {
                    case 'spring':
                        transition = Effect.Transitions.spring;
                        break;
                    case 'sinoidal':
                    default:
                        transition = Effect.Transitions.sinoidal;
                        break;
                }

                this.scrolling = new Effect.SmoothScroll(this.scroller, {
                    duration: this.options.duration,
                    x: (elementOffset[0] - scrollerOffset[0]),
                    y: (elementOffset[1] - scrollerOffset[1]),
                    transition: transition,
                    afterFinish: (function () {
                        if (this.controls) {
                            this.activateControls();
                        }
                        if (this.options.afterMove && (typeof this.options.afterMove == 'function')) {
                            this.options.afterMove();
                        }                        
                        this.scrolling = false;
                    }).bind(this)});
            break;
        }

		return false;
	},

	prev: function () {
		if (this.current) {
			var currentIndex = this.current._index;
			var prevIndex = (currentIndex == 0) ? (this.options.circular ? this.slides.length - 1 : 0) : currentIndex - 1;
        } else {
            var prevIndex = (this.options.circular ? this.slides.length - 1 : 0);
        }

		if (prevIndex == (this.slides.length - 1) && this.options.circular && this.options.effect != 'fade') {
			this.scroller.scrollLeft =  (this.slides.length - 1) * this.slides.first().getWidth();
			this.scroller.scrollTop =  (this.slides.length - 1) * this.slides.first().getHeight();
			prevIndex = this.slides.length - 2;
        }

		this.moveTo(this.slides[prevIndex]);
	},

	next: function () {
		if (this.current) {
			var currentIndex = this.current._index;
			var nextIndex = (this.slides.length - 1 == currentIndex) ? (this.options.circular ? 0 : currentIndex) : currentIndex + 1;
        } else {
            var nextIndex = 1;
        }

		if (nextIndex == 0 && this.options.circular && this.options.effect != 'fade') {
			this.scroller.scrollLeft = 0;
			this.scroller.scrollTop  = 0;
			nextIndex = 1;
        }

		if (nextIndex > this.slides.length - (this.options.visibleSlides + 1)) {
			nextIndex = this.slides.length - this.options.visibleSlides;
		}		

		this.moveTo(this.slides[nextIndex]);
	},

	first: function () {
		this.moveTo(this.slides[0]);
    },

	last: function () {
		this.moveTo(this.slides[this.slides.length - 1]);
    },

	toggle: function () {
		if (this.previous) {
			this.moveTo(this.slides[this.previous._index]);
        } else {
            return false;
        }
    },

	stop: function () {
	  this.stopped = true;
		if (this.timer) {
			clearTimeout(this.timer);
		}
	},

	start: function () { 
        this.periodicallyUpdate();
    },

	pause: function () {
		this.stop();
		this.activateControls();
    },

	resume: function (event) {
		if (event) {
			var related = event.relatedTarget || event.toElement;
			if (!related || (!this.slides.include(related) && !this.slides.any(function (slide) { return related.descendantOf(slide); }))) {
				this.start();
            }
        } else {
            this.start();
        }
    },

	periodicallyUpdate: function () {
		if (this.timer != null) {
			clearTimeout(this.timer);
			this.next();
        }
		this.timer = setTimeout(this.periodicallyUpdate.bind(this), this.options.frequency * 1000);
    },
    
    wheel: function (event) {
      if (this.options.beforeWheel) { this.options.beforeWheel(); }
        event.cancelBubble = true;
        event.returnValue = false;
        
		var delta = 0;
		if (!event) {
            event = window.event;
        }
		if (event.wheelDelta) {
			delta = event.wheelDelta / 120; 
		} else if (event.detail) { 
            delta = -event.detail / 3;	
        }        
       
        if (!this.scrolling) {
            this.deactivateControls();
            if (delta > 0) {
                this.prev();
            } else {
                this.next();
            }            
        }
        
		return Math.round(delta); //Safari Round
    },

	deactivateControls: function () {
		this.controls.invoke('addClassName', this.options.disabledClassName);
    },

	activateControls: function () {
		this.controls.invoke('removeClassName', this.options.disabledClassName);
    }
});


Effect.SmoothScroll = Class.create();
Object.extend(Object.extend(Effect.SmoothScroll.prototype, Effect.Base.prototype), {
	initialize: function (element) {
		this.element = $(element);
		var options = Object.extend({ x: 0, y: 0, mode: 'absolute' } , arguments[1] || {});
		this.start(options);
    },

	setup: function () {
		if (this.options.continuous && !this.element._ext) {
			this.element.cleanWhitespace();
			this.element._ext = true;
			this.element.appendChild(this.element.firstChild);
        }

		this.originalLeft = this.element.scrollLeft;
		this.originalTop  = this.element.scrollTop;

		if (this.options.mode == 'absolute') {
			this.options.x -= this.originalLeft;
			this.options.y -= this.originalTop;
        }
    },

	update: function (position) {
		this.element.scrollLeft = this.options.x * position + this.originalLeft;
		this.element.scrollTop  = this.options.y * position + this.originalTop;
    }
});

var Slideshow = Class.create({
  initialize: function (wrapper, options) {
    this.options = {
      frequency: 20,
      controlBoxSelector: 'slideshow-controls',
      slideSelector: '.slide',
      progressSelector: '.progress'
    };
    Object.extend(this.options, options || {});
    
    this.wrapper     = $(wrapper);
    this.slides      = wrapper.select(this.options.slideSelector);
    this.controlBox  = $(this.options.controlBoxSelector);
    this.progressBar = this.controlBox.down(this.options.progressSelector);
    
    this.slides.each(function (slide, index) {
      var el = new Element('li').update("&#9679;");
      if (index == 0) el.addClassName('first');
      if (index == this.slides.length - 1) el.addClassName('last');
      this.controlBox.appendChild(el);
    }, this);
    
    if (this.slides.length <= 1) this.controlBox.hide();
    
    this.controls = this.controlBox.select('li:not(.progress)');
    this.controlsWidth = (this.controls.first().getWidth() * this.controls.length) / this.controlBox.getWidth() * 100;

    this.carousel = new Carousel(this.wrapper, this.slides, this.controls, {
      wheel: this.options.wheel,
      circular: true, 
      auto: true,
      visibleSlides: 1,
      duration: 1.0,
      frequency: this.options.frequency,
      beforeMove: function (current) { this.updateControls(current); }.bind(this),
      beforeWheel: this.stop.bind(this)
    });
        
    this.attachEvents();
    this.updateControls(this.slides[0]);
  },
  
  attachEvents: function () {
    this.slides.each(function (slide, index) {
      slide.observe('click', this.stop.bind(this));
      this.controls[index].observe('click', function () { this.carousel.moveTo(slide) }.bind(this));
    }, this);
  },
  
  updateControls: function (current) {
    this.controls.invoke('removeClassName', 'active');
    this.controls[current._index].addClassName('active');
    
    if (!this.progressBar) { return; }
    
    if (this.effect) {
      this.effect.cancel();
      this.setProgressValue(0);
    }
    
    if (!this.carousel.stopped) {
      var element = this.progressBar, opacity = 0, fadeDuration = ((100 - this.controlsWidth) / 15);
      
      this.effect = new Effect.Tween(element, this.controlsWidth, 100, {
        duration: this.options.frequency,
        afterUpdate: function (effect) {
          if (effect.position <= effect.options.from + fadeDuration)
            opacity = effect.position - effect.options.from;
          else if (effect.position >= effect.options.to - fadeDuration)
            opacity = effect.options.to - effect.position;
            
          element.setOpacity(opacity * (1 / fadeDuration));
        }
      }, this.setProgressValue.bind(this));
    }
  },
  
  setProgressValue: function (position) {
    this.progressBar.style.width = position + '%';
  },
  
  stop: function () {
    this.carousel.stop();
  }  
});

Event.addBehavior({
  '#slideshow-wrapper' : function () { (new Slideshow(this, { wheel: this.readAttribute('wheel'), frequency: (this.readAttribute('frequency') || 6) })); }
});

var Voter = Class.create({
  initialize: function(container, options) {
    this.setup(container, options);
  },
  
  refresh: function(container, options) {
    this.upThumb.stopObserving('click', this.upVote.bind(this));
    this.downThumb.stopObserving('click', this.downVote.bind(this));    
    this.setup(container, options);
    if (this.previousVote) this.addVote(this.previousVote);
  },
  
  setup: function(container, options) {
    this.container   = container;
    thumbEls         = container.select(options.thumbs);
    this.scoreEl     = container.select(options.score)[0];
    this.multiEl     = container.select(options.multiplier)[0];
    this.upThumb     = thumbEls[0];
    this.downThumb   = thumbEls[1];
    this.score       = parseInt(this.scoreEl.innerHTML.match(/-?\d+$/), 10);
    this.voteable_id = parseInt(this.container.id.match(/-?\d+$/), 10);
    this.upValue     = parseInt(this.upThumb.href.match(/-?\d+$/), 10);
    this.downValue   = parseInt(this.downThumb.href.match(/-?\d+$/), 10);
    this.upThumb.observe('click', this.upVote.bind(this));
    this.downThumb.observe('click', this.downVote.bind(this));    
  },
  
  addVote: function(vote) {
    this.previousVote = vote;
    this.upThumb.addClassName('inactive');
    this.downThumb.addClassName('inactive');
    (vote.direction == 'up' ? this.upThumb : this.downThumb).removeClassName('inactive');
  },
  
  upVote: function(event) {
    event.stop();
    if (!this.previousVote || this.previousVote.direction == 'down') 
      this.updateScore(this.upThumb, this.upValue*this.multiplier(), 'up');
  },
  
  downVote: function(event) {
    event.stop();
    if(!this.previousVote || this.previousVote.direction == 'up')
      this.updateScore(this.downThumb, this.downValue*this.multiplier(), 'down');
  },
  
  multiplier: function(event) {
    return this.multiEl ? this.multiEl.value : 1;
  },
  
  updateScore: function(thumb, points, direction) {
    var vote = {voteable_id: this.voteable_id, direction: direction, points: points};
    if(vote.direction == 'up' || (vote.direction == 'down' && this.previousVote))
      this.score += points;

    this.scoreEl.update(this.score);
    this.addVote(vote);
    new Ajax.Request(thumb.href.replace(/-?\d+$/, points), { method: 'post', asynchronous: true });
  }
  
});

var Voteable = Class.create({
  votes: $H(),
  voters: $H(),

  initialize: function (options) {
    this.options = {
      container: null,
      score: '.score',
      thumbs: '.thumbs a',
      multiplier: '#multiplier',
      votes: []
    };
    
    Object.extend(this.options, options || {});
    
    this.options.votes.each(function(vote) { 
      this.votes.set(vote[0], {voteable_id: vote[0],
                               direction:   vote[1],
                               points:      vote[2]});
    }, this);
        
    this.refresh();

    var voteable = this;
    Ajax.Responders.register({
      onComplete : function() { voteable.refresh(); }
    });
  },
  
  refresh: function() {
    $$(this.options.container).each(function(el) {
      var voter = this.voters.get(el.id);
      voter ? voter.refresh(el, this.options) : this.setVoter(el);
    }, this);
  },
  
  setVoter: function(el) {
    voter = new Voter(el, this.options);
    var vote = this.votes.get(voter.voteable_id);
    if (vote) voter.addVote(vote);
    this.voters.set(el.id, voter);
  }
});