HW = function() {

  var $E  = YAHOO.util.Event;
  var $D  = YAHOO.util.Dom;
  var $A  = YAHOO.util.Anim;
  var $   = YAHOO.util.Dom.get;

  var Tangram = function(el) {
  };


  var viewerTemplate;

  // Our custom drag and drop implementation, extending YAHOO.util.DD
  // to implement Keep-in-window and always-on-top (for active el)
  var DD = function(id, sGroup, config) {
    DD.superclass.constructor.apply(this, arguments);
  };

  YAHOO.extend(DD, YAHOO.util.DD, {
    startDrag: function(x, y) {
      $D.setStyle(HW.els, 'zIndex', '0');
      $D.setStyle($D.getElementsByClassName('viewer', 'div'), 'zIndex', '0');
      $D.setStyle(this.getEl(), 'zIndex', '1');
    },
    onDrag: function(e) {
    },
    endDrag: function(e) {
      var el = this.getEl();
      if(el.id) {
        var xy = $D.getXY(el);
        if(xy[0] < 0) {
          var anx = new $A(el, 
            {left: {to: 10}}, .25, YAHOO.util.Easing.backOut);
          anx.animate();
          xy[0] = 10;
        }
        if (xy[1] < 0) {
          var any = new $A(el, 
            {top: {to: 10}}, .25, YAHOO.util.Easing.backOut);
          any.animate();
          xy[1] = 10;
        }
        COOKIE.create(el.id, xy[0]+','+xy[1]);
      }
    }
  });

  var scrollers = {};
  var state = {};
  var els = {};
  var dd = {};
  var resizers = {};
  var resized = {};
  var viewers = [];
  var defaults = {
    'collection1': [401,376],
    'collection2': [560,118],
    'collection3': [708,260],
    'tangram-intro': [320,260],
    'viewer': [130,166],
    'news': [240,66],
    'projects': [230,166],
    'clothes':   [580,250],
    'shoes':     [590,260],
    'stockings': [600,270],
    'contact': [120,250]
  };

  /**
  * Create/Read/Delete Cookies - based on code from PPK
  * http://www.quirksmode.org/js/cookies.html
  */
  var COOKIE = function() {

    return {

      /*
      * @param  {String}  name   The cookie name
      * @param  {String}  value  The value to store
      * @param  {Integer} days   The number of days to store the value
      */
      create: function(name, value, days) {
        if (days) {
          var date = new Date();
          date.setTime(date.getTime()+(days*24*60*60*1000));
          var expires = "; expires="+date.toGMTString();
        }
        else var expires = "";
        document.cookie = name+"="+value+expires+"; path=/";
      },

      /*
      * @param  {String}  name   The cookie name
      */
      read: function(name) {
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for(var i=0;i < ca.length;i++) {
          var c = ca[i];
          while (c.charAt(0)==' ') c = c.substring(1,c.length);
          if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
        }
        return null;
      },

      /*
      * @param  {String}  name   The cookie name
      */
      erase: function(name) {
        COOKIE.create(name,"",-1);
      }

    };

  }(); // end COOKIE

  var getNext = function(detailId) {
    if(!detailId) { return; }
    var src = 'model' + detailId.slice(6);
    var className = $(src).parentNode.className.replace(/ first/, '');
    // var peers = $D.getElementsByClassName(className, 'li', $(src).parentNode.parentNode);
    var peers = $(src).parentNode.parentNode.getElementsByTagName('li');
    var next = -1;
    var a;
    for (var i = 0; i < peers.length; i++) {
      a = $D.getFirstChild(peers[i]);
      if(a && a.id == src && peers[i+1]) {
        next = $D.getFirstChild(peers[i+1]);
        break;
      }
    }
    if(next < 0) {
      return null;
    } else {
      return next;
    }
  };

  var getPrev = function(detailId) {
    if(!detailId) { return; }
    var src = 'model' + detailId.slice(6);
    var className = $(src).parentNode.className.replace(/ first/, '');
    // var peers = $D.getElementsByClassName(className, 'li', $(src).parentNode.parentNode);
    var peers = $(src).parentNode.parentNode.getElementsByTagName('li');
    var next = -1;
    var a;
    for (var i = 0; i < peers.length; i++) {
      a = $D.getFirstChild(peers[i]);
      if(a && a.id == src && peers[i-1]) {
        next = $D.getFirstChild(peers[i-1]);
        break;
      }
    }
    if(next < 0) {
      return null;
    } else {
      return next;
    }
  };

  return {
    els: els,
    viewers: viewers,
    dd: dd,
    viewerTemplate: viewerTemplate,

    /**
    * Move to next image in a viewer
    */
    viewerNext: function(e) {
      $E.stopEvent(e);
      var as = this.parentNode.parentNode.getElementsByTagName('a');
      var img = this.parentNode.parentNode.getElementsByTagName('img')[3];
      var modelId = 'model' + img.id.slice(6);
      var next = getNext(img.id);
      if(next) {
        img.src = next.href;
        img.id = 'detail'+next.id.slice(5);
        $D.removeClass(as[0], 'disabled');
      }
      if(!getNext(img.id)) {
        $D.addClass(this, 'disabled');
      }
    },

    /**
    * Move to previous image in a viewer
    */
    viewerPrevious: function(e) {
      $E.stopEvent(e);
      var as = this.parentNode.parentNode.getElementsByTagName('a');
      var img = this.parentNode.parentNode.getElementsByTagName('img')[3];
      var modelId = 'model' + img.id.slice(6);
      var next = getPrev(img.id);
      if(next) {
        img.src = next.href;
        img.id = 'detail'+next.id.slice(5);
        $D.removeClass(as[1], 'disabled');
      }
      if(!getPrev(img.id)) {
        $D.addClass(this, 'disabled');
      }
    },


    /**
    * Hide an About text block
    */
    hideAbout: function(e) {
      if(e.tagName) {
        var text = e;
      } else {
        $E.stopEvent(e);
        var text = this.parentNode;
      }
      if($D.hasClass(text, 'hidden')) {
        $D.setStyle(text, 'display', 'none');
      }
      if($D.hasClass(text, 'home-text') || $D.hasClass(text, 'home')) {
        state[text.id] = $D.getRegion(text).width;
      }
      if(text.id == 'tangram-intro') {
        $D.setStyle('tangram', 'display', 'none');
      }
      var head = $D.getFirstChild(text);
      $D.setStyle($D.getChildren(text), 'display', 'none');
      $D.setStyle(head, 'display', 'inline');
      if($D.hasClass(text, 'imageonly') || $D.hasClass(text, 'imageopen')) {
        $D.setStyle(head, 'visibility', 'visible');
      }
      $D.setStyle(text, 'width', 'auto');
      if(COOKIE.read(text.id+'state') == '1') {
        COOKIE.erase(text.id+'state');
      }
    },

    /**
    * Show an About text block
    */
    showAbout: function(e) {
      if(e) {
        $E.stopEvent(e);
      }
      $D.setStyle($D.getChildren(this.parentNode), 'display', 'block');
      $D.setStyle(this.parentNode, 'display', 'block');
      $D.setStyle(this.parentNode, 'zIndex', 1);
      if($D.hasClass(this.parentNode, 'image') || $D.hasClass(this.parentNode, 'imageonly') || $D.hasClass(this.parentNode, 'imageopen')) {
        this.parentNode.getElementsByTagName('img')[0].src = this.parentNode.getElementsByTagName('img')[0].src;
        $D.setStyle(this.parentNode, 'width', 
            this.parentNode.getElementsByTagName('img')[0].getAttribute('width')+'px');
        if($D.hasClass(this.parentNode, 'imageonly') || $D.hasClass(this.parentNode, 'imageopen')) {
          $D.setStyle(this, 'visibility', 'hidden');
        }
      } else if($D.hasClass(this.parentNode, 'collection') && $D.hasClass(this.parentNode, 'scroller')) {
        $D.setStyle(this.parentNode, 'width', '432px');
      } else if(this.parentNode != document.body) {
        if($D.hasClass(this.parentNode, 'has-image')) {
          var img = this.parentNode.getElementsByTagName('img')[0];
          $D.setStyle(this.parentNode, 'width', (img.width)+'px');
        } else if($D.hasClass(this.parentNode, 'news')) {
          $D.setStyle(this.parentNode, 'width', '350px');
        } else if($D.hasClass(this.parentNode, 'projects')) {
          $D.setStyle(this.parentNode, 'width', '350px');
        } else if($D.hasClass(this.parentNode, 'impressum')) {
          $D.setStyle(this.parentNode, 'width', '350px');
        } else if(this.parentNode.id == 'tangram-intro') {
          $D.setStyle('tangram', 'display', 'block');
        } else {
          if(state[this.parentNode.id]) {
            $D.setStyle(this.parentNode, 'width', state[this.parentNode.id]+'px');
          } else {
            $D.setStyle(this.parentNode, 'width', '250px');
          }
        }
      }
      COOKIE.create(this.parentNode.id+'state', '1');
    },


    /**
    * Scroll the ul elements
    */
    scrollerStart: function() {
      if(!$D.hasClass(this, 'active') && !scrollers[this.id]) {
        var ul = this.getElementsByTagName('ul')[0];
        var lis = $D.getElementsByClassName('first', 'li', this);
        var len = lis.length*72+72-432; // add the "last" li on top
        var r = $D.getRegion(ul);
        scrollers[this.id] = new $A(ul, {
          marginLeft: {to: 0-len},
          width: {to: r.width+len}
        }, lis.length*1.1, YAHOO.util.Easing.easeNone);
        scrollers[this.id].onTween.subscribe(function(e){
          state[this.id] = $D.getRegion(this).width;
        }, ul, true);
        scrollers[this.id].animate();
      } else if(!$D.hasClass(this, 'active')) {
        scrollers[this.id].animate();
      }
    },


    /**
    * Pause the scrolling - we need to adjust the duration so that when the
    * animation resumes that it continues at the same speed.
    */
    scrollerStop: function() {
      if(scrollers[this.id]) {
        scrollers[this.id].stop();
        var s = scrollers[this.id];
        var remaining = scrollers[this.id].duration - ((s.currentFrame * scrollers[this.id].duration) / s.totalFrames);
        scrollers[this.id].duration = remaining;
      }
    },

    /**
    * Reset the scroll
    */
    scrollerReset: function() {
      if(scrollers[this.id]) {
        $D.addClass(this, 'active');
        scrollers[this.id] = null;
        var reset = new $A(this.getElementsByTagName('ul')[0], {
          marginLeft: {to: 0},
          width: {to: 504}
        }, 0.5, YAHOO.util.Easing.bounceBoth);
        reset.onComplete.subscribe(function(e){
          $D.removeClass(this, 'active');
        }, this, true);
        reset.animate();
      }
    },


    /**
    * Create a proxy image and overlay it over the cropped image in the
    * scroller
    */
    scrollerShow: function() {

      var collection = this.parentNode.parentNode.parentNode.parentNode;
      HW.scrollerStop.apply(collection);
      var xy = $D.getXY(this);

      var p = document.getElementById('proxy');

      if(!p) {
        var proxy = $('viewer').cloneNode(true);
        proxy.id = 'proxy';
        document.body.appendChild(proxy);
        $D.setXY(proxy, [0,0]);
        $D.setStyle(proxy, 'height', '102px');
        $D.setStyle(proxy, 'width', '72px');
        $D.setStyle(proxy, 'visibility', 'visible');
        $D.setStyle(proxy, 'position', 'absolute');
        var as = proxy.getElementsByTagName('a');
        $E.on(proxy.getElementsByTagName('img')[2], 'click', function(e) {
          HW.scrollerHide.apply(this);
        }, this, true);
        $E.on(as[1], 'click', HW.viewerNext);
        $E.on(as[0], 'click', HW.viewerPrevious);
      } else {
        var proxy = p;
        var as = proxy.getElementsByTagName('a');
        $D.setStyle(proxy, 'position', 'absolute');
        $D.setStyle(proxy, 'zIndex', 10);
      }

      var proxyI = proxy.getElementsByTagName('img')[3];
      proxyI.src = this.parentNode.href;
      proxyI.id = 'detail'+this.parentNode.id.slice(5);

      var className = this.parentNode.parentNode.className.replace(/ first/, '');
      var peers = $D.getElementsByClassName(className, 'li', this.parentNode.parentNode.parentNode);

      if(peers.length == 1) {
        $D.addClass([as[0], as[1]], 'disabled');
      } else {
        $D.removeClass(as[1], 'disabled');
        $D.addClass(as[0], 'disabled');
      }

      var grow = new $A(this, {
          height: {to: 709},
          opacity: {to: 0},
          width: {to: 500}}, .25, YAHOO.util.Easing.bounceBoth);
      grow.animate();

      $D.setXY(proxy, [xy[0], xy[1]]);
      var panim = new $A(proxy, {
          height: {from: 102, to: 755},
          opacity: {to: 1},
          marginTop: {to: -200},
          width: {from: 72, to: 500}}, .25, YAHOO.util.Easing.bounceBoth);
      var pIanim = new $A(proxyI, {
          height: {from: 102, to: 709},
          width: {from: 72, to: 500}}, .25, YAHOO.util.Easing.bounceBoth);

      var grow2 = new $A(collection, {
          width: {to: 860}}, .25);
      var grow3 = new $A(this.parentNode.parentNode.parentNode, {
          width: {to: 860}}, .25);

      panim.onStart.subscribe(function(e){
        $D.setStyle('proxy', 'zIndex', 2);
      }, proxy, true);

      panim.onComplete.subscribe(function(e){
        $D.addClass(this, 'active');
        $D.setStyle('proxy', 'zIndex', 2);
      }, collection, true);

      panim.animate();
      pIanim.animate();
      grow2.animate();
      grow3.animate();

    },


    /**
    * Hide the active image in the scroller
    */
    scrollerHide: function(show) {

      if(this.tagName.toLowerCase() == 'img') {
        var imgs = this.parentNode.parentNode.parentNode.getElementsByTagName('img');
        var collection = this.parentNode.parentNode.parentNode.parentNode;
        var ul = this.parentNode.parentNode.parentNode;
      } else {
        var imgs = this.getElementsByTagName('img');
        var collection = this;
        var ul = this.getElementsByTagName('ul')[0];
      }

      var shrink = new $A(imgs, {
          height: {from: 709, to: 102}, 
          opacity: {to: 1},
          width: {from: 500, to: 72}}, .25);
      var shrink2 = new $A(collection, {
          width: {to: 431}}, .25);
      if(state[collection.id]) {
        var shrink3 = new $A(ul, {
            width: {to: state[collection.id]}}, .25);
      } else {
        var shrink3 = new $A(ul, {
            height: {to: 500},
            width: {to: 504}}, .25);
      }

      shrink3.onComplete.subscribe(HW.scrollerReset, collection, true);

      var p = document.getElementById('proxy');

      if(p) {
        var shrink4 = new $A(p, {
            height: {to: 102},
            opacity: {to: 0},
            marginTop: {to: 0},
            width: {to: 72}}, .25);
        shrink4.onStart.subscribe(function(e){
          $D.setStyle(p, 'zIndex', -1);
        }, p, true);
        shrink4.onComplete.subscribe(function() {
          $D.setStyle(p, 'opacity', 0);
        });
      }

      if(show) {
        shrink.onComplete.subscribe(HW.show, this, true);
      }

      shrink.animate();
      shrink2.animate();
      shrink3.animate();

      if(p) {
        shrink4.animate();
      }

      $D.removeClass(collection, 'active');

    },



    /**
    * Build and/or show the current Model in a Viewer node
    */
    show: function(e) {

      $E.stopEvent(e);

      if(1== 2 && $D.hasClass(this.parentNode.parentNode.parentNode, 'scroller')) {

        var img = this.getElementsByTagName('img')[0];
        var collection = this.parentNode.parentNode.parentNode;

        if($D.hasClass(collection, 'active')) {
          HW.scrollerHide.apply(img, [true]);
        } else {
          HW.scrollerShow.apply(img);
        }

      } else {

        if(!HW.viewers[this.id]) {

          // Create the viewer panel
          HW.viewers[this.id] = HW.viewerTemplate.cloneNode(true);
          $D.setStyle('viewer', 'zIndex', '-10');
          $D.setAttribute(HW.viewers[this.id], 'id', 'viewer'+this.id.slice(5));
          HW.viewers[this.id].id = 'viewer'+this.id.slice(5);
          $D.insertBefore(HW.viewers[this.id], $('viewer'));
          var v = HW.viewers[this.id];

          var rz = new YAHOO.util.Resize(v, { 
            handles: ['br'], 
            minWidth: 150, 
            maxWidth: 700, 
            ratio: true, 
            status: false 
          });

          rz.on('resize', function(args) {
              var panelHeight = args.height;
              var img = this.getElementsByTagName('img')[3];
              $D.setStyle(img, 'height', args.height+'px');
              $D.setStyle(img, 'width', args.width+'px');
          }, HW.viewers[this.id], true);

          // Stores the image count for the viewer
          $D.addClass(v, $D.getFirstChild(this).className); 

          // Set default/stored position
          var viewers = $D.getElementsByClassName('viewer', 'div');
          var xy = COOKIE.read(v.id);
          if(xy) {
            xy = xy.split(',');
            $D.setXY(v, xy);
          } else {
            var xy = $D.getXY('viewer');
            $D.setXY(v, [(xy[0] + (10 * viewers.length)),
              (xy[1] + (10 * viewers.length))]);
            COOKIE.create(v.id, (xy[0] + (10 * viewers.length))
              +','+(xy[1] + (10 * viewers.length)));
          }

          $D.setStyle(HW.els, 'zIndex', '0');
          $D.setStyle(v, 'zIndex', '1');

          HW.dd[v.id] = new DD(v.id); 
          $D.setStyle(v.id, 'cursor', 'move'); 

          var as = $D.getFirstChild(v).getElementsByTagName('a');

          $E.on(as[1], 'click', function(e) {
            $E.stopEvent(e);
            var img = this.parentNode.parentNode.getElementsByTagName('img')[3];
            var modelId = 'model' + img.id.slice(6);
            var next = getNext(img.id);
            if(next) {
              img.src = next.href;
              img.id = 'detail'+next.id.slice(5);
              $D.removeClass(as[0], 'disabled');
            }
            if(!getNext(img.id)) {
              $D.addClass(this, 'disabled');
            }
          });

          $E.on(as[0], 'click', function(e) {
            $E.stopEvent(e);
            var img = this.parentNode.parentNode.getElementsByTagName('img')[3];
            var modelId = 'model' + img.id.slice(6);
            var next = getPrev(img.id);
            if(next) {
              img.src = next.href;
              img.id = 'detail'+next.id.slice(5);
              $D.removeClass(as[1], 'disabled');
            }
            if(!getPrev(img.id)) {
              $D.addClass(this, 'disabled');
            }
          });

        } else {
          var v = HW.viewers[this.id];
        }

        var img = v.getElementsByTagName('img')[3];
        var as = $D.getFirstChild(v).getElementsByTagName('a');
        var count = $D.getFirstChild(this).className.slice(1);

        // $D.addClass(as[0], 'disabled'); // back is disable at start

        // Hide panel
        $E.on(as[2], 'click', function(e) {
          $D.setStyle(v, 'visibility', 'hidden');
        });

        // // activate next image when more than one image exists
        // if(count > 1) {
        //   $D.removeClass(as[1], 'disabled'); 
        // 
        // // hide nav when only one image exists next
        // } else {
        //   $D.setStyle([as[0], as[1]], 'visibility', 'hidden'); 
        // } 

        img.src = this.href;
        img.id = 'detail'+this.id.slice(5);
        $D.setStyle(v, 'visibility', 'visible');
        
      }

    },

    reset: function(e) {

      // HW.setMode('all');

      var viewers = $D.getElementsByClassName('viewer', 'div');
      for (var i = 0; i < viewers.length; i++) {
        if(viewers[i].id != 'viewer') {
          COOKIE.erase(viewers[i].id);
          HW.dd[viewers[i].id] = null;
          HW.viewers[viewers[i].id] = null;
          document.body.removeChild(viewers[i]);
        }
      }

      var homes = $D.getElementsByClassName('home', 'div');
      for (var i = 0; i < homes.length; i++) {
        var img = homes[i].getElementsByTagName('img')[0];
        if($D.hasClass(homes[i], 'image') && $D.hasClass(homes[i], 'resize')) {

          HW.showAbout.apply(homes[i]);

          var homeResize = new $A(img, {
              width: {to: $D.getAttribute(img, 'width')}, 
              height: {to: $D.getAttribute(img, 'height')}
            }, .8, YAHOO.util.Easing.backOut);

          var homeResize2 = new $A(homes[i], {
              width: {to: $D.getAttribute(img, 'width')}
            }, .8, YAHOO.util.Easing.backOut);

          homeResize2.onComplete.subscribe(function() {
            if(resized[this.id]) {
              resizers[this.id].reset();
            }
          }, homes[i], true);

          homeResize.animate();
          homeResize2.animate();

        }
      }

      HW.viewers = [];

      var contactMove = new $A($('contact'), {
          left: {to: defaults['contact'][0]}, 
          top: {to: defaults['contact'][1]}
        }, .8, YAHOO.util.Easing.backOut);

      contactMove.onComplete.subscribe(function() {
        // var contactFade = new $A($('contact'), 
        //   {opacity: {from: 1, to: 0}}, .5);
        // // contactFade.onComplete.subscribe(function() { 
        // //   HW.setMode('collection');
        // // });
        // contactFade.animate();
      });

      contactMove.animate();

      var moves = {};
      for(var i = 0; i < HW.els.length; i++) {
        COOKIE.erase(HW.els[i].id);
        if ($D.hasClass(HW.els[i], 'about') 
            && HW.els[i].id != 'press'
            && HW.els[i].id != 'projects'
            && HW.els[i].id != 'imprint'
            && HW.els[i].id != 'news') {
          HW.hideAbout(HW.els[i]);
        }
        if(defaults[HW.els[i].id]) {
          moves[i] = new $A(HW.els[i], {
              left: {to: defaults[HW.els[i].id][0]}, 
              top: {to: defaults[HW.els[i].id][1]}
            }, .8, YAHOO.util.Easing.backOut);
        }
        if(moves[i]) {
          moves[i].animate();
        }
      }

    }, // end reset()

    /**
    * Initialize behaviours
    */
    init: function() {

      var r = $D.getClientRegion();
      $D.setStyle(document.body, 'width', (r.width-15)+'px');
      $D.setStyle(document.body, 'height', r.height+'px');

      $E.on(window, 'resize', function(e) {
        var r = $D.getClientRegion();
        $D.setStyle(document.body, 'width', r.width+'px');
        $D.setStyle(document.body, 'height', r.height+'px');
      });

      HW.viewerTemplate = document.createElement('div');

      var viewerTemplateSpan = document.createElement('span'),
          viewerTemplatePrev = document.createElement('a'),
          viewerTemplateNext = document.createElement('a'),
          viewerTemplateClose = document.createElement('a'),
          viewerTemplateImg = new Image,
          viewerTemplatePrevImg = new Image,
          viewerTemplateNextImg = new Image,
          viewerTemplateCloseImg = new Image;

      $D.addClass(HW.viewerTemplate, 'viewer');
      $D.addClass(viewerTemplatePrev, 'prev');
      $D.addClass(viewerTemplateNext, 'next');
      $D.addClass(viewerTemplateClose, 'close');

      viewerTemplatePrevImg.src = '/assets/i/left.gif';
      viewerTemplateNextImg.src = '/assets/i/right.gif';
      viewerTemplateCloseImg.src = '/assets/i/close.gif';
      viewerTemplateImg.width = 400;
      viewerTemplateImg.height = 600;

      viewerTemplatePrev.appendChild(viewerTemplatePrevImg);
      viewerTemplateNext.appendChild(viewerTemplateNextImg);
      viewerTemplateClose.appendChild(viewerTemplateCloseImg);

      viewerTemplateSpan.appendChild(viewerTemplatePrev);
      viewerTemplateSpan.appendChild(viewerTemplateNext);
      viewerTemplateSpan.appendChild(viewerTemplateClose);

      HW.viewerTemplate.appendChild(viewerTemplateSpan);
      HW.viewerTemplate.appendChild(viewerTemplateImg);

      // <div id="viewer" class="viewer">
      //   <span>
      //     <a class="prev"><img src="/assets/i/left.gif" alt="Previous"></a>
      //     <a class="next"><img src="/assets/i/right.gif" alt="Next"></a>
      //     <a class="close"><img src="/assets/i/close.gif" alt="Close"></a>
      //   </span>
      //   <img src="" alt="" width="400" height="600">
      // </div>

      $E.onAvailable('tangram', function() {

        if(!$('tangram-intro')) {
          return;
        }

        var r = $D.getClientRegion();

        $E.on(document.body, 'click', function(e) {
          if($D.getStyle('tangram', 'zIndex') == -1) {
            $D.setStyle('tangram', 'zIndex', 0);
          }
        });

        $E.on(window, 'resize', function(e) {
          var r = $D.getClientRegion();
          $D.setStyle('tangram', 'width', r.width+'px');
          $D.setStyle('tangram', 'height', r.height+'px');
        });

        $D.setXY(this, [0,0]);
        $D.setStyle(this, 'zIndex', 0);
        $D.setStyle(this, 'width', r.width+'px');
        $D.setStyle(this, 'height', r.height+'px');

        var paper = Raphael(this, r.width, r.height);

        var u = 60;
        var pos = [650,400];
        var bg = paper.rect(0, 0, r.width, r.height).attr({fill: 'white', opacity: 0}).attr('stroke-width', '0');
        var el0 = paper.path('M 0 '+5*u+' L '+u+' '+4*u+' L '+u+' '+5*u+' Z').attr('fill', '#e5c070').attr('stroke-width', '0');
        var el1 = paper.rect(0, 0, 2*u, 2*u).attr('fill', '#d47056').attr('stroke-width', '0');
        var el2 = paper.rect(2*u, 0, 4*u, .5*u).attr('fill', 'black').attr('stroke-width', '0');
        var el3 = paper.path('M 0 '+2*u+' L '+1*u+' '+2*u+' L '+1*u+' '+4*u+' L 0 '+5*u+' Z').attr('fill', '#476ca3').attr('stroke-width', '0');
        var el4 = paper.path('M '+2*u+' '+.5*u+' L '+5*u+' '+3.5*u+' L '+2*u+' '+3.5*u+' Z').attr('fill', '#476ca3').attr('stroke-width', '0');
        var el5 = paper.path('M '+2*u+' '+.5*u+' L '+5*u+' '+.5*u+' L '+5*u+' '+3.5*u+' Z').attr('fill', '#e4e1d8').attr('stroke-width', '0');
        var el6 = paper.rect(5*u, .5*u, u, 2.5*u).attr('fill', '#e5c070').attr('stroke-width', '0');
        var el7 = paper.path('M '+u+' '+2*u+' L '+2*u+' '+2*u+' L '+2*u+' '+3.5*u+' L '+3*u+' '+3.5*u+' L '+3*u+' '+5*u+' L '+u+' '+5*u+' Z').attr('fill', '#e4e1d8').attr('stroke-width', '0');
        var el8 = paper.rect(3*u, 3.5*u, 2*u, 1.5*u).attr('fill', '#d47056').attr('stroke-width', '0');
        var el9 = paper.path('M 0 '+5*u+' L '+5*u+' '+5*u+' L '+5*u+' '+3*u+' L '+6*u+' '+3*u+' L '+6*u+' '+6*u+' L 0 '+6*u+' Z').attr('fill', 'black').attr('stroke-width', '0');

        var polys = [el0, el1, el2, el3, el4, el5, el6, el7, el8, el9];
        var state = [
          {x: pos[0]+0,   y: pos[1]+4*u,   r: 0, el: el0},
          {x: pos[0]+0,   y: pos[1]+0,     r: 0, el: el1},
          {x: pos[0]+2*u, y: pos[1]+0,     r: 0, el: el2},
          {x: pos[0]+0,   y: pos[1]+2*u,   r: 0, el: el3},
          {x: pos[0]+2*u, y: pos[1]+.5*u,  r: 0, el: el4},
          {x: pos[0]+2*u, y: pos[1]+.5*u,  r: 0, el: el5},
          {x: pos[0]+5*u, y: pos[1]+.5*u,  r: 0, el: el6},
          {x: pos[0]+u,   y: pos[1]+2*u,   r: 0, el: el7},
          {x: pos[0]+3*u, y: pos[1]+3.5*u, r: 0, el: el8},
          {x: pos[0]+0,   y: pos[1]+3*u,   r: 0, el: el9}
        ];

        var defaults = [
          {x: pos[0]+0,     y: pos[1]+(4*u),   r: 0, el: el0},
          {x: pos[0]+0,     y: pos[1]+0,       r: 0, el: el1},
          {x: pos[0]+(2*u), y: pos[1]+0,       r: 0, el: el2},
          {x: pos[0]+0,     y: pos[1]+(2*u),   r: 0, el: el3},
          {x: pos[0]+(2*u), y: pos[1]+(.5*u),  r: 0, el: el4},
          {x: pos[0]+(2*u), y: pos[1]+(.5*u),  r: 0, el: el5},
          {x: pos[0]+(5*u), y: pos[1]+(.5*u),  r: 0, el: el6},
          {x: pos[0]+u,     y: pos[1]+(2*u),   r: 0, el: el7},
          {x: pos[0]+(3*u), y: pos[1]+(3.5*u), r: 0, el: el8},
          {x: pos[0],       y: pos[1]+(3*u),   r: 0, el: el9}
        ];

        for(var i = 0; i < defaults.length; i++) {
          state[i].el.translate(pos[0], pos[1]);
        }

        var drag = false;
        var active = false;

        // On space keypress, rotate the active el
        var space = new YAHOO.util.KeyListener(document, { keys:32 }, function(e) { 
          $E.stopEvent(e);
          if(active !== false) {
            state[active].r -= 90;
            state[active].el.animate({rotation: state[active].r}, 1000, "<>");
          }
        }); 
        space.enable();

        // On esc keypress, reset the game
        var esc = new YAHOO.util.KeyListener(document, { keys:27 }, function(e) { 
          if(active !== false) {
            state[active].el.attr({'stroke-width': 0});
          }
          active = false;
          var anims = {};
          for(var i = 0; i < defaults.length; i++) {
            if(defaults[i] != state[i]) {
              anims[i] = {xy: null, r: null};
              if(i == 1 || i == 2 || i == 6 || i == 8) {
                anims[i].r = state[i].el.animate({rotation: 0, x: defaults[i].x, y: defaults[i].y}, 500);
              } else {
                anims[i].r = state[i].el.animate({rotation: 0, 
                  translation: (defaults[i].x-state[i].x)+' '+(defaults[i].y-state[i].y)}, 500);
              }
              state[i].r = 0;
              state[i].x = defaults[i].x+0;
              state[i].y = defaults[i].y+0;
            }
          }
        }); 
        esc.enable();

        // function onScreen(i) {
        //   var box = state[i].el.getBBox();
        //   if(box.x < 0) {
        //     var x = 0;
        //   } else {
        //     var x = box.x;
        //   }
        //   if(box.y < 0) {
        //     var y = 0;
        //   } else {
        //     var y = box.y;
        //   }
        //   state[i].el.translate(x - box.x, y - box.y);
        //   state[i].x = x;
        //   state[i].y = y;
        // }

        var dragger = function (e, el) {
          this.dx = e.clientX;
          this.dy = e.clientY;
          this.toFront();
          drag = this;
          if(active !== false && state[active].el != this) {
            state[active].el.attr({'stroke-width': 0});
          }
          for(var i = 0; i < state.length; i++) {
            if(this == state[i].el) {
              active = i;
              break;
            }
          }
          this.animate({"fill-opacity": .5}, 500);
          this.animate({'stroke-width': 1, 'stroke': 'white'}, 100);
          e.preventDefault && e.preventDefault();
        };

        bg.mousedown(function() {
          if(active !== false) {
            state[active].el.attr({'stroke-width': 0});
          }
          $D.setStyle('tangram', 'zIndex', 0);
          $D.setStyle($D.getElementsByClassName('about', 'div'), 'zIndex', 1);
          active = false;
        });

        $E.on('rotate', 'click', function(e) {
          if(active !== false) {
            state[active].r -= 90;
            state[active].el.animate({rotation: state[active].r}, 1000, "<>");
          }
        });

        $E.on('reset', 'click', function(e) {
          if(active !== false) {
            state[active].el.attr({'stroke-width': 0});
          }
          active = false;
          var anims = {};
          for(var i = 0; i < defaults.length; i++) {
            if(defaults[i] != state[i]) {
              anims[i] = {xy: null, r: null};
              if(i == 1 || i == 2 || i == 6 || i == 8) {
                anims[i].r = state[i].el.animate({rotation: 0, x: defaults[i].x, y: defaults[i].y}, 500);
              } else {
                anims[i].r = state[i].el.animate({rotation: 0, 
                  translation: (defaults[i].x-state[i].x)+' '+(defaults[i].y-state[i].y)}, 500);
              }
              state[i].r = 0;
              state[i].x = defaults[i].x+0;
              state[i].y = defaults[i].y+0;
            }
          }
        });

        for(var i = 0; i < polys.length; i++) {
          $D.setStyle(polys[i].node, 'cursor', 'move'); 
          polys[i].mousedown(dragger);
        }

        document.onmousemove = function (e) {
          e = e || window.event;
          if (drag) {
            drag.translate(e.clientX - drag.dx, e.clientY - drag.dy);
            state[active].x = state[active].x + (e.clientX - drag.dx);
            state[active].y = state[active].y + (e.clientY - drag.dy);
            drag.dx = e.clientX;
            drag.dy = e.clientY;
          }
        };
        document.onmouseup = function () {
          if(drag) {
            var box = state[active].el.getBBox();
            if(box.x < 0) {
              var x = 0;
            } else {
              var x = box.x;
            }
            if(box.y < 0) {
              var y = 0;
            } else {
              var y = box.y;
            }
            drag.translate(x - box.x, y- box.y);
            state[active].x = x;
            state[active].y = y;
            drag.animate({"fill-opacity": 1}, 100);
            drag = false;
           }
        };
      });

      $E.on(document.getElementsByTagName('a'), 'click', function(e) {

        if($(this).parentNode.parentNode.parentNode.id == 'collections-menu') {

          for(var i = 0; i < HW.els.length; i++) {
            if (HW.els[i].id != 'collections-menu') {
              HW.hideAbout(HW.els[i]);
            }
          }

          var viewers = $D.getElementsByClassName('viewer', 'div');
          for (var i = 0; i < viewers.length; i++) {
            if(viewers[i].id != 'viewer') {
              COOKIE.erase(viewers[i].id);
              HW.dd[viewers[i].id] = null;
              HW.viewers[viewers[i].id] = null;
              document.body.removeChild(viewers[i]);
            }
          }

        }
        var url = $D.getAttribute(this, 'href');
        if(url && url.slice(0, 1) == '#') {
          $E.stopEvent(e);
          var segs = url.slice(1).split('#'), 
              el;
          for (var i=0; i < segs.length; i++) {
            el = $(segs[i]);
            if(el) {
              HW.showAbout.apply($D.getFirstChild(el));
            }
          };
        }
        // var url = $D.getAttribute(this, 'href');
        // if(url && url.slice(0, 1) == '#') {
        //   $E.stopEvent(e);
        //   var el = $(url.slice(1));
        //   if(el) {
        //     HW.showAbout.apply($D.getFirstChild(el));
        //   }
        // }
      });
      // 
      var a = document.createElement('a');
      a.setAttribute('id', 'reset');
      a.id = 'reset';
      a.appendChild(document.createTextNode('reset'));
      document.body.appendChild(a);
      $E.on(a, 'click', HW.reset);

      var selected = $D.getElementsByClassName('selected', 'li', 'menu')[0];
      HW.els = $D.getChildrenBy(document.body, function(el) {
        if(el.tagName.toLowerCase() == 'div' && el.id != 'tangram') {
          return true;
        } else {
          return false;
        }
      });

      var collections = $D.getElementsByClassName('collection', 'div');
      if(collections.length) {
        var models = {};
        var left = 0;
        for(var i = 0; i < collections.length; i++) {
          $E.on($D.getElementsByClassName('model', 'a', collections[i]), 'click', HW.show);
          if($D.hasClass(collections[i], 'scroller')) {
            $E.on(collections[i], 'mouseover', HW.scrollerStart);
            $E.on(collections[i], 'mouseout', HW.scrollerStop);
            $E.on($D.getElementsByClassName('last', 'li', collections[i]), 'click', HW.scrollerReset, collections[i], true);
          }
        }
      }

      var news = [450,100];
      var newsYear = 0;
      var currentY = 0;
      var press = [100,150];
      var projects = [550,150];
      var default_x = 0;
      var default_y = 0;

      for(var i = 0; i < HW.els.length; i++) {

        if(HW.els[i].id == 'tangram') {
          continue;
        }

        if ($D.hasClass(HW.els[i], 'news')) {
          if(newsYear === 0) {
            newsYear = $D.getAttribute(HW.els[i], 'data-year');
          }
          if(newsYear != $D.getAttribute(HW.els[i], 'data-year')) {
            currentY = parseFloat($D.getAttribute(HW.els[i], 'data-year'), 10);
            news = [(450+currentY-1800),100];
            newsYear = $D.getAttribute(HW.els[i], 'data-year');
          }
          defaults[HW.els[i].id] = [news[0], news[1]];
          news[0] = news[0]+10;
          news[1] = news[1]+10;
        }

        if ($D.hasClass(HW.els[i], 'press')) {
          defaults[HW.els[i].id] = [press[0], press[1]];
          press[0] = press[0]+10;
          press[1] = press[1]+10;
        }

        if ($D.hasClass(HW.els[i], 'projects')) {
          defaults[HW.els[i].id] = [projects[0], projects[1]];
          projects[0] = projects[0]+10;
          projects[1] = projects[1]+10;
        }

        default_x = $D.getAttribute(HW.els[i], 'data_x');
        default_y = $D.getAttribute(HW.els[i], 'data_y');

        if(default_x && default_y) {
          defaults[HW.els[i].id] = [default_x, default_y];
        }

        // Load position state
        var xy = COOKIE.read(HW.els[i].id);
        if(xy) {
          xy = xy.split(',');
          if(xy.length == 2) {
            $D.setXY(HW.els[i], xy);
          }
        } else if(!xy && defaults[HW.els[i].id]) {
          $D.setXY(HW.els[i], defaults[HW.els[i].id]);
        }

        if($D.hasClass(HW.els[i], 'resize')) {

          var img = HW.els[i].getElementsByTagName('img')[0];
          resizers[HW.els[i].id] = new YAHOO.util.Resize(img, { 
            handles: ['br'], 
            minWidth: 150, 
            maxWidth: 1000, 
            ratio: true, 
            status: true
          });
          resized[HW.els[i].id] = false;

          resizers[HW.els[i].id].on('resize', function(args) {
            $D.setStyle(this, 'width', args.width+'px');
            resized[this.id] = true;
          }, HW.els[i], true);

        }

        // Activate drag (except on contact form)
        if(HW.els[i].id != 'contact' && HW.els[i].id != 'viewer') {
          HW.dd[HW.els[i].id] = new DD(HW.els[i]); 
          $D.setStyle(HW.els[i], 'cursor', 'move'); 
        }

        $E.on(HW.els[i], 'mousedown', function(e) {
          $D.setStyle(HW.els, 'zIndex', 0);
          $D.setStyle(this, 'zIndex', 1);
        }); 

        if($D.hasClass(HW.els[i], 'image')) {
          $D.setStyle(HW.els[i], 'width', HW.els[i].getElementsByTagName('img')[0].offsetWidth+'px');
        }

        if ($D.hasClass(HW.els[i], 'projects')) {

          var imgs = HW.els[i].getElementsByTagName('p')[0].getElementsByTagName('img');
          var height = imgs[0].className;
          for (var j = 0; j < imgs.length; j++) {
            if(j > 0) {
              $D.setStyle(imgs[j], 'height', height+'px');
              // $D.setStyle(imgs[j], 'width', Math.floor(imgs[j].clientWidth / 
              //     imgs[j].clientHeight / 
              //     height)+'px');
            }
          }

          $D.setStyle(imgs, 'position', 'absolute');
          $D.addClass(imgs[0], 'active');

          if(imgs.length > 1) {
            var c = document.createElement('p');
            var p = document.createElement('a');
            var n = document.createElement('a');
            p.href='#';
            $D.setStyle(p, 'paddingRight', '5px');
            $D.setStyle([p,n], 'textDecoration', 'none');
            n.href='#';
            p.appendChild(document.createTextNode('<'));
            n.appendChild(document.createTextNode('>'));
            $D.addClass(p, 'previous');
            $D.addClass(n, 'next');
            c.appendChild(p);
            c.appendChild(n);
            $D.insertAfter(c, imgs[0].parentNode);
            $E.on([p,n], 'click', function(e) {
              $E.stopEvent(e);
              var imgs = this.getElementsByTagName('img');
              for (var x = 0; x < imgs.length; x++) {
                if($D.hasClass(imgs[x], 'active')) {
                  if(x > 0 && $D.hasClass($E.getTarget(e), 'previous') && imgs[x-1]) {
                    $D.removeClass(imgs, 'active');
                    $D.addClass(imgs[x-1], 'active');
                    break;
                  } else if($D.hasClass($E.getTarget(e), 'next') && imgs[x+1]) {
                    $D.removeClass(imgs, 'active');
                    $D.addClass(imgs[x+1], 'active');
                    break;
                  }
                }
              }
            }, imgs[0].parentNode, true);
          }
        } else if ($D.hasClass(HW.els[i], 'about') || $D.hasClass(HW.els[i], 'home')) {
          $E.on($D.getElementsByClassName('close', 'a', HW.els[i]), 'click', HW.hideAbout);
          $E.on($D.getFirstChild(HW.els[i]), 'click', HW.showAbout);
          if ($D.hasClass(HW.els[i], 'about')) {
            if(HW.els[i].id != 'press'
                && HW.els[i].id != 'news'
                && HW.els[i].id != 'imprint'
                && HW.els[i].id != 'projects') {
              if(COOKIE.read(HW.els[i].id+'state') != '1') {
                HW.hideAbout(HW.els[i]);
              }
            }
          }
        }

      } // end for()

      HW.reset();

    } // end init();
  }; // end return {}

}();

YAHOO.util.Event.onDOMReady(HW.init);

