(function(){
  function wheel(e){
    if(e.wheelDelta){
      delta = e.wheelDelta/120;
    }else if(e.detail){
      delta =- e.detail/3;
    }
    if(!delta){
      return;
    }
    var custom_event = Event.element(e).fire('mouse:wheel',{
      delta: delta
    });
    if(custom_event.stopped){
      Event.stop(e);
      return false;
    }
  }
  document.observe('mousewheel',wheel);
  document.observe('DOMMouseScroll',wheel);
})();

var fbf = {
  Grid : {
    // height : 310,
    // width : 410,
    elements : {
      proxy : [[],[],[]]
    },
    height:222,
    width: 322,
    cache : {},
    url : '/m.php',
    locked : false,
    count: 1,
    fontSize : 36
  }
};

fbf.Preload = function(url){
  var image = new Image();
  image.src = url;
};

fbf.Grid.Base = function(){
  var xoverlay;
  var element;
  var cm, ct, tfx;
  var C, N, NE, E, SE, S, SW, W, NW;
  var X = 0, Y = 0;
  var T = 0, L = 0;
  var _g = [[],[],[]];
  var g = {};
  var t = {};
  var cb = {};
  var modal;
  var historyClose = false;
  var tpos = null;
  var startPage = true;
  
  var history, anchorHistory;
  
  function _onResize(e){    
    var d = document.viewport.getDimensions(); 
    
    var l=L/fbf.Grid.width;
    var t=T/fbf.Grid.height;
    
    _setCss(d);    
    _setProxy();
    
    L = l*fbf.Grid.width;
    T = t*fbf.Grid.height;
    X = -L;
    Y = -T;
    
    fbf.Grid.elements.grid.setStyle({
      left : -L+'px',
      top : -T+'px'
    });
    
    $('m_'+g.NW).setStyle({
      left : L+'px',
      top : T+'px'
    });
    
    $('m_'+g.N).setStyle({
      left : L+fbf.Grid.width+'px',
      top : T+'px'
    });
    
    $('m_'+g.NE).setStyle({
      left : L+(fbf.Grid.width*2)+'px',
      top : T+'px'
    });
    
    $('m_'+g.W).setStyle({
      left : L+'px',
      top : T+fbf.Grid.height+'px'
    });
    
    $('m_'+g.C).setStyle({
      left : L+fbf.Grid.width+'px',
      top : T+fbf.Grid.height+'px'
    });
    
    $('m_'+g.E).setStyle({
      left : L+(fbf.Grid.width*2)+'px',
      top : T+fbf.Grid.height+'px'
    });
    
    $('m_'+g.SW).setStyle({
      left : L+'px',
      top : T+(fbf.Grid.height*2)+'px'
    });
    
    $('m_'+g.S).setStyle({
      left : L+fbf.Grid.width+'px',
      top : T+(fbf.Grid.height*2)+'px'
    });
    
    $('m_'+g.SE).setStyle({
      left : L+(fbf.Grid.width*2)+'px',
      top : T+(fbf.Grid.height*2)+'px'
    });
    
    // var h = d.height/2;
    // var w = d.width/2;
    // var x = fbf.Grid.width/2;
    // var y = fbf.Grid.height/2;
    // 
    // C.update(h-y, w+x, h+y, w-x); 
    // N.update(h-(y*3), w+x, h-y, w-x);
    // NE.update(h-(y*3), w+(x*3), h-y, w+x);
    // E.update(h-y, w+(x*3), h+y, w+x);
    // SE.update(h+y, w+(x*3), h+(y*3), w+x);
    // S.update(h+y, w+x, h+(y*3), w-x);
    // SW.update(h+y, w-x, h+(y*3), w-(x*3));
    // W.update(h-y, w-x, h+y, w-(x*3));
    // NW.update(h-(y*3), w-x, h-y, w-(x*3));
    
    
    // var _t = 90;
    // var _l = (d.width/2)-((fbf.Grid.width*3)/2);
    // 
    // N.update(_t, _l+(fbf.Grid.width*2), _t+fbf.Grid.height, _l+fbf.Grid.width);
    // NE.update(_t, _l+(fbf.Grid.width*3), _t+fbf.Grid.height, _l+(fbf.Grid.width*2));
    // E.update(_t+fbf.Grid.height, _l+(fbf.Grid.width*3), _t+(fbf.Grid.height*2), _l+(fbf.Grid.width*2));
    // SE.update(_t+(fbf.Grid.height*2), _l+(fbf.Grid.width*3), _t+(fbf.Grid.height*3), _l+(fbf.Grid.width*2));
    // S.update(_t+(fbf.Grid.height*2), _l+(fbf.Grid.width*2), _t+(fbf.Grid.height*3), _l+fbf.Grid.width);
    // SW.update(_t+(fbf.Grid.height*2), _l+fbf.Grid.width, _t+(fbf.Grid.height*3), _l);
    // W.update(_t+fbf.Grid.height, _l+fbf.Grid.width, _t+(fbf.Grid.height*2), _l);
    // NW.update(_t, _l+fbf.Grid.width, _t+fbf.Grid.height, _l);
    // C.update(_t+fbf.Grid.height, _l+(fbf.Grid.width*2), _t+(fbf.Grid.height*2), _l+fbf.Grid.width);
    
  }
  
  function _draw(id, x, y){
    var c = fbf.Grid.cache[id].render();
    var module = new Element('div', {className: 'module'}).update(c);
    module.setStyle({
      'float' : 'none',
      'left' : x+'px',
      'position' : 'absolute',
      'top' : y+'px'
    });
    module.id = 'm_'+id;
    fbf.Grid.elements.grid.insert(module);
  }
  
  function _erase(id){   
    $('m_'+id).remove();
  }
  
  function _N(e){      
    var m = fbf.Grid.cache[g.N].neighbours;
        
    fbf.Grid.cache[g.NE].updateNeighbours({'N' : m.NE, 'NW' : m.N});    
    fbf.Grid.cache[g.NW].updateNeighbours({'N' : m.NW, 'NE' : m.N});
    
    T=T-fbf.Grid.height;
    
    _draw(m.NW, L, T);
    _draw(m.N, L+fbf.Grid.width, T);
    _draw(m.NE, L+(fbf.Grid.width*2), T);
    
    fbf.Grid.cache[m.N].setNeighbours({'E' : m.NE, 'SE' : g.NE, 'S' : g.N, 'SW' : g.NW, 'W' : m.NW});
    fbf.Grid.cache[m.NE].setNeighbours({'S' : g.NE, 'SW' : g.N, 'W' : m.N});
    fbf.Grid.cache[m.NW].setNeighbours({'E' : m.N, 'SE' : g.N, 'S' : g.NW});
    
    var callback = function(){      
      _erase(g.SW);
      _erase(g.S);
      _erase(g.SE);
      
      g.SW = g.W; g.S = g.C; g.SE = g.E;
      g.W = g.NW; g.C = g.N; g.E = g.NE;
      g.NW = m.NW; g.N = m.N; g.NE = m.NE;  
      
      _mouseenter('N');
              
    };    
    
    _setCenter(g.N);
    _tween(X, Y+fbf.Grid.height, callback);    
  }
  
  function _S(e){   
       
    var m = fbf.Grid.cache[g.S].neighbours;
    
    fbf.Grid.cache[g.SE].updateNeighbours({'S' : m.SE, 'SW' : m.S});
    fbf.Grid.cache[g.SW].updateNeighbours({'S' : m.SW, 'SE' : m.S});
    
    T=T+fbf.Grid.height;
    
    _draw(m.SW, L, T+(fbf.Grid.height*2));
    _draw(m.S, L+fbf.Grid.width, T+(fbf.Grid.height*2));
    _draw(m.SE, L+(fbf.Grid.width*2), T+(fbf.Grid.height*2));
    
    fbf.Grid.cache[m.S].setNeighbours({'N' : g.S, 'NE' : g.SE, 'E' : m.SE, 'W' : m.SW, 'NW': g.SW});
    fbf.Grid.cache[m.SE].setNeighbours({'N' : g.SE, 'W' : m.S, 'NW' : g.S});
    fbf.Grid.cache[m.SW].setNeighbours({'N' : g.SW, 'E' : m.S, 'NE' : g.S});
    
    var callback = function(){
      
      _erase(g.NW);
      _erase(g.N);
      _erase(g.NE);
            
      g.NW = g.W; g.N = g.C; g.NE = g.E;
      g.W = g.SW; g.C = g.S; g.E = g.SE;      
      g.SW = m.SW; g.S = m.S; g.SE = m.SE;
      
      _mouseenter('S');
      
    };    
    
    _setCenter(g.S);    
    _tween(X, Y-fbf.Grid.height, callback);    
  }
  
  function _E(e){        
    var m = fbf.Grid.cache[g.E].neighbours;
    
    fbf.Grid.cache[g.NE].updateNeighbours({'E' : m.NE, 'SE' : m.E});    
    fbf.Grid.cache[g.SE].updateNeighbours({'NE' : m.E, 'E' : m.SE});
    
    L=L+fbf.Grid.width;
        
    _draw(m.NE, L+(fbf.Grid.width*2), T);
    _draw(m.E, L+(fbf.Grid.width*2), T+fbf.Grid.height);
    _draw(m.SE, L+(fbf.Grid.width*2), T+(fbf.Grid.height*2));
    
    fbf.Grid.cache[m.NE].setNeighbours({'S' : m.E, 'SW' : g.E, 'W' : g.NE});
    fbf.Grid.cache[m.E].setNeighbours({'N' : m.NE, 'S' : m.SE, 'SW' : g.SE, 'W' : g.E, 'NW' : g.NE});
    fbf.Grid.cache[m.SE].setNeighbours({'N' : m.E, 'W' : g.SE, 'NW' : g.E});
    
    var callback = function(){
      
      _erase(g.NW);
      _erase(g.W);
      _erase(g.SW);
      
      g.NW = g.N; g.W = g.C; g.SW = g.S;      
      g.N = g.NE; g.C = g.E; g.S = g.SE;      
      g.NE = m.NE; g.E = m.E; g.SE = m.SE;
      
      _mouseenter('E');
      
    };
        
    _setCenter(g.E);    
    _tween(X-fbf.Grid.width, Y, callback);
  }
  
  function _W(e){    
    var m = fbf.Grid.cache[g.W].neighbours;
    
    
    fbf.Grid.cache[g.NW].updateNeighbours({'W' : m.NW, 'SW' : m.W});    
    fbf.Grid.cache[g.SW].updateNeighbours({'W' : m.SW, 'NW' : m.W});
    
    L=L-fbf.Grid.width;
    
    _draw(m.NW, L, T);
    _draw(m.W, L, T+fbf.Grid.height);
    _draw(m.SW, L, T+(fbf.Grid.height*2));
    
    fbf.Grid.cache[m.SW].setNeighbours({'N' : m.W, 'NE' : g.W, 'E' : g.SW});
    fbf.Grid.cache[m.W].setNeighbours({'N' : m.NW, 'NE' : g.NW, 'E' : g.W, 'SE' : g.SW, 'S' : m.SW});
    fbf.Grid.cache[m.NW].setNeighbours({'E' : g.NW, 'SE' : g.W, 'S' : m.W});
    
    var callback = function(){
            
      _erase(g.NE);
      _erase(g.E);
      _erase(g.SE);
      
      g.NE = g.N; g.E = g.C; g.SE = g.S;      
      g.N = g.NW; g.C = g.W; g.S = g.SW;      
      g.NW = m.NW; g.W = m.W; g.SW = m.SW;
            
      _mouseenter('W');      
            
    };
    
    _setCenter(g.W);    
    _tween(X+fbf.Grid.width, Y, callback);    
  }
  
  function _NE(e){    
    var m = fbf.Grid.cache[g.NE].neighbours;
    
    fbf.Grid.cache[g.N].updateNeighbours({'N' : m.NW, 'NE' : m.N});    
    fbf.Grid.cache[g.E].updateNeighbours({'NE' : m.E, 'E' : m.SE});    
    fbf.Grid.cache[g.SE].updateNeighbours({'NE' : m.SE});    
    fbf.Grid.cache[g.NW].updateNeighbours({'NE' : m.NW});    
    
    T=T-fbf.Grid.height;
    L=L+fbf.Grid.width;   
    
    _draw(m.NW, L, T);
    _draw(m.N, L+(fbf.Grid.width), T);
    _draw(m.NE, L+(fbf.Grid.width*2), T);
    _draw(m.E, L+(fbf.Grid.width*2), T+fbf.Grid.height);
    _draw(m.SE, L+(fbf.Grid.width*2), T+(fbf.Grid.height*2));
    
    fbf.Grid.cache[m.N].setNeighbours({'E' : m.NE, 'SE' : m.E, 'S' : g.NE, 'SW' : g.N, 'W' : m.NW});      
    fbf.Grid.cache[m.NE].setNeighbours({'S' : m.E, 'SW' : g.NE, 'W' : m.N});    
    fbf.Grid.cache[m.E].setNeighbours({'N' : m.NE, 'S' : m.SE, 'SW' : g.E, 'W' : g.NE, 'NW' : m.N});
    fbf.Grid.cache[m.SE].setNeighbours({'N' : m.E, 'SW' : g.SE, 'W' : g.E, 'NW' : g.NE});      
    fbf.Grid.cache[m.NW].setNeighbours({'E' : m.N, 'SE' : g.NE, 'S' : g.N, 'SW' : g.NW});
    
    var callback = function(){  
      
      _erase(g.SE);
      _erase(g.S);      
      _erase(g.SW);
      _erase(g.W);
      _erase(g.NW);
      
      g.SW = g.C; g.W = g.N; g.S = g.E; 
      g.C = g.NE; g.NW = m.NW; g.N = m.N;
      g.NE = m.NE; g.E = m.E; g.SE = m.SE;     
      
      _mouseenter('NE');             
      
    };
    
    _setCenter(g.NE);    
    _tween(X-fbf.Grid.width, Y+fbf.Grid.height, callback);    
  }
  
  function _SE(e){    
    var m = fbf.Grid.cache[g.SE].neighbours;
    
    fbf.Grid.cache[g.NE].updateNeighbours({'SE' : m.NE});    
    fbf.Grid.cache[g.E].updateNeighbours({'E' : m.NE, 'SE' : m.E});    
    fbf.Grid.cache[g.S].updateNeighbours({'SE' : m.S, 'S' : m.SW});    
    fbf.Grid.cache[g.SW].updateNeighbours({'SE' : m.SW});    
    
    T=T+fbf.Grid.height;
    L=L+fbf.Grid.width;   

    _draw(m.NE, L+(fbf.Grid.width*2), T);
    _draw(m.E, L+(fbf.Grid.width*2), T+fbf.Grid.height);
    _draw(m.SE, L+(fbf.Grid.width*2), T+(fbf.Grid.height*2));
    _draw(m.S, L+fbf.Grid.width, T+(fbf.Grid.height*2));
    _draw(m.SW, L, T+(fbf.Grid.height*2));
    
    fbf.Grid.cache[m.NE].setNeighbours({'S' : m.E, 'SW' : g.SE, 'W' : g.E, 'NW' : g.NE});    
    fbf.Grid.cache[m.E].setNeighbours({'S' : m.SE, 'SW' : m.S, 'W' : g.SE, 'NW' : g.E, 'N' : m.NE});      
    fbf.Grid.cache[m.SE].setNeighbours({'N' : m.E, 'W' : m.S, 'NW' : g.SE});      
    fbf.Grid.cache[m.S].setNeighbours({'N' : g.SE, 'NE' : m.E, 'E' : m.SE, 'W' : m.SW, 'NW' : g.S});           
    fbf.Grid.cache[m.SW].setNeighbours({'N' : g.S, 'NE' : g.SE, 'E' : m.S, 'NW' : g.SW});
    
    var callback = function(){  
      
      _erase(g.NW);
      _erase(g.N);     
      _erase(g.NE);
      _erase(g.W);
      _erase(g.SW);
      
      g.NW = g.C; g.W = g.S; g.N = g.E;
      g.C = g.SE; g.NE = m.NE; g.E = m.E;
      g.SE = m.SE; g.S = m.S; g.SW = m.SW 
      
      _mouseenter('SE');
      
    };
    
    _setCenter(g.SE);    
    _tween(X-fbf.Grid.width, Y-fbf.Grid.height, callback);
  }
  
  function _SW(e){    
    var m = fbf.Grid.cache[g.SW].neighbours;
    
    fbf.Grid.cache[g.SE].updateNeighbours({'SW' : m.SE});    
    fbf.Grid.cache[g.S].updateNeighbours({'S' : m.SE, 'SW' : m.S});    
    fbf.Grid.cache[g.W].updateNeighbours({'SW' : m.W, 'W' : m.NW});    
    fbf.Grid.cache[g.NW].updateNeighbours({'SW' : m.NW});    
    
    T=T+fbf.Grid.height;
    L=L-fbf.Grid.width;   

    _draw(m.SE, L+(fbf.Grid.width*2), T+(fbf.Grid.height*2));
    _draw(m.S, L+fbf.Grid.width, T+(fbf.Grid.height*2));
    _draw(m.SW, L, T+(fbf.Grid.height*2));
    _draw(m.W, L, T+fbf.Grid.height);
    _draw(m.NW, L, T);
    
    fbf.Grid.cache[m.SE].setNeighbours({'N' : g.S, 'NE' : g.SE, 'W' : m.S, 'NW' : g.SW});      
    fbf.Grid.cache[m.S].setNeighbours({'N' : g.SW, 'NE' : g.S, 'E' : m.SE, 'W' : m.SW, 'NW' : m.W});      
    fbf.Grid.cache[m.SW].setNeighbours({'N' : m.W, 'NE' : g.SW, 'E' : m.S});      
    fbf.Grid.cache[m.W].setNeighbours({'N' : m.NW, 'NE' : g.W, 'E' : g.SW, 'SE' : m.S, 'S' : m.SW});    
    fbf.Grid.cache[m.NW].setNeighbours({'NE' : g.NW, 'E' : g.W, 'SE' : g.SW, 'S' : m.W});
    
    var callback = function(){ 
 
     _erase(g.NW);
     _erase(g.N);     
     _erase(g.NE);
     _erase(g.E);
     _erase(g.SE);
     
     g.NE = g.C; g.E = g.S; g.N = g.W;
     g.C = g.SW; g.NW = m.NW; g.W = m.W;
     g.SW = m.SW; g.S = m.S; g.SE = m.SE;               
     
     _mouseenter('SW');
          
    };
    
    _setCenter(g.SW);    
    _tween(X+fbf.Grid.width, Y-fbf.Grid.height, callback);    
  }
  
  function _NW(e){    
    var m = fbf.Grid.cache[g.NW].neighbours;
    
    fbf.Grid.cache[g.N].updateNeighbours({'N' : m.NE, 'NW' : m.N});    
    fbf.Grid.cache[g.NE].updateNeighbours({'NW' : m.NE});    
    fbf.Grid.cache[g.SW].updateNeighbours({'NW' : m.SW});    
    fbf.Grid.cache[g.W].updateNeighbours({'W' : m.SW, 'NW' : m.W});    
    
    T=T-fbf.Grid.height;
    L=L-fbf.Grid.width;   
    
    _draw(m.N, L+fbf.Grid.width, T);
    _draw(m.NE, L+(fbf.Grid.width*2), T);
    _draw(m.SW, L, T+(fbf.Grid.height*2));
    _draw(m.W, L, T+fbf.Grid.height);
    _draw(m.NW, L, T);

    fbf.Grid.cache[m.N].setNeighbours({'E' : m.NE, 'SE' : g.N, 'S' : g.NW, 'SW' : m.W, 'W' : m.NW});        
    fbf.Grid.cache[m.NE].setNeighbours({'SE' : g.NE, 'S' : g.N, 'SW' : g.NW, 'W' : m.N});        
    fbf.Grid.cache[m.SW].setNeighbours({'N' : m.W, 'NE' : g.NW, 'E' : g.W, 'SE' : g.SW});        
    fbf.Grid.cache[m.W].setNeighbours({'N' : m.NW, 'NE' : m.N, 'E' : g.NW, 'SE' : g.W, 'S' : m.SW});      
    fbf.Grid.cache[m.NW].setNeighbours({'E' : m.N, 'SE' : g.NW, 'S' : m.W});

    var callback = function(){ 

     _erase(g.SE);
     _erase(g.S);     
     _erase(g.E);
     _erase(g.SW);
     _erase(g.NE);
       
     g.SE = g.C; g.E = g.N; g.S = g.W;
     g.C = g.NW; g.NW = m.NW; g.W = m.W;
     g.SW = m.SW; g.N = m.N; g.NE = m.NE;   
     
     _mouseenter('NW');
            
    };
    
    _setCenter(g.NW);    
    _tween(X+fbf.Grid.width, Y+fbf.Grid.height, callback);    
  }
  
  function _setCenter(id){
    cm = $('m_'+id);
    ct = cm.down('div.title');
  }
  
  function _tween(x, y, callback){
    
    fbf.Grid.elements.grid.morph('top:'+y+'px; left:'+x+'px;', {
      duration: 0.5,
      after : function(){
        try {
          callback();
        }catch(e){}
        $('m_'+g.C).addClassName('center-module');
        X = x;
        Y = y;
        fbf.Grid.locked = false;
      },
      before : function(){
        $('m_'+g.C).removeClassName('center-module');                
        fbf.Grid.locked = true;
        
        if(tpos){
          tpos.style.marginTop = '0';
          tpos=null;
          // tfx = new S2.FX.Morph(tpos, {
          //   'style' : 'margin-top: 0',
          //   after : function(){
          //     tpos=null;
          //   }
          // });
          // tfx.play();
        }
        
      }
    });
  }
  
  function _mouseenter(pos, event){   
    var title = $('m_'+g[pos]).down('div.title');     
    $('m_'+g[pos]).addClassName('module-hover');
    if(title){
      tpos =title;
      tpos.style.marginTop = -title.offsetHeight+'px';
      // tfx = new S2.FX.Morph(title, {
      //   'style' : 'margin-top: -'+title.offsetHeight+'px'
      // });
      // tfx.play();
    }    
  }
  
  function _mouseleave(pos, event){  
    $('m_'+g[pos]).removeClassName('module-hover');           
    if(tpos){
      if(event.relatedTarget && event.relatedTarget.childOf(tpos)) return; 
        tpos.style.marginTop = 0;
        tpos = null;
      // tfx = new S2.FX.Morph(t[pos], {
      //   'style' : 'margin-top: 0',
      //   after : function(){
      //     t[pos]=null;
      //   }
      // });
      // tfx.play();
    }
  }
  
  // function addHighlight(pos){
  //   $('m_'+g[pos]).addClassName('module-hover');
  //   var title = $('m_'+g[pos]).down('div.title');     
  //   if(title){
  //     tpos = title;
  //     tpos.style.marginTop = -title.offsetHeight+'px';
  //   }
  // }
  
  function _load(e){    
    if(!fbf.Grid.locked){
      e.stop();
      var module = fbf.Grid.cache[g.C];            
      var url = module.url.startsWith('/') ? module.url : (module.url.match(/tp:\/\/[^\/]+(.+)/) || [,''])[1];      
      pageHistory.fire(url);
    }
  }
  
  function _navigate(n, e){
    if(n == 'C'){
      _load(e);
    }else{
      if(!fbf.Grid.locked && Ajax.activeRequestCount == 0){
        e.stop();      
        history.fire(g[n]);
        if(!Object.isUndefined(pageTracker)){
          var url = '/m/'+fbf.Grid.cache[g[n]].slug;
          pageTracker._trackPageview(url);
        }
      }
    }
  }
  
  function _pageHistory(e){    
    var url = pageHistory.state;  
          
    if(url && url!= '/'){      
      if(url.indexOf('casestudy')!=-1){
        modal.overlay.options.height = 509;
        modal.overlay.options.width = 974;
      }else if(url.indexOf('slide_show')!=-1){
        modal.overlay.options.height = 513;
        modal.overlay.options.width = 832;
      }else if(url.indexOf('video')!=-1){
        modal.overlay.options.height = 493;
        modal.overlay.options.width = 832;
      }else{
        modal.overlay.options.height = 503;
        modal.overlay.options.width = 974;
      }
      if(modal.overlay.element.visible()){
        modal.reload(url);
        historyClose=true;
      }else{
        modal.load(url);
      }
    }else{
      modal.hide();
    }    
  }
  
  function _history(e){  
    var state = history.state;    
    
    if(startPage && g.C == state){
      return;
    }
    
    var m = $H(g).find(function(gg){
      return gg[1] == state;
    }); 
        
    if(m){
      switch(m[0]){
        case "N": _N(); break;
        case "NE": _NE(); break;
        case "E": _E(); break;
        case "SE": _SE(); break;
        case "S": _S(); break;
        case "SW": _SW(); break;
        case "W": _W(); break;
        case "NW": _NW(); break;
      }
    }
  }
  
  function _setCss(d){    
    var _style;
    var maxH = d.height-110;
    var maxW = d.width-40;
    var maxF = 26;
    
    var moduleH = Math.min(Math.floor(maxH/3), 310);
    var moduleW = Math.min(Math.floor(maxW/3), 410);
    
    var moduleHW = Math.floor((moduleH/3)*4);
    var moduleWH = Math.floor((moduleW/4)*3);
    
    if(maxW<maxH){
      fbf.Grid.height = moduleWH;
      fbf.Grid.width = moduleW;
    }else{
      fbf.Grid.height = moduleH;
      fbf.Grid.width = moduleHW;
    }    
    
    _style = fbf.Grid.elements.start.style;
    _style.height = (fbf.Grid.height*3)+'px';
    _style.width = (fbf.Grid.width*3)+'px';
    
    _style = fbf.Grid.elements.content.style;
    _style.height = (fbf.Grid.height*3)+'px';
    _style.marginLeft = -((fbf.Grid.width*3)/2)+'px';
    _style.width = (fbf.Grid.width*3)+'px';
        
    fbf.Grid.elements.controls.style.width = (fbf.Grid.width*3)+'px';
    
    var scale = (fbf.Grid.width/410)*100;    
    fbf.Grid.fontSize = Math.max(Math.ceil((maxF/100)*scale), 12);
    
    var st=document.styleSheets[document.styleSheets.length-1];    
    (st.cssRules ? st.cssRules[0] : st.rules[0]).style.width=(fbf.Grid.width-22)+'px';
    (st.cssRules ? st.cssRules[0] : st.rules[0]).style.height=(fbf.Grid.height-22)+'px';
    (st.cssRules ? st.cssRules[1] : st.rules[1]).style.fontSize=(fbf.Grid.fontSize)+'px';
    (st.cssRules ? st.cssRules[2] : st.rules[2]).style.width=(fbf.Grid.width-22)+'px';
    (st.cssRules ? st.cssRules[2] : st.rules[2]).style.height=(fbf.Grid.height-22)+'px';
    (st.cssRules ? st.cssRules[3] : st.rules[3]).style.width=(fbf.Grid.width-22)+'px';
    (st.cssRules ? st.cssRules[3] : st.rules[3]).style.height=(fbf.Grid.height-22)+'px';
    
  }
  
  function _setProxy(){
    fbf.Grid.elements.proxy[0][0].setStyle({
      left : fbf.Grid.width*0+'px',
      top : fbf.Grid.height*0+'px'
    });

    fbf.Grid.elements.proxy[0][1].setStyle({
      left : fbf.Grid.width*1+'px',
      top : fbf.Grid.height*0+'px'
    });
  
    fbf.Grid.elements.proxy[0][2].setStyle({
      left : fbf.Grid.width*2+'px',
      top : fbf.Grid.height*0+'px'
    });
    
    fbf.Grid.elements.proxy[1][0].setStyle({
      left : fbf.Grid.width*0+'px',
      top : fbf.Grid.height*1+'px'
    });

    fbf.Grid.elements.proxy[1][1].setStyle({
      left : fbf.Grid.width*1+'px',
      top : fbf.Grid.height*1+'px'
    });
  
    fbf.Grid.elements.proxy[1][2].setStyle({
      left : fbf.Grid.width*2+'px',
      top : fbf.Grid.height*1+'px'
    });
    
    fbf.Grid.elements.proxy[2][0].setStyle({
      left : fbf.Grid.width*0+'px',
      top : fbf.Grid.height*2+'px'
    });

    fbf.Grid.elements.proxy[2][1].setStyle({
      left : fbf.Grid.width*1+'px',
      top : fbf.Grid.height*2+'px'
    });
  
    fbf.Grid.elements.proxy[2][2].setStyle({
      left : fbf.Grid.width*2+'px',
      top : fbf.Grid.height*2+'px'
    });
    
  }
  
  function initialize(e){       
    var _style;
    fbf.Grid.elements = {
      'content' : $('content'),
      'grid' : $('grid'),
      'start' : $('start-page'),
      'controls' : $('navigation-inner'),
      'site' : $('site'),
      proxy : [[],[],[]]
    };
    
    var d = document.viewport.getDimensions(); 
    _setCss(d);
    
    fbf.Grid.elements.site.setStyle({
      opacity: 0,
      visibility : 'visible'
    }).morph('opacity:1');
    
    var h = d.height/2;
    var w = d.width/2;
    var x = fbf.Grid.width/2;
    var y = fbf.Grid.height/2;
            
    var _pos = [
      ['NW', 'N', 'NE'],
      ['W','C','E'],
      ['SW','S','SE']      
    ];      
    
    Event.observe(window, 'resize', _onResize);
      
    fbf.Grid.elements.grid.select('div.module').reverse().each(function(module, i){      
         var position = module.positionedOffset();
         _style = module.style;
         _style.float = 'none';
         _style.left = (position.left-5)+'px';
         _style.position = 'absolute';
         _style.top = (position.top-5)+'px';
         
         var token = module.identify().split('-');
         var link = module.down('.full-content');
         
         var m = new fbf.Grid.Module(token[1]); 
         if(link){
           m.url = link.href;
         }
         m.slug = token[0];
         m.setContent(module.innerHTML);      
         module.id = 'm_'+m.id;                 
         var x = Math.ceil((position.left-5)/fbf.Grid.width);
         var y = Math.ceil((position.top-5)/fbf.Grid.height);  
                            
         _g[x][y] = m.id;
         
         fbf.Grid.elements.proxy[x][y] = new Element('div', {className : 'proxy', id: 'proxy_'+x+'_'+y}).setStyle({
           top: (position.top-5)+'px',
           left: (position.left-5)+'px',
           zIndex: 1000,
           background : 'url(/img/site/magic.png) repeat 0 0'
         });
         fbf.Grid.elements.content.insert(fbf.Grid.elements.proxy[x][y]);
         fbf.Grid.elements.proxy[x][y].observe('mouseenter', _mouseenter.curry(_pos[x][y]));
         fbf.Grid.elements.proxy[x][y].observe('mouseleave', _mouseleave.curry(_pos[x][y]));
         fbf.Grid.elements.proxy[x][y].observe('click', _navigate.curry(_pos[x][y]));
         
       });
       
       //fbf.Grid.elements.proxy[1][1].style.border='4px solid #fff';
       
       _setProxy();
           
       g.N = _g[1][0];
       g.NE = _g[2][0];
       g.E = _g[2][1];
       g.SE = _g[2][2];
       g.S = _g[1][2];
       g.SW = _g[0][2];
       g.W = _g[0][1];
       g.NW = _g[0][0];
       g.C = _g[1][1];
       
       _setCenter(g.C);
           
       fbf.Grid.cache[g.N].setNeighbours({'E' : g.NE, 'SE' : g.E, 'S' : g.C, 'SW' : g.W, 'W' : g.NW});
       fbf.Grid.cache[g.NE].setNeighbours({'S' : g.E, 'SW' : g.C, 'W' : g.N});
       fbf.Grid.cache[g.E].setNeighbours({'N' : g.NE, 'S' : g.SE, 'SW' : g.S, 'W' : g.C, 'NW' : g.N});    
       fbf.Grid.cache[g.SE].setNeighbours({'N' : g.E, 'W' : g.S, 'NW' : g.C});    
       fbf.Grid.cache[g.S].setNeighbours({'N' : g.C, 'NE' : g.E, 'E' : g.SE, 'W' : g.SW, 'NW' : g.W});    
       fbf.Grid.cache[g.SW].setNeighbours({'N' : g.W, 'NE' : g.C, 'E' : g.S});    
       fbf.Grid.cache[g.W].setNeighbours({'N' : g.NW, 'NE' : g.N, 'E' : g.C, 'SE' : g.S, 'S' : g.SW});    
       fbf.Grid.cache[g.NW].setNeighbours({'E' : g.N, 'SE' : g.C, 'S' : g.W});    
       fbf.Grid.cache[g.C].setNeighbours({'N' : g.N, 'NE' : g.NE, 'E' : g.E, 'SE' : g.SE, 'S' : g.S, 'SW' : g.SW, 'W' : g.W, 'NW' : g.NW});   
       
       var _t = 90;
       var _l = (d.width/2)-((fbf.Grid.width*3)/2);

       // N = new dd.util.Region(_t, _l+(fbf.Grid.width*2), _t+fbf.Grid.height, _l+fbf.Grid.width);
       // NE = new dd.util.Region(_t, _l+(fbf.Grid.width*3), _t+fbf.Grid.height, _l+(fbf.Grid.width*2));
       // E = new dd.util.Region(_t+fbf.Grid.height, _l+(fbf.Grid.width*3), _t+(fbf.Grid.height*2), _l+(fbf.Grid.width*2));
       // SE = new dd.util.Region(_t+(fbf.Grid.height*2), _l+(fbf.Grid.width*3), _t+(fbf.Grid.height*3), _l+(fbf.Grid.width*2));
       // S = new dd.util.Region(_t+(fbf.Grid.height*2), _l+(fbf.Grid.width*2), _t+(fbf.Grid.height*3), _l+fbf.Grid.width);
       // SW = new dd.util.Region(_t+(fbf.Grid.height*2), _l+fbf.Grid.width, _t+(fbf.Grid.height*3), _l);
       // W = new dd.util.Region(_t+fbf.Grid.height, _l+fbf.Grid.width, _t+(fbf.Grid.height*2), _l);
       // NW = new dd.util.Region(_t, _l+fbf.Grid.width, _t+fbf.Grid.height, _l);
       // C = new dd.util.Region(_t+fbf.Grid.height, _l+(fbf.Grid.width*2), _t+(fbf.Grid.height*2), _l+fbf.Grid.width);
       // 
       // N.observe('click', _navigate.curry('N'));   
       // NE.observe('click', _navigate.curry('NE'));
       // E.observe('click', _navigate.curry('E'));
       // SE.observe('click', _navigate.curry('SE'));
       // S.observe('click', _navigate.curry('S'));
       // SW.observe('click', _navigate.curry('SW'));
       // W.observe('click', _navigate.curry('W'));
       // NW.observe('click', _navigate.curry('NW'));
       // 
       // C.observe('click', _load);  
      
       history = new dd.util.History.Module('m', g.C);
       history.observe('history:change', _history);  
       
       var url = (window.location.href.match(/tp:\/\/[^\/]+(.+)/) || [,''])[1].split('#')[0];
       pageHistory = new dd.util.History.Module('p', url);   
       
       //alert(url);
       
       pageHistory.observe('history:change', _pageHistory);
       
       //anchorHistory = new dd.util.History.Module('a', '');       
       
    
      //overlay_history = new dd.util.History.Module('p');
      //overlay_history.observe('history:change', _overlay_history);
    
    modal = new dd.ui.Overlay.AjaxModal({
      'height' : 495,
      'width' : 974,
      onClose : function(){
        if(historyClose){
          pageHistory.fire('/');
          historyClose = false;
        }else{
          var original_url = document.location.href;
          window.history.back();
          if(original_url == document.location.href){
            pageHistory.fire('/');
            historyClose = false;
          }
        }
      },
      show : function(){
        this.overlay.resize();                
        if(xoverlay && xoverlay.visible()){
          this.mask.element.show();
          this.overlay.element.show();  
          $('overlay-mask').hide();        
          xoverlay.hide();
        }else{
          var fx = new S2.FX.Parallel([
            new S2.FX.Morph(this.overlay.element, {
              style : 'opacity: 1; left: #{left}; top: #{top}; width: #{width}; height: #{height}'.interpolate(this.overlay.style)
            }),
            new S2.FX.Morph(this.mask.element, {style : 'opacity:'+this.mask.options.opacity})
          ], {
            before : function(){
              fbf.Grid.locked = true;
              this.overlay.resize();
              this.mask.element.setStyle({'opacity' : 0}).show();
              this.overlay.element.setStyle({
                'opacity' : 0, 
                'width' : fbf.Grid.width+'px', 
                'height' : fbf.Grid.height+'px',
                'left' : w-x+'px',
                'top' : h-y+'px'
              }).show();
            }.bind(this),
            'position' : 'end'
          });
          fx.play();
        }
      },
      hide : function(){
        var cfx = new S2.FX.Morph(this.overlay.content, {
          'style' : 'opacity:0;',
          'position' : 'end'
        });
        cfx.play();
        
        var fx = new S2.FX.Parallel([
          new S2.FX.Morph(this.mask.element, {style : 'opacity:0'}),
          new S2.FX.Morph(this.overlay.element, {
            style : 'opacity: 0; left: #{left}; top: #{top}; width: #{width}; height: #{height}'.interpolate({
              'width' : fbf.Grid.width+'px', 
              'height' : fbf.Grid.height+'px',
              'left' : w-x+'px',
              'top' : h-y+'px'
            })            
          })
        ], {
          after : function(){
            this.mask.element.hide();
            this.overlay.element.hide();
            fbf.Grid.locked = false;
            
            this.overlay.content.stopObserving();
            this.overlay.content.descendants().invoke('stopObserving');
            this.overlay.content.update('');
            
          }.bind(this),
          'position' : 'end'
        });
        fx.play();
      }
    });
    
    
    
    fbf.Grid.elements.controls.observe('click', function(e){
      var element;
      if(element=e.findElement('a.modal')){
        e.stop();
        pageHistory.fire(element.pathname);
      }
    });
    
    fbf.Twitter.initialize('twitter-feed', 'FbFdigital', {
      count : 20,
      link: '<a href="#{url}">#{url}</a>',
      template: '<li class="tweet-#{count}"><div class="tweet"><p class="text">#{text}</p><p class="meta">#{date} from #{source}</p></div><div class="retweet"><a href="http://twitter.com/home?status=#{encoded_text}">retweet</a></div></li>'
    });
    
    
    xoverlay = $('overlay');
    if(xoverlay){
      fbf.Grid.locked = true;
      xoverlay.down('a.closeButton').observe('click', function(e){
        e.stop();
        
        var overlayMask = $('overlay-mask');
        var overlayContent = $('overlay-content');
        
        var cfx = new S2.FX.Morph(overlayContent, {
          'style' : 'opacity:0;',
          'position' : 'end'
        });
        cfx.play();
        
        var fx = new S2.FX.Parallel([
          new S2.FX.Morph(overlayMask, {style : 'opacity:0'}),
          new S2.FX.Morph(xoverlay, {
            style : 'opacity: 0; left: #{left}; top: #{top}; width: #{width}; height: #{height}'.interpolate({
              'width' : fbf.Grid.width+'px', 
              'height' : fbf.Grid.height+'px',
              'left' : w-x+'px',
              'top' : h-y+'px'
            })            
          })
        ], {
          after : function(){
            overlayMask.hide();
            xoverlay.hide();
            fbf.Grid.locked = false;            
            xoverlay.stopObserving();
            xoverlay.descendants().invoke('stopObserving');
            xoverlay.update('');            
            fbf.Grid.locked = false;
            
            pageHistory.fire(null);
            
          }.bind(this),
          'position' : 'end'
        });
        fx.play();
        
        
      });
    }
    
    // var anchor;
    // if(anchor = $(top.location.hash.substr(1))){
    //   console.log(anchor);
    // }
    
  }

  //Event.observe(window, 'load', _initialize);
  document.observe('dom:loaded', initialize);
  
  function get(id){
    return fbf.Grid.cache[id];
  }
  
  return {
    get : get,
    load : function(url){
      modal.load(url);
    },
    update : function(url){
      modal.reload(url);
    },
    debug : function(){
      console.dir(g);
    }
  }  
}();

fbf.Grid.Module = Class.create({
  initialize : function(id){
    this.id = fbf.Grid.count++;
    this._id = id;
    this.background = Math.floor(Math.random()*16777215).toString(16);
    this.content = '<div style="background:#'+this.background+';">'+this.id+'</div>';
    this.neighbours = {};
    this.controller = 'article';
    this.pending = $A(['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']);
    fbf.Grid.cache[this.id] = this;
  },
  setNeighbours : function(n){
    if(n){this.updateNeighbours(n);}
    if(this.pending.length>0){this.preload();};  
  },
  updateNeighbours : function(n){
    this.neighbours = Object.extend(this.neighbours, n);
    if(this.pending.length<=8){
      var k = Object.keys(n).flatten();
      this.pending = this.pending.reject(function(r){
        return k.indexOf(r)!=-1
      });
    }
  },
  preload : function(){  
    var url = fbf.Grid.url+'?slug='+this.slug+'&limit='+this.pending.length;
    new Ajax.Request(url, {
      'parameters' : {
        'test' : window.test ? 1 : 0
      },
      'method' : 'get',
      'onSuccess' : this.onSuccess.bind(this)
    });
  },
  preloadNeighbour : function(p){
    if(!this.neighbours[p]){
      this.onSuccess(p);
    }
  },
  render : function(){
    return this.content;
  },
  onSuccess : function(t){    
    try{
      var j = t.responseText.evalJSON();
      this.pending.each(function(_c, i){
        var _j = j[i];     
        if(_j.img){
          fbf.Preload(_j.img);
        }       
        var id = _j.id;   
        var m = new fbf.Grid.Module(id);
        m.content = _j.html;
        m.slug = _j.slug;
        m.url = _j.url;
        this.neighbours[_c] = m.id;
        this.pending = $A();
      }, this);
    }catch(e){
      fbf.Grid.Errors.log(fbf.Grid.url+this.slug+'/limit:'+this.pending.length+'.json', t.responseText);
    }
  },
  remove : function(){
    this.element.remove();
  },
  setContent : function(html){
    this.content = html;
  }
});

function get(id){
  return fbf.Grid.Base.get(id);
}

fbf.Grid.Errors = function(){
  var element, modal;
  
  function log(id, text){
    var d = new Element('div', {className : 'errors'}).update(text);  
    d.insert({top: new Element('div', {className: 'title'}).update(id)})
    element.insert(d);
    modal.show();  
    var t = d.positionedOffset();
    element.scrollTop = t[1];
  }
  
  function initialize(){
    modal = new dd.ui.Overlay.Modal({
      'height' : 600,
      'width' : 800
    });
    element = new Element('div', {id: 'errors'}).setStyle({
      'overflow' : 'scroll',
      'height' : '600px',
      'width' : '800px',
      'background' : '#fff',
      'fontSize' : '12px'
    });
    modal.update(element);
  }
  
  document.observe('dom:loaded', initialize);
  
  return {
    log : log
  }
}();

fbf.CaseStudy = Class.create({
  initialize : function(tabset, linkset){    
    this.tabset = $(tabset);
    this.tabs = this.tabset.select('div.tab').invoke('hide');
    this.i = 0;
    
    if(this.tabs.length>0){
      this.tabs[0].show();
    }
    
    this.linkset = $(linkset);
    this.links = this.linkset.select('a');
    
    this.links.each(function(element, i){           
      $E(element, 'click', this.onClick.bindAsEventListener(this, i));       
      $E(element, 'mouseenter', this.onMouseover.bindAsEventListener(this, element.down('span')));
      $E(element, 'mouseleave', this.onMouseout.bindAsEventListener(this, element.down('span')));     
    }, this);
  },
  onClick : function(e, i){
    e.stop();
    this.tabs[this.i].hide();
    this.tabs[i].show();
    this.i=i;
  },
  _lock : function(eventName){
    this[eventName] = true;
  },
  _unlock : function(eventName){
    this[eventName] = false;
  },
  onMouseover : function(e, element){
    if(element && !this.mouseEnterlocked){
      element.morph('top : 0', {
        before : this.mouseEnterLock,
        after : this.mouseEnterUnlock
      });
    }
  },
  onMouseout : function(e, element){
    if(element && !this.mouseLeaveLocked){
      element.morph('top : 100%', {
        before : this.mouseLeaveLock,
        after : this.mouseLeaveUnlock
      });
    }
  }
});

fbf.Scrollbar = Class.create({
  initialize : function(wrapper, element){
    this.wrapper = $(wrapper);
    this.element = $(element);    
    
    this.scrollbar = new Element('div', {
      className: 'scrollbar'
    });
    
    this.handle = new Element('div', {
      className: 'scrollbar-handle'
    }).update('<span class="t"></span><span class="b"></span>');
    
    this.scrollbarWrapper = new Element('div', {
      className : 'scrollbar-wrapper'
    });
    
    this.wrapper.insert(this.scrollbarWrapper.insert(this.scrollbar.insert(this.handle)));
    
    this.slider = new Control.Slider(this.handle, this.scrollbar, {
      axis : 'vertical',
      onChange : this.onChange.bind(this),
      onSlide : this.onChange.bind(this)
    });
    
    
    this.onMouseWheelListener = this.onMouseWheel.bindAsEventListener(this);
    this.element.observe('mouse:wheel', this.onMouseWheelListener);
    
    this.up = new Element('a', {href: '#', className: 'up'}).update('Up');
    this.down = new Element('a', {href: '#', className: 'down'}).update('Down');
    
    this.scrollbarWrapper.insert(this.up);
    this.scrollbarWrapper.insert(this.down);
    
    this.up.observe('click', this.scrollUp.bindAsEventListener(this));
    this.down.observe('click', this.scrollDown.bindAsEventListener(this));
    
    this.handle.observe('mouseenter', this.onMouseEnter.bindAsEventListener(this));
    this.handle.observe('mouseleave', this.onMouseLeave.bindAsEventListener(this));
    
    this.render();
    
    
  },
  onMouseEnter : function(){
    this.handle.addClassName('scrollbar-handle-hover');
  },
  onMouseLeave : function(){
    this.handle.removeClassName('scrollbar-handle-hover');
  },
  onMouseWheel : function(e){
    this.slider.setValueBy(-(e.memo.delta / 20));
    e.stop();
    return false;
  },
  onChange : function(value){
    this.element.scrollTop = Math.round(value/this.slider.maximum * (this.element.scrollHeight - this.element.offsetHeight));  
  },
  render : function(){
    
    var height = this.element.getHeight();
    var scrollHeight = this.element.scrollHeight;
    this.scrollAmount = height/scrollHeight;
                
    this.scrollbarWrapper[(scrollHeight>height) ? 'show' : 'hide']();    
    
    this.slider.trackLength = this.slider.maximumOffset() - this.slider.minimumOffset();    
    var h = Math.max((this.scrollbar.offsetHeight * (height / scrollHeight)), 100);    
    if(!isNaN(h)){  
      this.handle.style.height = h+'px';
      this.slider.handleLength = this.handle.style.height.replace(/px/,'');  
    }
  },
  scrollDown : function(e){
    this.slider.setValueBy(this.scrollAmount);
    e.stop();
    
  },
  scrollUp : function(e){
    this.slider.setValueBy(-this.scrollAmount);
    e.stop();
  }
});

fbf.SubmitComment = function(e){
  e.stop();
  $('CommentSubmit').disable();
  Form.request(this, {
    onSuccess : function(t){
      var response = t.responseText.evalJSON();      
      if(response.success){
        var html = '<p>'+response.success+'</p>';
        $('CommentName').clear();
        $('CommentEmail').clear();
        $('CommentUrl').clear();
        $('CommentComment').clear();
        $('ajax-flash-message').className = 'success';
      }else{
        var html = $H(response.error).inject('<h4>Please correct the following errors:</h4>', function(h, item, i){
          return h+'<p>'+item.value+'</p>';
        });
        $('ajax-flash-message').className = 'error';
      }
      $('ajax-flash-message').update(html).show();
      $('CommentSubmit').enable();
    }
  });
}

fbf.ModalLinks = Class.create({
  initialize : function(element){
    this.element = $(element);
    this.element.observe('click', this.onClick.bindAsEventListener(this));
  },
  onClick : function(e){
    var element = e.findElement('a.modal');
    if(element){
      e.stop();
      
      pageHistory.fire(element.pathname);
      
      //console.log(element.pathname);
      
      //pageHistory.fire(element.pathname);
      // if($('overlay') && $('overlay').visible()){
      //   fbf.Grid.Base.load(element.href);
      // }else{
      //   fbf.Grid.Base.update(element.href);
      // }
    }
  }
});

fbf.Twitter = function(){
  var element, options, username, callback, loaded;
  var linkRegex = /(ftp|http|https|file):\/\/[\S]+(\b|$)/;
  var mentionRegex = /(^|[^a-z0-9_])@([a-z0-9_]+)/;
  var url = "http://twitter.com/status/user_timeline/#{username}.json?count=#{count}&callback=?";
  
  function linkUrl(url){
    return options.link.evaluate({url:url[0]});
  }
  
  function mentionUrl(mention){
    return mention[1]+options.mention.evaluate({username:mention[2]});    
  }
  
  function relDate(date){    
    var date = Date.parse(date.replace(/( \+)/," UTC$1"));    
    var diff = (((new Date()).getTime() - date) / 1000);
    var day_diff = Math.floor(diff / 86400)

  	if ( isNaN(day_diff) || day_diff < 0 || day_diff >= 31 ) return;

  	return day_diff == 0 && (
  			diff < 60 && "just now" ||
  			diff < 120 && "1 minute ago" ||
  			diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" ||
  			diff < 7200 && "1 hour ago" ||
  			diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") ||
  		day_diff == 1 && "Yesterday" ||
  		day_diff + " days ago";
  }
  
  
  function getTweet(html, tweet, i){
    tweet.date= new Date(tweet.created_at).strftime(options.date);      
    tweet.count = i;
    tweet.encoded_text = escape(tweet.text);
    tweet.raw_text = tweet.text;
    tweet.rel_date = relDate(tweet.created_at);
    tweet.text = tweet.text.gsub(linkRegex, linkUrl).gsub(mentionRegex, mentionUrl);
    return html+options.template.evaluate(tweet);
  }
  
  function updateTweets(tweets){
    element.update($A(tweets).inject('', getTweet));
    loaded = true;
    if(callback){
      callback(element.innerHTML);
    }
  }
  
  return {
    initialize : function(id, username, _options){
      element = $(id);
      options = Object.extend({
        'count': 10,
        'link' : '<a href="#{url}" target="_blank">#{url}</a>',
        'mention' : '<a href="http://twitter.com/#{username}" target="_blank">@#{username}</a>',
        'template' : '<p>#{text}</p>',
        'date' : '%i:%M %p %b %d'
      }, _options||{});
      options.link = new Template(options.link);      
      options.mention = new Template(options.mention);            
      options.template = new Template(options.template);
      getJSON(url.interpolate({username : username, count: options.count}), updateTweets);
    },
    onload : function(func){
      callback = func;
      if(loaded){
        callback(element.innerHTML);
      }
    }
  }
}();











function thumbRollovers(rolloversContainer, rollovers) {
  rollovers.each(function(el, idx) {   
    el.setStyle({
      overflow : 'hidden',
      position: 'relative',
      textIndent : '-9999px'
    });
    

    
    var canAnimate = true;
    
    el.observe('mouseenter', function(e) {
      overlay.morph('top : 0', {
        before : function() { overlay.show(); }
      }); 
    });
    
    el.observe('mouseleave', function(e) {
      offsetHeight = el.getStyle('height');
      
      overlay.morph('top : '+offsetHeight, {
        after : function() { overlay.hide() }
      }); 
    });    

    el.insert(overlay); 
  });
}