text: (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  //
  // Shop.js Full Store Example
  //
  
  //
  // Pull in Shop.js module CommonJS module
  //
  const Shop = require('shop.js');
  
  //
  // Start execution when all scripts are loaded.  We have to wait for all scripts because there are jquery plugins that need to be
  // loaded as part of Shop.js
  //
  $(window).load(() => {
    //
    // Shop.use supports overwriting of the internal templates.
    // This is commonly done with the error template for the low level form controls to support various frameworks.
    // The below example is for Bootstrop.
    //
    Shop.use({
      Controls: {
        Error: '<div class="text-danger" if="{ errorMessage }">{ errorMessage }</div>'
      }
    });
  
    //
    // Shop.start starts the rendering engine with the passed in options and returns a reference to the Shop.js global
    // event mediator object.
    //
    const m = Shop.start(require('./settings'));
  
    //
    // .shop-button directs the user to the /shop/index.html page from the index page.
    //
    var $shopButton = $('.shop-button');
  
    //
    // .checkout-button directs the user to the /checkout/index.html page from the shop page.
    //
    var $checkoutButton = $('.checkout-button');
  
    //
    // The 'submit-success' event is sent when the user successfully submits a payment and it is successfully charged.
    //
    m.on('submit-success', () => {
      //
      // Show the thank you message after a user successfully checks out. Hide the checkout form since checkout submit
      // was a success.
      //
      $('.thanks.hidden').removeClass('hidden');
      $('.co-body').addClass('hidden');
    });
  
    //
    // Shop.isEmpty returns true if there are no items in the cart currently.
    // This code redirects the user to the index if the cart is empty on /checkout/index.html
    //
    if (window.location.pathname === '/checkout/') {
      if (Shop.isEmpty()) {
        window.location = '/';
      }
    }
  
    //
    // When the $shopButton is clicked, redirect the user to /shop/index.html
    //
    $shopButton.on('click', event => {
      window.location = '/shop';
    });
  
    //
    // When the $checkoutButton is clicked, redirect the user to /checkout/index.html
    //
    $checkoutButton.on('click', event => {
      window.location = '/checkout';
    });
  });
  
  },{"./settings":2,"shop.js":40}],2:[function(require,module,exports){
  module.exports = {
    key: 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJiaXQiOjQ1MDM2MTcwNzU2NzUxNzYsImp0aSI6IkNTaWFDckhpdDQ0Iiwic3ViIjoiRXFUR294cDV1MyJ9.fRcRQRRe0CrcnGSW12fmQ_8Cly6mqByIc5wTnANPdPWP3V1Bx9AIGbTVPTx_3KbBEziGewKJtNT1ys6WDXegyg',
    endpoint: 'https://api.staging.crowdstart.com',
    taxRates: [
      {
        taxRate: 0.0875,
        city: 'san francisco',
        state:    'ca',
        country: 'us'
      },
      {
        taxRate: 0.075,
        state:   'ca',
        country: 'us'
      }
    ]
  };
  
  },{}],3:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var CardCVC, Text,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Text = require('./text');
  
  module.exports = CardCVC = (function(superClass) {
    extend(CardCVC, superClass);
  
    function CardCVC() {
      return CardCVC.__super__.constructor.apply(this, arguments);
    }
  
    CardCVC.prototype.tag = 'card-cvc';
  
    CardCVC.prototype.lookup = 'payment.account.cvc';
  
    return CardCVC;
  
  })(Text);
  
  
  
  },{"./text":25}],4:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var CardExpiry, Text,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Text = require('./text');
  
  module.exports = CardExpiry = (function(superClass) {
    extend(CardExpiry, superClass);
  
    function CardExpiry() {
      return CardExpiry.__super__.constructor.apply(this, arguments);
    }
  
    CardExpiry.prototype.tag = 'card-expiry';
  
    CardExpiry.prototype.lookup = 'payment.account.expiry';
  
    return CardExpiry;
  
  })(Text);
  
  
  
  },{"./text":25}],5:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var CardNumber, Text,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Text = require('./text');
  
  module.exports = CardNumber = (function(superClass) {
    extend(CardNumber, superClass);
  
    function CardNumber() {
      return CardNumber.__super__.constructor.apply(this, arguments);
    }
  
    CardNumber.prototype.tag = 'card-number';
  
    CardNumber.prototype.lookup = 'payment.account.number';
  
    return CardNumber;
  
  })(Text);
  
  
  
  },{"./text":25}],6:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Checkbox, Control,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Control = require('./control');
  
  module.exports = Checkbox = (function(superClass) {
    extend(Checkbox, superClass);
  
    function Checkbox() {
      return Checkbox.__super__.constructor.apply(this, arguments);
    }
  
    Checkbox.prototype.tag = 'checkbox-control';
  
    Checkbox.prototype.html = require('../templates/controls/checkbox');
  
    Checkbox.prototype.getValue = function(event) {
      return event.target.checked;
    };
  
    return Checkbox;
  
  })(Control);
  
  
  
  },{"../templates/controls/checkbox":43,"./control":7}],7:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Control, CrowdControl, Events, m, riot, scrolling,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  CrowdControl = require('crowdcontrol');
  
  m = require('../mediator');
  
  Events = require('../events');
  
  riot = require('riot');
  
  scrolling = false;
  
  module.exports = Control = (function(superClass) {
    extend(Control, superClass);
  
    function Control() {
      return Control.__super__.constructor.apply(this, arguments);
    }
  
    Control.prototype.init = function() {
      if ((this.input == null) && (this.inputs != null)) {
        this.input = this.inputs[this.lookup];
      }
      if (this.input != null) {
        return Control.__super__.init.apply(this, arguments);
      }
    };
  
    Control.prototype.getValue = function(event) {
      var ref;
      return (ref = $(event.target).val()) != null ? ref.trim() : void 0;
    };
  
    Control.prototype.error = function(err) {
      if (err instanceof DOMException) {
        console.log('WARNING: Error in riot dom manipulation ignored.', err);
        return;
      }
      Control.__super__.error.apply(this, arguments);
      if (!scrolling) {
        scrolling = true;
        $('html, body').animate({
          scrollTop: $(this.root).offset().top - $(window).height() / 2
        }, {
          complete: function() {
            return scrolling = false;
          },
          duration: 500
        });
      }
      return m.trigger(Events.ChangeFailed, this.input.name, this.input.ref.get(this.input.name));
    };
  
    Control.prototype.change = function() {
      Control.__super__.change.apply(this, arguments);
      return m.trigger(Events.Change, this.input.name, this.input.ref.get(this.input.name));
    };
  
    Control.prototype.changed = function(value) {
      m.trigger(Events.ChangeSuccess, this.input.name, value);
      return riot.update();
    };
  
    return Control;
  
  })(CrowdControl.Views.Input);
  
  
  
  },{"../events":32,"../mediator":41,"crowdcontrol":64,"riot":114}],8:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var CountrySelect, Select,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Select = require('./select');
  
  module.exports = CountrySelect = (function(superClass) {
    extend(CountrySelect, superClass);
  
    function CountrySelect() {
      return CountrySelect.__super__.constructor.apply(this, arguments);
    }
  
    CountrySelect.prototype.tag = 'country-select-control';
  
    CountrySelect.prototype.options = function() {
      return require('../data/countries').data;
    };
  
    return CountrySelect;
  
  })(Select);
  
  
  
  },{"../data/countries":29,"./select":16}],9:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var GiftEmail, Text,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Text = require('./text');
  
  module.exports = GiftEmail = (function(superClass) {
    extend(GiftEmail, superClass);
  
    function GiftEmail() {
      return GiftEmail.__super__.constructor.apply(this, arguments);
    }
  
    GiftEmail.prototype.tag = 'gift-email';
  
    GiftEmail.prototype.lookup = 'order.giftEmail';
  
    return GiftEmail;
  
  })(Text);
  
  
  
  },{"./text":25}],10:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var GiftMessage, TextArea,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  TextArea = require('./textarea');
  
  module.exports = GiftMessage = (function(superClass) {
    extend(GiftMessage, superClass);
  
    function GiftMessage() {
      return GiftMessage.__super__.constructor.apply(this, arguments);
    }
  
    GiftMessage.prototype.tag = 'gift-message';
  
    GiftMessage.prototype.lookup = 'order.giftMessage';
  
    return GiftMessage;
  
  })(TextArea);
  
  
  
  },{"./textarea":26}],11:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Checkbox, GiftToggle,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Checkbox = require('./checkbox');
  
  module.exports = GiftToggle = (function(superClass) {
    extend(GiftToggle, superClass);
  
    function GiftToggle() {
      return GiftToggle.__super__.constructor.apply(this, arguments);
    }
  
    GiftToggle.prototype.tag = 'gift-toggle';
  
    GiftToggle.prototype.lookup = 'order.gift';
  
    return GiftToggle;
  
  })(Checkbox);
  
  
  
  },{"./checkbox":6}],12:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var GiftType, Select,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Select = require('./state-select');
  
  module.exports = GiftType = (function(superClass) {
    extend(GiftType, superClass);
  
    function GiftType() {
      return GiftType.__super__.constructor.apply(this, arguments);
    }
  
    GiftType.prototype.tag = 'gift-type';
  
    GiftType.prototype.lookup = 'order.giftType';
  
    return GiftType;
  
  })(Select);
  
  
  
  },{"./state-select":23}],13:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  module.exports = {
    Control: require('./control'),
    Text: require('./text'),
    TextArea: require('./textarea'),
    Checkbox: require('./checkbox'),
    Select: require('./select'),
    QuantitySelect: require('./quantity-select'),
    CountrySelect: require('./country-select'),
    StateSelect: require('./state-select'),
    UserEmail: require('./user-email'),
    UserName: require('./user-name'),
    ShippingAddressLine1: require('./shippingaddress-line1'),
    ShippingAddressLine2: require('./shippingaddress-line2'),
    ShippingAddressCity: require('./shippingaddress-city'),
    ShippingAddressPostalCode: require('./shippingaddress-postalcode'),
    ShippingAddressState: require('./shippingaddress-state'),
    ShippingAddressCountry: require('./shippingaddress-country'),
    CardNumber: require('./card-number'),
    CardExpiry: require('./card-expiry'),
    CardCVC: require('./card-cvc'),
    Terms: require('./terms'),
    GiftToggle: require('./gift-toggle'),
    GiftType: require('./gift-type'),
    GiftEmail: require('./gift-email'),
    GiftMessage: require('./gift-message'),
    PromoCode: require('./promocode'),
    register: function() {
      this.Text.register();
      this.TextArea.register();
      this.Checkbox.register();
      this.Select.register();
      this.QuantitySelect.register();
      this.CountrySelect.register();
      this.StateSelect.register();
      this.UserEmail.register();
      this.UserName.register();
      this.ShippingAddressLine1.register();
      this.ShippingAddressLine2.register();
      this.ShippingAddressCity.register();
      this.ShippingAddressPostalCode.register();
      this.ShippingAddressState.register();
      this.ShippingAddressCountry.register();
      this.CardNumber.register();
      this.CardExpiry.register();
      this.CardCVC.register();
      this.Terms.register();
      this.GiftToggle.register();
      this.GiftType.register();
      this.GiftEmail.register();
      this.GiftMessage.register();
      return this.PromoCode.register();
    }
  };
  
  
  
  },{"./card-cvc":3,"./card-expiry":4,"./card-number":5,"./checkbox":6,"./control":7,"./country-select":8,"./gift-email":9,"./gift-message":10,"./gift-toggle":11,"./gift-type":12,"./promocode":14,"./quantity-select":15,"./select":16,"./shippingaddress-city":17,"./shippingaddress-country":18,"./shippingaddress-line1":19,"./shippingaddress-line2":20,"./shippingaddress-postalcode":21,"./shippingaddress-state":22,"./state-select":23,"./terms":24,"./text":25,"./textarea":26,"./user-email":27,"./user-name":28}],14:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var PromoCode, Text,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Text = require('./text');
  
  module.exports = PromoCode = (function(superClass) {
    extend(PromoCode, superClass);
  
    function PromoCode() {
      return PromoCode.__super__.constructor.apply(this, arguments);
    }
  
    PromoCode.prototype.tag = 'promocode';
  
    PromoCode.prototype.lookup = 'order.promoCode';
  
    return PromoCode;
  
  })(Text);
  
  
  
  },{"./text":25}],15:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Events, QuantitySelect, Select, i, j, m, opts,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Select = require('./select');
  
  Events = require('../events');
  
  m = require('../mediator');
  
  opts = {};
  
  for (i = j = 1; j < 100; i = ++j) {
    opts[i] = i;
  }
  
  module.exports = QuantitySelect = (function(superClass) {
    extend(QuantitySelect, superClass);
  
    function QuantitySelect() {
      return QuantitySelect.__super__.constructor.apply(this, arguments);
    }
  
    QuantitySelect.prototype.tag = 'quantity-select-control';
  
    QuantitySelect.prototype.lookup = 'quantity';
  
    QuantitySelect.prototype.options = function() {
      return opts;
    };
  
    QuantitySelect.prototype.init = function() {
      return QuantitySelect.__super__.init.apply(this, arguments);
    };
  
    QuantitySelect.prototype.readOnly = true;
  
    QuantitySelect.prototype.getValue = function(event) {
      var ref;
      return parseFloat((ref = $(event.target).val()) != null ? ref.trim() : void 0);
    };
  
    QuantitySelect.prototype.change = function(e) {
      var newValue, oldValue;
      if (e.target == null) {
        return;
      }
      oldValue = this.data.get('quantity');
      QuantitySelect.__super__.change.apply(this, arguments);
      newValue = this.data.get('quantity');
      this.data.set('quantity', oldValue);
      return this.cart.set(this.data.get('productId'), newValue);
    };
  
    return QuantitySelect;
  
  })(Select);
  
  
  
  },{"../events":32,"../mediator":41,"./select":16}],16:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Select, Text, coolDown, isABrokenBrowser, isObject, requestAnimationFrame, riot,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Text = require('./text');
  
  riot = require('riot');
  
  isObject = require('is-object');
  
  requestAnimationFrame = require('raf');
  
  isABrokenBrowser = window.navigator.userAgent.indexOf('MSIE') > 0 || window.navigator.userAgent.indexOf('Trident') > 0;
  
  coolDown = -1;
  
  module.exports = Select = (function(superClass) {
    extend(Select, superClass);
  
    function Select() {
      return Select.__super__.constructor.apply(this, arguments);
    }
  
    Select.prototype.tag = 'select-control';
  
    Select.prototype.html = require('../templates/controls/select');
  
    Select.prototype.tags = false;
  
    Select.prototype.min = 10;
  
    Select.prototype.selectOptions = {};
  
    Select.prototype.options = function() {
      return this.selectOptions;
    };
  
    Select.prototype.readOnly = false;
  
    Select.prototype.ignore = false;
  
    Select.prototype.events = {
      updated: function() {
        return this.onUpdated();
      }
    };
  
    Select.prototype.getValue = function(event) {
      var ref;
      return (ref = $(event.target).val()) != null ? ref.trim().toLowerCase() : void 0;
    };
  
    Select.prototype.change = function() {
      Select.__super__.change.apply(this, arguments);
      return riot.update();
    };
  
    Select.prototype.initSelect = function($select) {
      var $input, invertedOptions, name, options, ref, value;
      options = [];
      invertedOptions = {};
      ref = this.options();
      for (value in ref) {
        name = ref[value];
        options.push({
          name: name,
          value: value
        });
        invertedOptions[name] = value;
      }
      $select.selectize({
        dropdownParent: 'body',
        valueField: 'value',
        labelField: 'name',
        searchField: 'name',
        items: [this.input.ref.get(this.input.name)] || [],
        options: options
      }).on('change', (function(_this) {
        return function(event) {
          if (coolDown !== -1) {
            return;
          }
          coolDown = setTimeout(function() {
            return coolDown = -1;
          }, 100);
          _this.change(event);
          event.preventDefault();
          event.stopPropagation();
          return false;
        };
      })(this));
      $input = $select.parent().find('.selectize-input input:first');
      $input.on('change', function(event) {
        var val;
        val = $(event.target).val();
        if (invertedOptions[val] != null) {
          return $select[0].selectize.setValue(invertedOptions[val]);
        }
      });
      if (this.readOnly) {
        return $input.attr('readonly', true);
      }
    };
  
    Select.prototype.init = function(opts) {
      Select.__super__.init.apply(this, arguments);
      return this.style = this.style || 'width:100%';
    };
  
    Select.prototype.onUpdated = function() {
      var $control, $select, select;
      if (this.input == null) {
        return;
      }
      $select = $(this.root).find('select');
      select = $select[0];
      if (select != null) {
        if (!this.initialized) {
          return requestAnimationFrame((function(_this) {
            return function() {
              _this.initSelect($select);
              return _this.initialized = true;
            };
          })(this));
        } else {
          select.selectize.clear(true);
          return select.selectize.addItem(this.input.ref.get(this.input.name), true);
        }
      } else {
        $control = $(this.root).find('.selectize-control');
        if ($control[0] == null) {
          return requestAnimationFrame((function(_this) {
            return function() {
              return _this.update();
            };
          })(this));
        }
      }
    };
  
    return Select;
  
  })(Text);
  
  
  
  },{"../templates/controls/select":44,"./text":25,"is-object":99,"raf":101,"riot":114}],17:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var ShippingAddressCity, Text,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Text = require('./text');
  
  module.exports = ShippingAddressCity = (function(superClass) {
    extend(ShippingAddressCity, superClass);
  
    function ShippingAddressCity() {
      return ShippingAddressCity.__super__.constructor.apply(this, arguments);
    }
  
    ShippingAddressCity.prototype.tag = 'shippingaddress-city';
  
    ShippingAddressCity.prototype.lookup = 'order.shippingAddress.city';
  
    return ShippingAddressCity;
  
  })(Text);
  
  
  
  },{"./text":25}],18:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var CountrySelect, ShippingAddressCountry,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  CountrySelect = require('./country-select');
  
  module.exports = ShippingAddressCountry = (function(superClass) {
    extend(ShippingAddressCountry, superClass);
  
    function ShippingAddressCountry() {
      return ShippingAddressCountry.__super__.constructor.apply(this, arguments);
    }
  
    ShippingAddressCountry.prototype.tag = 'shippingaddress-country';
  
    ShippingAddressCountry.prototype.lookup = 'order.shippingAddress.country';
  
    return ShippingAddressCountry;
  
  })(CountrySelect);
  
  
  
  },{"./country-select":8}],19:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var ShippingAddressLine1, Text,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Text = require('./text');
  
  module.exports = ShippingAddressLine1 = (function(superClass) {
    extend(ShippingAddressLine1, superClass);
  
    function ShippingAddressLine1() {
      return ShippingAddressLine1.__super__.constructor.apply(this, arguments);
    }
  
    ShippingAddressLine1.prototype.tag = 'shippingaddress-line1';
  
    ShippingAddressLine1.prototype.lookup = 'order.shippingAddress.line1';
  
    return ShippingAddressLine1;
  
  })(Text);
  
  
  
  },{"./text":25}],20:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var ShippingAddressLine2, Text,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Text = require('./text');
  
  module.exports = ShippingAddressLine2 = (function(superClass) {
    extend(ShippingAddressLine2, superClass);
  
    function ShippingAddressLine2() {
      return ShippingAddressLine2.__super__.constructor.apply(this, arguments);
    }
  
    ShippingAddressLine2.prototype.tag = 'shippingaddress-line2';
  
    ShippingAddressLine2.prototype.lookup = 'order.shippingAddress.line2';
  
    return ShippingAddressLine2;
  
  })(Text);
  
  
  
  },{"./text":25}],21:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var ShippingAddressPostalCode, Text,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Text = require('./text');
  
  module.exports = ShippingAddressPostalCode = (function(superClass) {
    extend(ShippingAddressPostalCode, superClass);
  
    function ShippingAddressPostalCode() {
      return ShippingAddressPostalCode.__super__.constructor.apply(this, arguments);
    }
  
    ShippingAddressPostalCode.prototype.tag = 'shippingaddress-postalcode';
  
    ShippingAddressPostalCode.prototype.lookup = 'order.shippingAddress.postalCode';
  
    return ShippingAddressPostalCode;
  
  })(Text);
  
  
  
  },{"./text":25}],22:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var ShippingAddressState, StateSelect,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  StateSelect = require('./state-select');
  
  module.exports = ShippingAddressState = (function(superClass) {
    extend(ShippingAddressState, superClass);
  
    function ShippingAddressState() {
      return ShippingAddressState.__super__.constructor.apply(this, arguments);
    }
  
    ShippingAddressState.prototype.tag = 'shippingaddress-state';
  
    ShippingAddressState.prototype.lookup = 'order.shippingAddress.state';
  
    return ShippingAddressState;
  
  })(StateSelect);
  
  
  
  },{"./state-select":23}],23:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Select, StateSelect,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Select = require('./select');
  
  module.exports = StateSelect = (function(superClass) {
    extend(StateSelect, superClass);
  
    function StateSelect() {
      return StateSelect.__super__.constructor.apply(this, arguments);
    }
  
    StateSelect.prototype.tag = 'state-select-control';
  
    StateSelect.prototype.html = require('../templates/controls/state-select');
  
    StateSelect.prototype.options = function() {
      return require('../data/states').data;
    };
  
    StateSelect.prototype.countryField = 'order.shippingAddress.country';
  
    StateSelect.prototype.onUpdated = function() {
      var value;
      if (this.input == null) {
        return;
      }
      if (this.input.ref(this.countryField) === 'us') {
        $(this.root).find('.selectize-control').show();
      } else {
        $(this.root).find('.selectize-control').hide();
        value = this.input.ref(this.input.name);
        if (value) {
          this.input.ref.set(this.input.name, value.toUpperCase());
        }
      }
      return StateSelect.__super__.onUpdated.apply(this, arguments);
    };
  
    return StateSelect;
  
  })(Select);
  
  
  
  },{"../data/states":31,"../templates/controls/state-select":45,"./select":16}],24:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Checkbox, Terms,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Checkbox = require('./checkbox');
  
  module.exports = Terms = (function(superClass) {
    extend(Terms, superClass);
  
    function Terms() {
      return Terms.__super__.constructor.apply(this, arguments);
    }
  
    Terms.prototype.tag = 'terms';
  
    Terms.prototype.lookup = 'terms';
  
    return Terms;
  
  })(Checkbox);
  
  
  
  },{"./checkbox":6}],25:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Control, Text, placeholder,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Control = require('./control');
  
  placeholder = require('../utils/placeholder');
  
  module.exports = Text = (function(superClass) {
    extend(Text, superClass);
  
    function Text() {
      return Text.__super__.constructor.apply(this, arguments);
    }
  
    Text.prototype.tag = 'text-control';
  
    Text.prototype.html = require('../templates/controls/text');
  
    Text.prototype.formElement = 'input';
  
    Text.prototype.init = function() {
      Text.__super__.init.apply(this, arguments);
      return this.on('updated', (function(_this) {
        return function() {
          var el;
          el = _this.root.getElementsByTagName(_this.formElement)[0];
          return placeholder(el);
        };
      })(this));
    };
  
    return Text;
  
  })(Control);
  
  
  
  },{"../templates/controls/text":46,"../utils/placeholder":55,"./control":7}],26:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Text, TextArea,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Text = require('./text');
  
  module.exports = TextArea = (function(superClass) {
    extend(TextArea, superClass);
  
    function TextArea() {
      return TextArea.__super__.constructor.apply(this, arguments);
    }
  
    TextArea.prototype.tag = 'textarea-control';
  
    TextArea.prototype.html = require('../templates/controls/textarea');
  
    TextArea.prototype.formElement = 'textarea';
  
    return TextArea;
  
  })(Text);
  
  
  
  },{"../templates/controls/textarea":47,"./text":25}],27:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Text, UserName,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Text = require('./text');
  
  module.exports = UserName = (function(superClass) {
    extend(UserName, superClass);
  
    function UserName() {
      return UserName.__super__.constructor.apply(this, arguments);
    }
  
    UserName.prototype.tag = 'user-name';
  
    UserName.prototype.lookup = 'user.name';
  
    return UserName;
  
  })(Text);
  
  
  
  },{"./text":25}],28:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Text, UserEmail,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  Text = require('./text');
  
  module.exports = UserEmail = (function(superClass) {
    extend(UserEmail, superClass);
  
    function UserEmail() {
      return UserEmail.__super__.constructor.apply(this, arguments);
    }
  
    UserEmail.prototype.tag = 'user-email';
  
    UserEmail.prototype.lookup = 'user.email';
  
    return UserEmail;
  
  })(Text);
  
  
  
  },{"./text":25}],29:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  module.exports = {
    data: {
      af: "Afghanistan",
      ax: "Åland Islands",
      al: "Albania",
      dz: "Algeria",
      as: "American Samoa",
      ad: "Andorra",
      ao: "Angola",
      ai: "Anguilla",
      aq: "Antarctica",
      ag: "Antigua and Barbuda",
      ar: "Argentina",
      am: "Armenia",
      aw: "Aruba",
      au: "Australia",
      at: "Austria",
      az: "Azerbaijan",
      bs: "Bahamas",
      bh: "Bahrain",
      bd: "Bangladesh",
      bb: "Barbados",
      by: "Belarus",
      be: "Belgium",
      bz: "Belize",
      bj: "Benin",
      bm: "Bermuda",
      bt: "Bhutan",
      bo: "Bolivia",
      bq: "Bonaire, Sint Eustatius and Saba",
      ba: "Bosnia and Herzegovina",
      bw: "Botswana",
      bv: "Bouvet Island",
      br: "Brazil",
      io: "British Indian Ocean Territory",
      bn: "Brunei Darussalam",
      bg: "Bulgaria",
      bf: "Burkina Faso",
      bi: "Burundi",
      kh: "Cambodia",
      cm: "Cameroon",
      ca: "Canada",
      cv: "Cabo Verde",
      ky: "Cayman Islands",
      cf: "Central African Republic",
      td: "Chad",
      cl: "Chile",
      cn: "China",
      cx: "Christmas Island",
      cc: "Cocos (Keeling) Islands",
      co: "Colombia",
      km: "Comoros",
      cg: "Congo",
      cd: "Congo (Democratic Republic)",
      ck: "Cook Islands",
      cr: "Costa Rica",
      ci: "Côte d'Ivoire",
      hr: "Croatia",
      cu: "Cuba",
      cw: "Curaçao",
      cy: "Cyprus",
      cz: "Czech Republic",
      dk: "Denmark",
      dj: "Djibouti",
      dm: "Dominica",
      "do": "Dominican Republic",
      ec: "Ecuador",
      eg: "Egypt",
      sv: "El Salvador",
      gq: "Equatorial Guinea",
      er: "Eritrea",
      ee: "Estonia",
      et: "Ethiopia",
      fk: "Falkland Islands",
      fo: "Faroe Islands",
      fj: "Fiji",
      fi: "Finland",
      fr: "France",
      gf: "French Guiana",
      pf: "French Polynesia",
      tf: "French Southern Territories",
      ga: "Gabon",
      gm: "Gambia",
      ge: "Georgia",
      de: "Germany",
      gh: "Ghana",
      gi: "Gibraltar",
      gr: "Greece",
      gl: "Greenland",
      gd: "Grenada",
      gp: "Guadeloupe",
      gu: "Guam",
      gt: "Guatemala",
      gg: "Guernsey",
      gn: "Guinea",
      gw: "Guinea-Bissau",
      gy: "Guyana",
      ht: "Haiti",
      hm: "Heard Island and McDonald Islands",
      va: "Holy See",
      hn: "Honduras",
      hk: "Hong Kong",
      hu: "Hungary",
      is: "Iceland",
      "in": "India",
      id: "Indonesia",
      ir: "Iran",
      iq: "Iraq",
      ie: "Ireland",
      im: "Isle of Man",
      il: "Israel",
      it: "Italy",
      jm: "Jamaica",
      jp: "Japan",
      je: "Jersey",
      jo: "Jordan",
      kz: "Kazakhstan",
      ke: "Kenya",
      ki: "Kiribati",
      kp: "Korea (Democratic People's Republic of)",
      kr: "Korea (Republic of)",
      kw: "Kuwait",
      kg: "Kyrgyzstan",
      la: "Lao People's Democratic Republic",
      lv: "Latvia",
      lb: "Lebanon",
      ls: "Lesotho",
      lr: "Liberia",
      ly: "Libya",
      li: "Liechtenstein",
      lt: "Lithuania",
      lu: "Luxembourg",
      mo: "Macao",
      mk: "Macedonia",
      mg: "Madagascar",
      mw: "Malawi",
      my: "Malaysia",
      mv: "Maldives",
      ml: "Mali",
      mt: "Malta",
      mh: "Marshall Islands",
      mq: "Martinique",
      mr: "Mauritania",
      mu: "Mauritius",
      yt: "Mayotte",
      mx: "Mexico",
      fm: "Micronesia",
      md: "Moldova",
      mc: "Monaco",
      mn: "Mongolia",
      me: "Montenegro",
      ms: "Montserrat",
      ma: "Morocco",
      mz: "Mozambique",
      mm: "Myanmar",
      na: "Namibia",
      nr: "Nauru",
      np: "Nepal",
      nl: "Netherlands",
      nc: "New Caledonia",
      nz: "New Zealand",
      ni: "Nicaragua",
      ne: "Niger",
      ng: "Nigeria",
      nu: "Niue",
      nf: "Norfolk Island",
      mp: "Northern Mariana Islands",
      no: "Norway",
      om: "Oman",
      pk: "Pakistan",
      pw: "Palau",
      ps: "Palestine",
      pa: "Panama",
      pg: "Papua New Guinea",
      py: "Paraguay",
      pe: "Peru",
      ph: "Philippines",
      pn: "Pitcairn",
      pl: "Poland",
      pt: "Portugal",
      pr: "Puerto Rico",
      qa: "Qatar",
      re: "Réunion",
      ro: "Romania",
      ru: "Russian Federation",
      rw: "Rwanda",
      bl: "Saint Barthélemy",
      sh: "Saint Helena, Ascension and Tristan da Cunha",
      kn: "Saint Kitts and Nevis",
      lc: "Saint Lucia",
      mf: "Saint Martin (French)",
      pm: "Saint Pierre and Miquelon",
      vc: "Saint Vincent and the Grenadines",
      ws: "Samoa",
      sm: "San Marino",
      st: "Sao Tome and Principe",
      sa: "Saudi Arabia",
      sn: "Senegal",
      rs: "Serbia",
      sc: "Seychelles",
      sl: "Sierra Leone",
      sg: "Singapore",
      sx: "Sint Maarten (Dutch)",
      sk: "Slovakia",
      si: "Slovenia",
      sb: "Solomon Islands",
      so: "Somalia",
      za: "South Africa",
      gs: "South Georgia and the South Sandwich Islands",
      ss: "South Sudan",
      es: "Spain",
      lk: "Sri Lanka",
      sd: "Sudan",
      sr: "Suriname",
      sj: "Svalbard and Jan Mayen",
      sz: "Swaziland",
      se: "Sweden",
      ch: "Switzerland",
      sy: "Syrian Arab Republic",
      tw: "Taiwan",
      tj: "Tajikistan",
      tz: "Tanzania",
      th: "Thailand",
      tl: "Timor-Leste",
      tg: "Togo",
      tk: "Tokelau",
      to: "Tonga",
      tt: "Trinidad and Tobago",
      tn: "Tunisia",
      tr: "Turkey",
      tm: "Turkmenistan",
      tc: "Turks and Caicos Islands",
      tv: "Tuvalu",
      ug: "Uganda",
      ua: "Ukraine",
      ae: "United Arab Emirates",
      gb: "United Kingdom of Great Britain and Northern Ireland",
      us: "United States of America",
      um: "United States Minor Outlying Islands",
      uy: "Uruguay",
      uz: "Uzbekistan",
      vu: "Vanuatu",
      ve: "Venezuela",
      vn: "Viet Nam",
      vg: "Virgin Islands (British)",
      vi: "Virgin Islands (U.S.)",
      wf: "Wallis and Futuna",
      eh: "Western Sahara",
      ye: "Yemen",
      zm: "Zambia",
      zw: "Zimbabwe"
    }
  };
  
  
  
  },{}],30:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  module.exports = {
    data: {
      'aud': '$',
      'cad': '$',
      'eur': '€',
      'gbp': '£',
      'hkd': '$',
      'jpy': '¥',
      'nzd': '$',
      'sgd': '$',
      'usd': '$',
      'ghc': '¢',
      'ars': '$',
      'bsd': '$',
      'bbd': '$',
      'bmd': '$',
      'bnd': '$',
      'kyd': '$',
      'clp': '$',
      'cop': '$',
      'xcd': '$',
      'svc': '$',
      'fjd': '$',
      'gyd': '$',
      'lrd': '$',
      'mxn': '$',
      'nad': '$',
      'sbd': '$',
      'srd': '$',
      'tvd': '$',
      'bob': '$b',
      'uyu': '$u',
      'egp': '£',
      'fkp': '£',
      'gip': '£',
      'ggp': '£',
      'imp': '£',
      'jep': '£',
      'lbp': '£',
      'shp': '£',
      'syp': '£',
      'cny': '¥',
      'afn': '؋',
      'thb': '฿',
      'khr': '៛',
      'crc': '₡',
      'trl': '₤',
      'ngn': '₦',
      'kpw': '₩',
      'krw': '₩',
      'ils': '₪',
      'vnd': '₫',
      'lak': '₭',
      'mnt': '₮',
      'cup': '₱',
      'php': '₱',
      'uah': '₴',
      'mur': '₨',
      'npr': '₨',
      'pkr': '₨',
      'scr': '₨',
      'lkr': '₨',
      'irr': '﷼',
      'omr': '﷼',
      'qar': '﷼',
      'sar': '﷼',
      'yer': '﷼',
      'pab': 'b/.',
      'vef': 'bs',
      'bzd': 'bz$',
      'nio': 'c$',
      'chf': 'chf',
      'huf': 'ft',
      'awg': 'ƒ',
      'ang': 'ƒ',
      'pyg': 'gs',
      'jmd': 'j$',
      'czk': 'kč',
      'bam': 'km',
      'hrk': 'kn',
      'dkk': 'kr',
      'eek': 'kr',
      'isk': 'kr',
      'nok': 'kr',
      'sek': 'kr',
      'hnl': 'l',
      'ron': 'lei',
      'all': 'lek',
      'lvl': 'ls',
      'ltl': 'lt',
      'mzn': 'mt',
      'twd': 'nt$',
      'bwp': 'p',
      'byr': 'p.',
      'gtq': 'q',
      'zar': 'r',
      'brl': 'r$',
      'dop': 'rd$',
      'myr': 'rm',
      'idr': 'rp',
      'sos': 's',
      'pen': 's/.',
      'ttd': 'tt$',
      'zwd': 'z$',
      'pln': 'zł',
      'mkd': 'ден',
      'rsd': 'Дин.',
      'bgn': 'лв',
      'kzt': 'лв',
      'kgs': 'лв',
      'uzs': 'лв',
      'azn': 'ман',
      'rub': 'руб',
      'inr': '',
      'try': '',
      '': ''
    }
  };
  
  
  
  },{}],31:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  module.exports = {
    data: {
      al: 'Alabama',
      ak: 'Alaska',
      az: 'Arizona',
      ar: 'Arkansas',
      ca: 'California',
      co: 'Colorado',
      ct: 'Connecticut',
      de: 'Delaware',
      dc: 'District of Columbia',
      fl: 'Florida',
      ga: 'Georgia',
      hi: 'Hawaii',
      id: 'Idaho',
      il: 'Illinois',
      "in": 'Indiana',
      ia: 'Iowa',
      ks: 'Kansas',
      ky: 'Kentucky',
      la: 'Louisiana',
      me: 'Maine',
      mt: 'Montana',
      ne: 'Nebraska',
      nv: 'Nevada',
      nh: 'New Hampshire',
      nj: 'New Jersey',
      nm: 'New Mexico',
      ny: 'New York',
      nc: 'North Carolina',
      nd: 'North Dakota',
      oh: 'Ohio',
      ok: 'Oklahoma',
      or: 'Oregon',
      md: 'Maryland',
      ma: 'Massachusetts',
      mi: 'Michigan',
      mn: 'Minnesota',
      ms: 'Mississippi',
      mo: 'Missouri',
      pa: 'Pennsylvania',
      ri: 'Rhode Island',
      sc: 'South Carolina',
      sd: 'South Dakota',
      tn: 'Tennessee',
      tx: 'Texas',
      ut: 'Utah',
      vt: 'Vermont',
      va: 'Virginia',
      wa: 'Washington',
      wv: 'West Virginia',
      wi: 'Wisconsin',
      wy: 'Wyoming',
      aa: 'U.S. Armed Forces – Americas',
      ae: 'U.S. Armed Forces – Europe',
      ap: 'U.S. Armed Forces – Pacific'
    }
  };
  
  
  
  },{}],32:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  module.exports = {
    Ready: 'ready',
    SetData: 'set-data',
    TryUpdateItem: 'try-update-item',
    UpdateItem: 'update-item',
    UpdateItems: 'update-items',
    Change: 'change',
    ChangeSuccess: 'change-success',
    ChangeFailed: 'change-failed',
    DeleteLineItem: 'delete-line-item',
    Submit: 'submit',
    SubmitSuccess: 'submit-success',
    SubmitFailed: 'submit-failed',
    ApplyCoupon: 'apply-coupon',
    ApplyCouponSuccess: 'apply-coupon-success',
    ApplyCouponFailed: 'apply-coupon-failed'
  };
  
  
  
  },{}],33:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var CartForm, CrowdControl, Events, m, riot, store,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  CrowdControl = require('crowdcontrol');
  
  riot = require('riot');
  
  m = require('../mediator');
  
  Events = require('../events');
  
  store = require('../utils/store');
  
  require('../utils/patches');
  
  module.exports = CartForm = (function(superClass) {
    extend(CartForm, superClass);
  
    function CartForm() {
      return CartForm.__super__.constructor.apply(this, arguments);
    }
  
    CartForm.prototype.tag = 'cart';
  
    CartForm.prototype.html = '<yield>\n  <lineitems if="{ !isEmpty() }"></lineitems>\n</yield>';
  
    CartForm.prototype.init = function() {
      var promoCode;
      this.originalParentElement = this.root.parentElement;
      CartForm.__super__.init.apply(this, arguments);
      promoCode = store.get('promoCode');
      if (promoCode) {
        this.data.set('order.promoCode', promoCode);
        this.applyPromoCode();
        return this.update();
      }
    };
  
    CartForm.prototype.configs = require('./config');
  
    CartForm.prototype.applying = false;
  
    CartForm.prototype.promoMessage = '';
  
    CartForm.prototype.isEmpty = function() {
      return this.data('order.items').length === 0;
    };
  
    CartForm.prototype.applyPromoCode = function() {
      var promoCode;
      this.promoMessage = '';
      promoCode = this.data.get('order.promoCode');
      if (!promoCode) {
        return;
      }
      store.set('promoCode', promoCode);
      this.promoMessage = 'Applying...';
      this.applying = true;
      promoCode = promoCode.toUpperCase();
      m.trigger(Events.ApplyCoupon, promoCode);
      return this.cart.promoCode(promoCode).then((function(_this) {
        return function() {
          var coupon;
          _this.applying = false;
          coupon = _this.data.get('order.coupon');
          if (((coupon != null ? coupon.freeProductId : void 0) != null) && coupon.freeProductId !== "" && coupon.freeQuantity > 0) {
            _this.promoMessage = coupon.freeQuantity + " Free " + freeProduct.name;
          } else {
            _this.promoMessage = promoCode + ' Applied!';
          }
          m.trigger(Events.ApplyCouponSuccess, coupon);
          return _this.update();
        };
      })(this))["catch"]((function(_this) {
        return function(err) {
          var coupon;
          store.remove('promoCode');
          _this.applying = false;
          coupon = _this.data.get('order.coupon');
          if (coupon != null ? coupon.enabled : void 0) {
            _this.promoMessage = 'This code is expired.';
          } else {
            _this.promoMessage = 'This code is invalid.';
          }
          m.trigger(Events.ApplyCouponFailed, err);
          return _this.update();
        };
      })(this));
    };
  
    return CartForm;
  
  })(CrowdControl.Views.Form);
  
  
  
  },{"../events":32,"../mediator":41,"../utils/patches":54,"../utils/store":56,"./config":35,"crowdcontrol":64,"riot":114}],34:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var CheckoutForm, CrowdControl, Events, m, riot, store,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  CrowdControl = require('crowdcontrol');
  
  riot = require('riot');
  
  m = require('../mediator');
  
  Events = require('../events');
  
  store = require('../utils/store');
  
  module.exports = CheckoutForm = (function(superClass) {
    extend(CheckoutForm, superClass);
  
    function CheckoutForm() {
      return CheckoutForm.__super__.constructor.apply(this, arguments);
    }
  
    CheckoutForm.prototype.tag = 'checkout';
  
    CheckoutForm.prototype.html = '<form onsubmit={submit}>\n  <yield/>\n</form>';
  
    CheckoutForm.prototype.errorMessage = null;
  
    CheckoutForm.prototype.loading = false;
  
    CheckoutForm.prototype.checkedOut = false;
  
    CheckoutForm.prototype.configs = require('./config');
  
    CheckoutForm.prototype._submit = function(event) {
      if (this.loading || this.checkedOut) {
        return;
      }
      this.loading = true;
      m.trigger(Events.Submit, this.tag);
      this.errorMessage = null;
      this.update();
      return this.cart.checkout().then((function(_this) {
        return function(pRef) {
          var hasErrored;
          pRef.p["catch"](function(err) {
            var hasErrored, ref;
            if (typeof window !== "undefined" && window !== null) {
              if ((ref = window.Raven) != null) {
                ref.captureException(err);
              }
            }
            hasErrored = true;
            _this.loading = false;
            console.log("checkout submit Error: " + err);
            _this.errorMessage = 'Unable to complete your transaction. Please try again later.';
            m.trigger(Events.SubmitFailed, _this.tag);
            return _this.update();
          });
          hasErrored = false;
          setTimeout(function() {
            if (!hasErrored) {
              _this.loading = false;
              store.clear();
              _this.checkedOut = true;
              return _this.update();
            }
          }, 200);
          return m.trigger(Events.SubmitSuccess, _this.tag);
        };
      })(this))["catch"]((function(_this) {
        return function(err) {
          var ref;
          _this.loading = false;
          console.log("authorize submit Error: " + err);
          if (err.type === 'authorization-error') {
            _this.errorMessage = err.message;
          } else {
            if (typeof window !== "undefined" && window !== null) {
              if ((ref = window.Raven) != null) {
                ref.captureException(err);
              }
            }
            _this.errorMessage = 'Unable to complete your transaction. Please try again later.';
          }
          m.trigger(Events.SubmitFailed, _this.tag);
          return _this.update();
        };
      })(this));
    };
  
    return CheckoutForm;
  
  })(CrowdControl.Views.Form);
  
  
  
  },{"../events":32,"../mediator":41,"../utils/store":56,"./config":35,"crowdcontrol":64,"riot":114}],35:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var agreeToTerms, cardNumber, cvc, expiration, isEcardGiftRequired, isEmail, isPostalRequired, isRequired, ref, requiresStripe, splitName;
  
  ref = require('./middleware'), isRequired = ref.isRequired, isEmail = ref.isEmail, splitName = ref.splitName, isPostalRequired = ref.isPostalRequired, requiresStripe = ref.requiresStripe, expiration = ref.expiration, cardNumber = ref.cardNumber, cvc = ref.cvc, isEcardGiftRequired = ref.isEcardGiftRequired, agreeToTerms = ref.agreeToTerms;
  
  module.exports = {
    'user.email': [isRequired, isEmail],
    'user.name': [isRequired, splitName],
    'user.password': null,
    'order.shippingAddress.line1': [isRequired],
    'order.shippingAddress.line2': null,
    'order.shippingAddress.city': [isRequired],
    'order.shippingAddress.state': [isRequired],
    'order.shippingAddress.postalCode': [isPostalRequired],
    'order.shippingAddress.country': [isRequired],
    'order.gift': null,
    'order.giftType': null,
    'order.giftEmail': [isEcardGiftRequired, isEmail],
    'order.giftMessage': null,
    'order.promoCode': null,
    'payment.account.number': [requiresStripe, cardNumber],
    'payment.account.expiry': [requiresStripe, expiration],
    'payment.account.cvc': [requiresStripe, cvc],
    'terms': [agreeToTerms]
  };
  
  
  
  },{"./middleware":39}],36:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  module.exports = {
    Checkout: require('./checkout'),
    Cart: require('./cart'),
    LineItem: require('./lineitem'),
    LineItems: require('./lineitems'),
    register: function() {
      this.Checkout.register();
      this.Cart.register();
      this.LineItem.register();
      return this.LineItems.register();
    }
  };
  
  
  
  },{"./cart":33,"./checkout":34,"./lineitem":37,"./lineitems":38}],37:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var CrowdControl, Events, LineItemForm, m, riot,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  CrowdControl = require('crowdcontrol');
  
  riot = require('riot');
  
  m = require('../mediator');
  
  Events = require('../events');
  
  module.exports = LineItemForm = (function(superClass) {
    extend(LineItemForm, superClass);
  
    function LineItemForm() {
      return LineItemForm.__super__.constructor.apply(this, arguments);
    }
  
    LineItemForm.prototype.tag = 'lineitem';
  
    LineItemForm.prototype.html = require('../templates/forms/lineitem');
  
    LineItemForm.prototype.configs = {
      'quantity': null
    };
  
    LineItemForm.prototype.init = function() {
      return LineItemForm.__super__.init.apply(this, arguments);
    };
  
    LineItemForm.prototype["delete"] = function(event) {
      return m.trigger(Events.DeleteLineItem, this.data);
    };
  
    return LineItemForm;
  
  })(CrowdControl.Views.Form);
  
  
  
  },{"../events":32,"../mediator":41,"../templates/forms/lineitem":48,"crowdcontrol":64,"riot":114}],38:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var CrowdControl, Events, LineItems, m, riot,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  CrowdControl = require('crowdcontrol');
  
  riot = require('riot');
  
  m = require('../mediator');
  
  Events = require('../events');
  
  module.exports = LineItems = (function(superClass) {
    extend(LineItems, superClass);
  
    function LineItems() {
      return LineItems.__super__.constructor.apply(this, arguments);
    }
  
    LineItems.prototype.tag = 'lineitems';
  
    LineItems.prototype.html = require('../templates/forms/lineitems');
  
    LineItems.prototype.init = function() {};
  
    return LineItems;
  
  })(CrowdControl.Views.View);
  
  
  
  },{"../events":32,"../mediator":41,"../templates/forms/lineitems":49,"crowdcontrol":64,"riot":114}],39:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Promise, countryUtils, emailRe, requestAnimationFrame;
  
  Promise = require('broken');
  
  requestAnimationFrame = require('raf');
  
  countryUtils = require('../utils/country');
  
  emailRe = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
  
  module.exports = {
    isRequired: function(value) {
      if (value && value !== '') {
        return value;
      }
      throw new Error('Required');
    },
    isEmail: function(value) {
      if (!value) {
        return value;
      }
      if (emailRe.test(value)) {
        return value.toLowerCase();
      }
      throw new Error('Enter a valid email');
    },
    splitName: function(value) {
      var i;
      if (!value) {
        return value;
      }
      i = value.indexOf(' ');
      this.set('user.firstName', value.slice(0, i));
      this.set('user.lastName', value.slice(i + 1));
      return value;
    },
    isPostalRequired: function(value) {
      if (countryUtils.requiresPostalCode(this.get('order.shippingAddress.country') || '') && ((value == null) || value === '')) {
        throw new Error("Required for Selected Country");
      }
      return value;
    },
    isEcardGiftRequired: function(value) {
      if ((!this.get('order.gift') || this.get('order.giftType') !== 'ecard') || (value && value !== '')) {
        return value;
      }
      throw new Error('Required');
    },
    requiresStripe: function(value) {
      if (this('order.type') === 'stripe' && ((value == null) || value === '')) {
        throw new Error("Required");
      }
      return value;
    },
    requireTerms: function(value) {
      if (!value) {
        throw new Error('Please read and agree to the terms and conditions.');
      }
      return value;
    },
    cardNumber: function(value) {
      if (!value) {
        return value;
      }
      if (this('order.type') !== 'stripe') {
        return value;
      }
      return new Promise(function(resolve, reject) {
        return requestAnimationFrame(function() {
          if ($('input[name=number]').hasClass('jp-card-invalid')) {
            reject(new Error('Enter a valid card number'));
          }
          return resolve(value);
        });
      });
    },
    expiration: function(value) {
      var base, base1, date;
      if (!value) {
        return value;
      }
      if (this('order.type') !== 'stripe') {
        return value;
      }
      date = value.split('/');
      if (date.length < 2) {
        throw new Error('Enter a valid expiration date');
      }
      this.set('payment.account.month', typeof (base = date[0]).trim === "function" ? base.trim() : void 0);
      this.set('payment.account.year', ('' + (new Date()).getFullYear()).substr(0, 2) + (typeof (base1 = date[1]).trim === "function" ? base1.trim() : void 0));
      return new Promise(function(resolve, reject) {
        return requestAnimationFrame(function() {
          if ($('input[name=expiry]').hasClass('jp-card-invalid')) {
            reject(new Error('Enter a valid expiration date'));
          }
          return resolve(value);
        });
      });
    },
    cvc: function(value) {
      if (!value) {
        return value;
      }
      if (this('order.type') !== 'stripe') {
        return value;
      }
      return new Promise(function(resolve, reject) {
        return requestAnimationFrame(function() {
          if ($('input[name=cvc]').hasClass('jp-card-invalid')) {
            reject(new Error('Enter a valid CVC number'));
          }
          return resolve(value);
        });
      });
    },
    agreeToTerms: function(value) {
      if (value === true) {
        return value;
      }
      throw new Error('Agree to the terms and conditions');
    }
  };
  
  
  
  },{"../utils/country":52,"broken":59,"raf":101}],40:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Cart, Crowdstart, Events, Promise, Shop, analytics, extend, getReferrer, itemUpdateQueue, m, refer, riot, store, waits;
  
  require('./utils/patches');
  
  Promise = require('broken');
  
  riot = require('riot');
  
  extend = require('extend');
  
  if (typeof window !== "undefined" && window !== null) {
    window.riot = riot;
  }
  
  refer = require('referential');
  
  store = require('./utils/store');
  
  Cart = require('commerce.js').Cart;
  
  Crowdstart = require('crowdstart.js');
  
  m = require('./mediator');
  
  Events = require('./events');
  
  analytics = require('./utils/analytics');
  
  Shop = require('./shop');
  
  Shop.Forms = require('./forms');
  
  Shop.Widgets = require('./widgets');
  
  Shop.Controls = require('./controls');
  
  Shop.CrowdControl = require('crowdcontrol');
  
  Shop.Referential = refer;
  
  Shop.CrowdControl.Views.View.prototype.renderCurrency = require('./utils/currency').renderUICurrencyFromJSON;
  
  Shop.use = function(templates) {
    var ref, ref1;
    if (templates != null ? (ref = templates.Controls) != null ? ref.Error : void 0 : void 0) {
      Shop.Controls.Control.prototype.errorHtml = templates.Controls.Error;
    }
    if (templates != null ? (ref1 = templates.Controls) != null ? ref1.Text : void 0 : void 0) {
      return Shop.Controls.Text.prototype.html = templates.Controls.Text;
    }
  };
  
  Shop.riot = riot;
  
  Shop.analytics = analytics;
  
  Shop.isEmpty = function() {
    var items;
    items = this.data.get('order.items');
    return items.length === 0;
  };
  
  getReferrer = function() {
    var err, error, k, match, q, qs, search, v;
    search = /([^&=]+)=?([^&]*)/g;
    q = window.location.href.split('?')[1];
    qs = {};
    if (q != null) {
      while ((match = search.exec(q))) {
        k = match[1];
        try {
          k = decodeURIComponent(k);
        } catch (undefined) {}
        v = match[2];
        try {
          v = decodeURIComponent(v);
        } catch (error) {
          err = error;
        }
        qs[k] = v;
      }
    }
    if (qs.referrer != null) {
      store.set('referrer', qs.referrer);
      return q.referrer;
    } else {
      return store.get('referrer');
    }
  };
  
  Shop.start = function(opts) {
    var data, i, item, items, j, k, len, len1, p, ps, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, referrer, tag, tags, v;
    if (opts == null) {
      opts = {};
    }
    if (opts.key == null) {
      throw new Error('Please specify your API Key');
    }
    Shop.Forms.register();
    Shop.Widgets.register();
    Shop.Controls.register();
    referrer = (ref = getReferrer()) != null ? ref : (ref1 = opts.order) != null ? ref1.referrer : void 0;
    items = store.get('items');
    this.data = refer({
      taxRates: opts.taxRates || [],
      order: {
        giftType: 'physical',
        type: 'stripe',
        shippingRate: ((ref2 = opts.config) != null ? ref2.shippingRate : void 0) || ((ref3 = opts.order) != null ? ref3.shippingRate : void 0) || 0,
        taxRate: ((ref4 = opts.config) != null ? ref4.taxRate : void 0) || ((ref5 = opts.order) != null ? ref5.taxRate : void 0) || 0,
        currency: ((ref6 = opts.config) != null ? ref6.currency : void 0) || ((ref7 = opts.order) != null ? ref7.currency : void 0) || 'usd',
        referrerId: referrer,
        shippingAddress: {
          country: 'us'
        },
        discount: 0,
        tax: 0,
        subtotal: 0,
        total: 0,
        items: items != null ? items : []
      }
    });
    data = this.data.get();
    for (k in data) {
      v = data[k];
      if (opts[k]) {
        extend(data[k], opts[k]);
      }
    }
    this.data.set(data);
    this.client = new Crowdstart.Api({
      key: opts.key,
      endpoint: opts.endpoint
    });
    this.cart = new Cart(this.client, this.data);
    tags = riot.mount('cart, cart-counter, checkout', {
      data: this.data,
      cart: this.cart,
      client: this.client
    });
    riot.update = function() {
      var i, len, results, tag;
      results = [];
      for (i = 0, len = tags.length; i < len; i++) {
        tag = tags[i];
        results.push(tag.update());
      }
      return results;
    };
    this.cart.onUpdate = (function(_this) {
      return function(item) {
        items = _this.data.get('order.items');
        store.set('items', items);
        if (item != null) {
          m.trigger(Events.UpdateItem, item);
        }
        return riot.update();
      };
    })(this);
    ps = [];
    for (i = 0, len = tags.length; i < len; i++) {
      tag = tags[i];
      p = new Promise(function(resolve) {
        return tag.one('updated', function() {
          return resolve();
        });
      });
      ps.push(p);
    }
    Promise.settle(ps).then(function() {
      return m.trigger(Events.Ready);
    })["catch"](function(err) {
      var ref8;
      return typeof window !== "undefined" && window !== null ? (ref8 = window.Raven) != null ? ref8.captureException(err) : void 0 : void 0;
    });
    m.data = this.data;
    m.on(Events.SetData, (function(_this) {
      return function(data1) {
        _this.data = data1;
        return _this.cart.invoice();
      };
    })(this));
    m.on(Events.DeleteLineItem, function(item) {
      var id;
      id = item.get('id');
      return Shop.setItem(id, 0);
    });
    m.trigger(Events.SetData, this.data);
    m.on('error', function(err) {
      var ref8;
      console.log(err);
      return typeof window !== "undefined" && window !== null ? (ref8 = window.Raven) != null ? ref8.captureException(err) : void 0 : void 0;
    });
    if ((items != null) && items.length > 0) {
      for (j = 0, len1 = items.length; j < len1; j++) {
        item = items[j];
        if (item.id != null) {
          this.cart.load(item.id);
        } else if (item.productId != null) {
          this.cart.refresh(item.productId);
        }
      }
    }
    riot.update();
    return m;
  };
  
  waits = 0;
  
  itemUpdateQueue = [];
  
  Shop.setItem = function(id, quantity, locked) {
    var p;
    if (locked == null) {
      locked = false;
    }
    m.trigger(Events.TryUpdateItem, id);
    p = this.cart.set(id, quantity, locked);
    if (this.promise !== p) {
      this.promise = p;
      return this.promise.then((function(_this) {
        return function() {
          riot.update();
          return m.trigger(Events.UpdateItems, _this.data.get('order.items'));
        };
      })(this))["catch"](function(err) {
        var ref;
        return typeof window !== "undefined" && window !== null ? (ref = window.Raven) != null ? ref.captureException(err) : void 0 : void 0;
      });
    }
  };
  
  Shop.getItem = function(id) {
    return this.cart.get(id);
  };
  
  module.exports = Crowdstart.Shop = Shop;
  
  
  
  },{"./controls":13,"./events":32,"./forms":36,"./mediator":41,"./shop":42,"./utils/analytics":51,"./utils/currency":53,"./utils/patches":54,"./utils/store":56,"./widgets":58,"broken":59,"commerce.js":63,"crowdcontrol":64,"crowdstart.js":89,"extend":98,"referential":103,"riot":114}],41:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var riot;
  
  riot = require('riot');
  
  module.exports = riot.observable({});
  
  
  
  },{"riot":114}],42:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Shop;
  
  module.exports = Shop = (function() {
    function Shop() {}
  
    return Shop;
  
  })();
  
  
  
  },{}],43:[function(require,module,exports){
  module.exports = '<input id="{ input.name }" name="{ name || input.name }" type="checkbox" onchange="{ change }" onblur="{ change }" __selected="{ input.ref(input.name) }"/><yield></yield>'
  },{}],44:[function(require,module,exports){
  module.exports = '<select id="{ input.name }" style="{ style }" name="{ name || input.name }" onchange="{ change }" onblur="{ change }" placeholder="{ placeholder }"></select><yield></yield>'
  },{}],45:[function(require,module,exports){
  module.exports = '<input if="{ input.ref(countryField) !== &quot;us&quot; }" id="{ input.name }" name="{ name || input.name }" type="text" onchange="{ change }" onblur="{ change }" value="{ input.ref(input.name) }" placeholder="{ placeholder }"/><select if="{ input.ref(countryField) == &quot;us&quot; }" id="{ input.name }" style="{ style }" name="{ name || input.name }" onchange="{ change }" onblur="{ change }" value="{ input.ref(input.name) }" data-placeholder="{ placeholder }"><option if="{ placeholder }"></option><option each="{ value, name in options }" value="{value}" __selected="{ this.parent.input.ref(input.name) == value }">{name}</option></select><yield></yield>'
  },{}],46:[function(require,module,exports){
  module.exports = '<input id="{ input.name }" name="{ name || input.name }" type="{ type }" onchange="{ change }" onblur="{ change }" value="{ input.ref(input.name) }" placeholder="{ placeholder }" autocomplete="{ autoComplete }"/><yield></yield>'
  },{}],47:[function(require,module,exports){
  module.exports = '<textarea id="{ input.name }" name="{ name || input.name }" rows="{ rows }" cols="{ cols }" type="text" onchange="{ change }" onblur="{ change }" placeholder="{ placeholder }">{ input.ref(input.name) }</textarea><yield></yield>'
  },{}],48:[function(require,module,exports){
  module.exports = '<yield><div if="{ !data.get(\'locked\') }" class="product-quantity-container"><quantity-select-control></quantity-select-control></div><div if="{ data.get(\'locked\') }" class="product-quantity-container locked">{ data.get(\'quantity\') }</div><div class="product-text-container"><div class="product-name">{ data.get(\'productName\') }</div><div class="product-slug">{ data.get(\'productSlug\') }</div><div if="{ data.get(\'description\') }" class="product-description">{ data.get(\'description\') }</div></div><div onclick="{ delete }" class="product-delete"></div><div class="product-price-container"><div class="product-price">{ renderCurrency(parentData.get(\'currency\'), data.get().price * data.get().quantity) }<div class="product-currency">{ parentData.get(\'currency\').toUpperCase() }</div></div><div if="{ data.get().listPrice &gt; data.get().price }" class="product-list-price">{ renderCurrency(parentData.get(\'currency\'), data.get().listPrice * data.get().quantity) }<div class="product-currency">{ parentData.get(\'currency\').toUpperCase() }</div></div></div></yield>'
  },{}],49:[function(require,module,exports){
  module.exports = '<lineitem each="{ item, v in data(\'order.items\') }" parent-data="{ this.parent.data.ref(\'order\') }" data="{ this.parent.data.ref(\'order.items.\' + v) }"><yield></yield></lineitem>'
  },{}],50:[function(require,module,exports){
  module.exports = '<div class="cart-count">({ countItems() })</div><div class="cart-price">({ renderCurrency(data.get(\'order.currency\'), totalPrice()) })</div>'
  },{}],51:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  module.exports = {
    track: function(event, data) {
      var err, error;
      if ((typeof window !== "undefined" && window !== null ? window.analytics : void 0) != null) {
        try {
          return window.analytics.track(event, data);
        } catch (error) {
          err = error;
          return console.error(err);
        }
      }
    }
  };
  
  
  
  },{}],52:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  module.exports = {
    requiresPostalCode: function(code) {
      code = code.toLowerCase();
      return code === 'dz' || code === 'ar' || code === 'am' || code === 'au' || code === 'at' || code === 'az' || code === 'a2' || code === 'bd' || code === 'by' || code === 'be' || code === 'ba' || code === 'br' || code === 'bn' || code === 'bg' || code === 'ca' || code === 'ic' || code === 'cn' || code === 'hr' || code === 'cy' || code === 'cz' || code === 'dk' || code === 'en' || code === 'ee' || code === 'fo' || code === 'fi' || code === 'fr' || code === 'ge' || code === 'de' || code === 'gr' || code === 'gl' || code === 'gu' || code === 'gg' || code === 'ho' || code === 'hu' || code === 'in' || code === 'id' || code === 'il' || code === 'it' || code === 'jp' || code === 'je' || code === 'kz' || code === 'kr' || code === 'ko' || code === 'kg' || code === 'lv' || code === 'li' || code === 'lt' || code === 'lu' || code === 'mk' || code === 'mg' || code === 'm3' || code === 'my' || code === 'mh' || code === 'mq' || code === 'yt' || code === 'mx' || code === 'mn' || code === 'me' || code === 'nl' || code === 'nz' || code === 'nb' || code === 'no' || code === 'pk' || code === 'ph' || code === 'pl' || code === 'po' || code === 'pt' || code === 'pr' || code === 're' || code === 'ru' || code === 'sa' || code === 'sf' || code === 'cs' || code === 'sg' || code === 'sk' || code === 'si' || code === 'za' || code === 'es' || code === 'lk' || code === 'nt' || code === 'sx' || code === 'uv' || code === 'vl' || code === 'se' || code === 'ch' || code === 'tw' || code === 'tj' || code === 'th' || code === 'tu' || code === 'tn' || code === 'tr' || code === 'tm' || code === 'vi' || code === 'ua' || code === 'gb' || code === 'us' || code === 'uy' || code === 'uz' || code === 'va' || code === 'vn' || code === 'wl' || code === 'ya';
    }
  };
  
  
  
  },{}],53:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var currencySeparator, currencySigns, digitsOnlyRe, isZeroDecimal;
  
  currencySigns = require('../data/currencies').data;
  
  currencySeparator = '.';
  
  digitsOnlyRe = new RegExp('[^\\d.-]', 'g');
  
  isZeroDecimal = function(code) {
    if (code === 'bif' || code === 'clp' || code === 'djf' || code === 'gnf' || code === 'jpy' || code === 'kmf' || code === 'krw' || code === 'mga' || code === 'pyg' || code === 'rwf' || code === 'vnd' || code === 'vuv' || code === 'xaf' || code === 'xof' || code === 'xpf') {
      return true;
    }
    return false;
  };
  
  module.exports = {
    renderUpdatedUICurrency: function(code, uiCurrency) {
      var currentCurrencySign;
      currentCurrencySign = currencySigns[code];
      return Util.renderUICurrencyFromJSON(Util.renderJSONCurrencyFromUI(uiCurrency));
    },
    renderUICurrencyFromJSON: function(code, jsonCurrency) {
      var currentCurrencySign;
      if (isNaN(jsonCurrency)) {
        jsonCurrency = 0;
      }
      currentCurrencySign = currencySigns[code];
      jsonCurrency = '' + jsonCurrency;
      if (isZeroDecimal(code)) {
        return currentCurrencySign + jsonCurrency;
      }
      while (jsonCurrency.length < 3) {
        jsonCurrency = '0' + jsonCurrency;
      }
      return currentCurrencySign + jsonCurrency.substr(0, jsonCurrency.length - 2) + '.' + jsonCurrency.substr(-2);
    },
    renderJSONCurrencyFromUI: function(code, uiCurrency) {
      var currentCurrencySign, parts;
      currentCurrencySign = currencySigns[code];
      if (isZeroDecimal(code)) {
        return parseInt(('' + uiCurrency).replace(digitsOnlyRe, '').replace(currencySeparator, ''), 10);
      }
      parts = uiCurrency.split(currencySeparator);
      if (parts.length > 1) {
        parts[1] = parts[1].substr(0, 2);
        while (parts[1].length < 2) {
          parts[1] += '0';
        }
      } else {
        parts[1] = '00';
      }
      return parseInt(parseFloat(parts[0].replace(digitsOnlyRe, '')) * 100 + parseFloat(parts[1].replace(digitsOnlyRe, '')), 10);
    }
  };
  
  
  
  },{"../data/currencies":30}],54:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var agent, ieMajor, ieMinor, matches, raf, reg;
  
  agent = navigator.userAgent;
  
  reg = /MSIE\s?(\d+)(?:\.(\d+))?/i;
  
  matches = agent.match(reg);
  
  if (matches != null) {
    ieMajor = matches[1];
    ieMinor = matches[2];
  }
  
  if (window.Promise == null) {
    window.Promise = require('broken');
  }
  
  raf = require('raf');
  
  if (window.requestAnimationFrame == null) {
    window.requestAnimationFrame = raf;
  }
  
  if (window.cancelAnimationFrame == null) {
    window.cancelAnimationFrame = raf.cancel;
  }
  
  module.exports = {
    ieVersion: {
      major: ieMajor,
      minor: ieMinor
    }
  };
  
  
  
  },{"broken":59,"raf":101}],55:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var hidePlaceholderOnFocus, unfocusOnAnElement;
  
  hidePlaceholderOnFocus = function(event) {
    var target;
    target = event.currentTarget ? event.currentTarget : event.srcElement;
    if (target.value === target.getAttribute('placeholder')) {
      return target.value = '';
    }
  };
  
  unfocusOnAnElement = function(event) {
    var target;
    target = event.currentTarget ? event.currentTarget : event.srcElement;
    if (target.value === '') {
      return target.value = target.getAttribute('placeholder');
    }
  };
  
  if (document.createElement("input").placeholder != null) {
    module.exports = function() {};
  } else {
    module.exports = function(input) {
      var ref;
      input = (ref = input[0]) != null ? ref : input;
      if (input._placeholdered != null) {
        return;
      }
      Object.defineProperty(input, '_placeholdered', {
        value: true,
        writable: true
      });
      if (!input.value) {
        input.value = input.getAttribute('placeholder');
      }
      if (input.addEventListener) {
        input.addEventListener('click', hidePlaceholderOnFocus, false);
        return input.addEventListener('blur', unfocusOnAnElement, false);
      } else if (input.attachEvent) {
        input.attachEvent('onclick', hidePlaceholderOnFocus);
        return input.attachEvent('onblur', unfocusOnAnElement);
      }
    };
  }
  
  
  
  },{}],56:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var cookie, store;
  
  store = require('store');
  
  cookie = require('js-cookie');
  
  if (store.enabled) {
    module.exports = store;
  } else {
    module.exports = {
      get: function(k) {
        var e, error, v;
        v = cookie.get(k);
        try {
          v = JSON.parse(v);
        } catch (error) {
          e = error;
        }
        return v;
      },
      set: function(k, v) {
        var keys, ref;
        keys = (ref = cookie.get('_keys')) != null ? ref : '';
        cookie.set('_keys', keys += ' ' + k);
        return cookie.set(k, JSON.stringify(v));
      },
      clear: function() {
        var i, k, keys, ks, len, ref;
        keys = (ref = cookie.get('_keys')) != null ? ref : '';
        ks = keys.split(' ');
        for (i = 0, len = ks.length; i < len; i++) {
          k = ks[i];
          cookie.remove(k);
        }
        return cookie.remove('_keys');
      }
    };
  }
  
  
  
  },{"js-cookie":100,"store":115}],57:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var CartCounterForm, CrowdControl,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  CrowdControl = require('crowdcontrol');
  
  require('../utils/patches');
  
  module.exports = CartCounterForm = (function(superClass) {
    extend(CartCounterForm, superClass);
  
    function CartCounterForm() {
      return CartCounterForm.__super__.constructor.apply(this, arguments);
    }
  
    CartCounterForm.prototype.tag = 'cart-counter';
  
    CartCounterForm.prototype.html = require('../templates/widgets/cart-counter');
  
    CartCounterForm.prototype.init = function() {
      return CartCounterForm.__super__.init.apply(this, arguments);
    };
  
    CartCounterForm.prototype.countItems = function() {
      var count, i, item, items, j, len;
      items = this.data.get('order.items');
      count = 0;
      for (i = j = 0, len = items.length; j < len; i = ++j) {
        item = items[i];
        count += item.quantity;
      }
      return count;
    };
  
    CartCounterForm.prototype.totalPrice = function() {
      var i, item, items, j, len, price;
      items = this.data.get('order.items');
      price = 0;
      for (i = j = 0, len = items.length; j < len; i = ++j) {
        item = items[i];
        price += item.price * item.quantity;
      }
      return price;
    };
  
    return CartCounterForm;
  
  })(CrowdControl.Views.View);
  
  
  
  },{"../templates/widgets/cart-counter":50,"../utils/patches":54,"crowdcontrol":64}],58:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  module.exports = {
    CartCounter: require('./cart-counter'),
    register: function() {
      return this.CartCounter.register();
    }
  };
  
  
  
  },{"./cart-counter":57}],59:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Promise, PromiseInspection;
  
  Promise = require('zousan');
  
  Promise.suppressUncaughtRejectionError = false;
  
  PromiseInspection = (function() {
    function PromiseInspection(arg) {
      this.state = arg.state, this.value = arg.value, this.reason = arg.reason;
    }
  
    PromiseInspection.prototype.isFulfilled = function() {
      return this.state === 'fulfilled';
    };
  
    PromiseInspection.prototype.isRejected = function() {
      return this.state === 'rejected';
    };
  
    return PromiseInspection;
  
  })();
  
  Promise.reflect = function(promise) {
    return new Promise(function(resolve, reject) {
      return promise.then(function(value) {
        return resolve(new PromiseInspection({
          state: 'fulfilled',
          value: value
        }));
      })["catch"](function(err) {
        return resolve(new PromiseInspection({
          state: 'rejected',
          reason: err
        }));
      });
    });
  };
  
  Promise.settle = function(promises) {
    return Promise.all(promises.map(Promise.reflect));
  };
  
  Promise.prototype.callback = function(cb) {
    if (typeof cb === 'function') {
      this.then(function(value) {
        return cb(null, value);
      });
      this["catch"](function(error) {
        return cb(error, null);
      });
    }
    return this;
  };
  
  module.exports = Promise;
  
  
  
  },{"zousan":60}],60:[function(require,module,exports){
  (function (global){
  !function(t){"use strict";function e(t){if(t){var e=this;t(function(t){e.resolve(t)},function(t){e.reject(t)})}}function n(t,e){if("function"==typeof t.y)try{var n=t.y.call(i,e);t.p.resolve(n)}catch(o){t.p.reject(o)}else t.p.resolve(e)}function o(t,e){if("function"==typeof t.n)try{var n=t.n.call(i,e);t.p.resolve(n)}catch(o){t.p.reject(o)}else t.p.reject(e)}var r,i,c="fulfilled",u="rejected",s="undefined",f=function(){function t(){for(;e.length-n;)e[n](),e[n++]=i,n==o&&(e.splice(0,o),n=0)}var e=[],n=0,o=1024,r=function(){if(typeof MutationObserver!==s){var e=document.createElement("div"),n=new MutationObserver(t);return n.observe(e,{attributes:!0}),function(){e.setAttribute("a",0)}}return typeof setImmediate!==s?function(){setImmediate(t)}:function(){setTimeout(t,0)}}();return function(t){e.push(t),e.length-n==1&&r()}}();e.prototype={resolve:function(t){if(this.state===r){if(t===this)return this.reject(new TypeError("Attempt to resolve promise with self"));var e=this;if(t&&("function"==typeof t||"object"==typeof t))try{var o=!0,i=t.then;if("function"==typeof i)return void i.call(t,function(t){o&&(o=!1,e.resolve(t))},function(t){o&&(o=!1,e.reject(t))})}catch(u){return void(o&&this.reject(u))}this.state=c,this.v=t,e.c&&f(function(){for(var o=0,r=e.c.length;r>o;o++)n(e.c[o],t)})}},reject:function(t){if(this.state===r){this.state=u,this.v=t;var n=this.c;n?f(function(){for(var e=0,r=n.length;r>e;e++)o(n[e],t)}):e.suppressUncaughtRejectionError||console.log("You upset Zousan. Please catch rejections: ",t,t.stack)}},then:function(t,i){var u=new e,s={y:t,n:i,p:u};if(this.state===r)this.c?this.c.push(s):this.c=[s];else{var l=this.state,a=this.v;f(function(){l===c?n(s,a):o(s,a)})}return u},"catch":function(t){return this.then(null,t)},"finally":function(t){return this.then(t,t)},timeout:function(t,n){n=n||"Timeout";var o=this;return new e(function(e,r){setTimeout(function(){r(Error(n))},t),o.then(function(t){e(t)},function(t){r(t)})})}},e.resolve=function(t){var n=new e;return n.resolve(t),n},e.reject=function(t){var n=new e;return n.reject(t),n},e.all=function(t){function n(n,c){"function"!=typeof n.then&&(n=e.resolve(n)),n.then(function(e){o[c]=e,r++,r==t.length&&i.resolve(o)},function(t){i.reject(t)})}for(var o=[],r=0,i=new e,c=0;c<t.length;c++)n(t[c],c);return t.length||i.resolve(o),i},typeof module!=s&&module.exports&&(module.exports=e),t.Zousan=e,e.soon=f}("undefined"!=typeof global?global:this);
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{}],61:[function(require,module,exports){
  arguments[4][51][0].apply(exports,arguments)
  },{"dup":51}],62:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Cart, Promise, analytics;
  
  analytics = require('./analytics');
  
  Promise = require('broken');
  
  Cart = (function() {
    Cart.prototype.waits = 0;
  
    Cart.prototype.queue = null;
  
    Cart.prototype.data = null;
  
    Cart.prototype.client = null;
  
    Cart.prototype.promise = null;
  
    Cart.prototype.reject = null;
  
    Cart.prototype.resolve = null;
  
    function Cart(client, data1) {
      this.client = client;
      this.data = data1;
      this.queue = [];
      this.invoice();
    }
  
    Cart.prototype.set = function(id, quantity, locked) {
      if (locked == null) {
        locked = false;
      }
      this.queue.push([id, quantity, locked]);
      if (this.queue.length === 1) {
        this.promise = new Promise((function(_this) {
          return function(resolve, reject) {
            _this.resolve = resolve;
            return _this.reject = reject;
          };
        })(this));
        this._set();
      }
      return this.promise;
    };
  
    Cart.prototype.get = function(id) {
      var i, item, items, j, k, len, len1, ref;
      items = this.data.get('order.items');
      for (i = j = 0, len = items.length; j < len; i = ++j) {
        item = items[i];
        if (item.id !== id && item.productId !== id && item.productSlug !== id) {
          continue;
        }
        return item;
      }
      ref = this.queue;
      for (i = k = 0, len1 = ref.length; k < len1; i = ++k) {
        item = ref[i];
        if (item[0] !== id) {
          continue;
        }
        return {
          id: item[0],
          quantity: item[2],
          locked: item[3]
        };
      }
    };
  
    Cart.prototype._set = function() {
      var deltaQuantity, i, id, item, items, j, k, len, len1, locked, newValue, oldValue, quantity, ref;
      items = this.data.get('order.items');
      if (this.queue.length === 0) {
        this.invoice();
        if (this.resolve != null) {
          this.resolve(items);
        }
        return;
      }
      ref = this.queue[0], id = ref[0], quantity = ref[1], locked = ref[2];
      if (quantity === 0) {
        for (i = j = 0, len = items.length; j < len; i = ++j) {
          item = items[i];
          if (item.productId === id || item.productSlug === id || item.id === id) {
            break;
          }
        }
        if (i < items.length) {
          this.data.set('order.items', []);
          items.splice(i, 1);
          this.onUpdate();
          analytics.track('Removed Product', {
            id: item.productId,
            sku: item.productSlug,
            name: item.productName,
            quantity: item.quantity,
            price: parseFloat(item.price / 100)
          });
          this.data.set('order.items', items);
          this.onUpdate(item);
        }
        this.queue.shift();
        this._set();
        return;
      }
      for (i = k = 0, len1 = items.length; k < len1; i = ++k) {
        item = items[i];
        if (item.id !== id && item.productId !== id && item.productSlug !== id) {
          continue;
        }
        oldValue = item.quantity;
        item.quantity = quantity;
        item.locked = locked;
        newValue = quantity;
        deltaQuantity = newValue - oldValue;
        if (deltaQuantity > 0) {
          analytics.track('Added Product', {
            id: item.productId,
            sku: item.productSlug,
            name: item.productName,
            quantity: deltaQuantity,
            price: parseFloat(item.price / 100)
          });
        } else if (deltaQuantity < 0) {
          analytics.track('Removed Product', {
            id: item.productId,
            sku: item.productSlug,
            name: item.productName,
            quantity: deltaQuantity,
            price: parseFloat(item.price / 100)
          });
        }
        this.data.set('order.items.' + i + '.quantity', quantity);
        this.data.set('order.items.' + i + '.locked', locked);
        this.onUpdate(item);
        this.queue.shift();
        this._set();
        return;
      }
      items.push({
        id: id,
        quantity: quantity,
        locked: locked
      });
      this.waits++;
      return this.load(id);
    };
  
    Cart.prototype.load = function(id) {
      var items;
      items = this.data.get('order.items');
      return this.client.product.get(id).then((function(_this) {
        return function(product) {
          var i, item, j, len;
          _this.waits--;
          for (i = j = 0, len = items.length; j < len; i = ++j) {
            item = items[i];
            if (product.id === item.id || product.slug === item.id) {
              analytics.track('Added Product', {
                id: product.id,
                sku: product.slug,
                name: product.name,
                quantity: item.quantity,
                price: parseFloat(product.price / 100)
              });
              _this.update(product, item);
              _this.data.set('order.items.' + i, item);
              break;
            }
          }
          _this.queue.shift();
          return _this._set();
        };
      })(this))["catch"]((function(_this) {
        return function(err) {
          _this.waits--;
          console.log("setItem Error: " + err);
          _this.queue.shift();
          return _this._set();
        };
      })(this));
    };
  
    Cart.prototype.refresh = function(id) {
      var items;
      items = this.data.get('order.items');
      return this.client.product.get(id).then((function(_this) {
        return function(product) {
          var i, item, j, len;
          _this.waits--;
          for (i = j = 0, len = items.length; j < len; i = ++j) {
            item = items[i];
            if (product.id === item.productId || product.slug === item.productSlug) {
              _this.update(product, item);
              break;
            }
          }
          return items;
        };
      })(this))["catch"](function(err) {
        return console.log("setItem Error: " + err);
      });
    };
  
    Cart.prototype.update = function(product, item) {
      delete item.id;
      item.productId = product.id;
      item.productSlug = product.slug;
      item.productName = product.name;
      item.price = product.price;
      item.listPrice = product.listPrice;
      item.description = product.description;
      return this.onUpdate(item);
    };
  
    Cart.prototype.onUpdate = function(item) {};
  
    Cart.prototype.promoCode = function(promoCode) {
      if (promoCode != null) {
        this.invoice();
        return this.client.coupon.get(promoCode).then((function(_this) {
          return function(coupon) {
            if (coupon.enabled) {
              _this.data.set('order.coupon', coupon);
              _this.data.set('order.couponCodes', [promoCode]);
              if (coupon.freeProductId !== "" && coupon.freeQuantity > 0) {
                return _this.client.product.get(coupon.freeProductId).then(function(freeProduct) {
                  return _this.invoice();
                })["catch"](function(err) {
                  throw new Error('This coupon is invalid.');
                });
              } else {
                _this.invoice();
              }
            } else {
              throw new Error('This code is expired.');
            }
          };
        })(this));
      }
      return this.data.get('order.promoCode');
    };
  
    Cart.prototype.taxRates = function(taxRates) {
      if (taxRates != null) {
        this.data.set('taxRates', taxRates);
        this.invoice();
      }
      return this.data.get('taxRates');
    };
  
    Cart.prototype.invoice = function() {
      var city, country, coupon, discount, item, items, j, k, l, len, len1, len2, len3, len4, m, n, ref, ref1, ref2, ref3, ref4, shipping, shippingRate, state, subtotal, tax, taxRate, taxRateFilter, taxRates;
      items = this.data.get('order.items');
      discount = 0;
      coupon = this.data.get('order.coupon');
      if (coupon != null) {
        switch (coupon.type) {
          case 'flat':
            if ((coupon.productId == null) || coupon.productId === '') {
              discount = coupon.amount || 0;
            } else {
              ref = this.data.get('order.items');
              for (j = 0, len = ref.length; j < len; j++) {
                item = ref[j];
                if (item.productId === coupon.productId) {
                  discount += (coupon.amount || 0) * item.quantity;
                }
              }
            }
            break;
          case 'percent':
            if ((coupon.productId == null) || coupon.productId === '') {
              ref1 = this.data.get('order.items');
              for (k = 0, len1 = ref1.length; k < len1; k++) {
                item = ref1[k];
                discount += (coupon.amount || 0) * item.price * item.quantity * 0.01;
              }
            } else {
              ref2 = this.data.get('order.items');
              for (l = 0, len2 = ref2.length; l < len2; l++) {
                item = ref2[l];
                if (item.productId === coupon.productId) {
                  discount += (coupon.amount || 0) * item.price * item.quantity * 0.01;
                }
              }
            }
            discount = Math.floor(discount);
        }
      }
      this.data.set('order.discount', discount);
      items = this.data.get('order.items');
      subtotal = -discount;
      for (m = 0, len3 = items.length; m < len3; m++) {
        item = items[m];
        subtotal += item.price * item.quantity;
      }
      this.data.set('order.subtotal', subtotal);
      taxRates = this.data.get('taxRates');
      if (taxRates != null) {
        for (n = 0, len4 = taxRates.length; n < len4; n++) {
          taxRateFilter = taxRates[n];
          city = this.data.get('order.shippingAddress.city');
          if (!city || ((taxRateFilter.city != null) && taxRateFilter.city.toLowerCase() !== city.toLowerCase())) {
            continue;
          }
          state = this.data.get('order.shippingAddress.state');
          if (!state || ((taxRateFilter.state != null) && taxRateFilter.state.toLowerCase() !== state.toLowerCase())) {
            continue;
          }
          country = this.data.get('order.shippingAddress.country');
          if (!country || ((taxRateFilter.country != null) && taxRateFilter.country.toLowerCase() !== country.toLowerCase())) {
            continue;
          }
          this.data.set('order.taxRate', taxRateFilter.taxRate);
          break;
        }
      }
      taxRate = (ref3 = this.data.get('order.taxRate')) != null ? ref3 : 0;
      tax = Math.ceil((taxRate != null ? taxRate : 0) * subtotal);
      shippingRate = (ref4 = this.data.get('order.shippingRate')) != null ? ref4 : 0;
      shipping = shippingRate;
      this.data.set('order.shipping', shipping);
      this.data.set('order.tax', tax);
      return this.data.set('order.total', subtotal + shipping + tax);
    };
  
    Cart.prototype.checkout = function() {
      var data;
      this.invoice();
      data = {
        user: this.data.get('user'),
        order: this.data.get('order'),
        payment: this.data.get('payment')
      };
      return this.client.checkout.authorize(data).then((function(_this) {
        return function(order) {
          var i, item, j, len, options, p, ref, referralProgram;
          _this.data.set('coupon', _this.data.get('order.coupon') || {});
          _this.data.set('order', order);
          p = _this.client.checkout.capture(order.id).then(function(order) {
            _this.data.set('order', order);
            return order;
          })["catch"](function(err) {
            var ref;
            if (typeof window !== "undefined" && window !== null) {
              if ((ref = window.Raven) != null) {
                ref.captureException(err);
              }
            }
            return console.log("capture Error: " + err);
          });
          referralProgram = _this.data.get('referralProgram');
          if (referralProgram != null) {
            _this.client.referrer.create({
              userId: data.order.userId,
              orderId: data.order.orderId,
              program: referralProgram
            }).then(function(referrer) {
              return _this.data.set('referrerId', referrer.id);
            })["catch"](function(err) {
              var ref;
              if (typeof window !== "undefined" && window !== null) {
                if ((ref = window.Raven) != null) {
                  ref.captureException(err);
                }
              }
              return console.log("new referralProgram Error: " + err);
            });
          }
          options = {
            orderId: _this.data.get('order.id'),
            total: parseFloat(_this.data.get('order.total') / 100),
            shipping: parseFloat(_this.data.get('order.shipping') / 100),
            tax: parseFloat(_this.data.get('order.tax') / 100),
            discount: parseFloat(_this.data.get('order.discount') / 100),
            coupon: _this.data.get('order.couponCodes.0') || '',
            currency: _this.data.get('order.currency'),
            products: []
          };
          ref = _this.data.get('order.items');
          for (i = j = 0, len = ref.length; j < len; i = ++j) {
            item = ref[i];
            options.products[i] = {
              id: item.productId,
              sku: item.productSlug,
              name: item.productName,
              quantity: item.quantity,
              price: parseFloat(item.price / 100)
            };
          }
          analytics.track('Completed Order', options);
          return {
            p: p
          };
        };
      })(this));
    };
  
    return Cart;
  
  })();
  
  module.exports = Cart;
  
  
  
  },{"./analytics":61,"broken":59}],63:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  module.exports = {
    Cart: require('./cart')
  };
  
  
  
  },{"./cart":62}],64:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var CrowdControl, r, riot;
  
  r = require('./riot');
  
  riot = r();
  
  CrowdControl = {
    Views: require('./views'),
    tags: [],
    start: function(opts) {
      return this.tags = riot.mount('*', opts);
    },
    update: function() {
      var i, len, ref, results, tag;
      ref = this.tags;
      results = [];
      for (i = 0, len = ref.length; i < len; i++) {
        tag = ref[i];
        results.push(tag.update());
      }
      return results;
    },
    riot: r
  };
  
  if (module.exports != null) {
    module.exports = CrowdControl;
  }
  
  if (typeof window !== "undefined" && window !== null) {
    if (window.Crowdstart != null) {
      window.Crowdstart.Crowdcontrol = CrowdControl;
    } else {
      window.Crowdstart = {
        CrowdControl: CrowdControl
      };
    }
  }
  
  
  
  },{"./riot":65,"./views":67}],65:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var r;
  
  r = function() {
    return this.riot;
  };
  
  r.set = function(riot) {
    this.riot = riot;
  };
  
  r.riot = typeof window !== "undefined" && window !== null ? window.riot : void 0;
  
  module.exports = r;
  
  
  
  },{}],66:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Form, Promise, View, inputify, observable, settle,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  View = require('./view');
  
  inputify = require('./inputify');
  
  observable = require('../riot')().observable;
  
  Promise = require('broken');
  
  settle = require('promise-settle');
  
  Form = (function(superClass) {
    extend(Form, superClass);
  
    function Form() {
      return Form.__super__.constructor.apply(this, arguments);
    }
  
    Form.prototype.configs = null;
  
    Form.prototype.inputs = null;
  
    Form.prototype.data = null;
  
    Form.prototype.initInputs = function() {
      var input, name, ref, results1;
      this.inputs = {};
      if (this.configs != null) {
        this.inputs = inputify(this.data, this.configs);
        ref = this.inputs;
        results1 = [];
        for (name in ref) {
          input = ref[name];
          results1.push(observable(input));
        }
        return results1;
      }
    };
  
    Form.prototype.init = function() {
      return this.initInputs();
    };
  
    Form.prototype.submit = function() {
      var input, name, pRef, ps, ref;
      ps = [];
      ref = this.inputs;
      for (name in ref) {
        input = ref[name];
        pRef = {};
        input.trigger('validate', pRef);
        ps.push(pRef.p);
      }
      return settle(ps).then((function(_this) {
        return function(results) {
          var i, len, result;
          for (i = 0, len = results.length; i < len; i++) {
            result = results[i];
            if (!result.isFulfilled()) {
              return;
            }
          }
          return _this._submit.apply(_this, arguments);
        };
      })(this));
    };
  
    Form.prototype._submit = function() {};
  
    return Form;
  
  })(View);
  
  module.exports = Form;
  
  
  
  },{"../riot":65,"./inputify":69,"./view":70,"broken":59,"promise-settle":73}],67:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  module.exports = {
    Form: require('./form'),
    Input: require('./input'),
    View: require('./view')
  };
  
  
  
  },{"./form":66,"./input":68,"./view":70}],68:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Input, View,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  View = require('./view');
  
  Input = (function(superClass) {
    extend(Input, superClass);
  
    function Input() {
      return Input.__super__.constructor.apply(this, arguments);
    }
  
    Input.prototype.input = null;
  
    Input.prototype.errorMessage = '';
  
    Input.prototype.errorHtml = '<div class="error-container" if="{ errorMessage }">\n  <div class="error-message">{ errorMessage }</div>\n</div>';
  
    Input.prototype.beforeInit = function() {
      return this.html += this.errorHtml;
    };
  
    Input.prototype.init = function() {
      return this.input.on('validate', (function(_this) {
        return function(pRef) {
          return _this.validate(pRef);
        };
      })(this));
    };
  
    Input.prototype.getValue = function(event) {
      return event.target.value;
    };
  
    Input.prototype.change = function(event) {
      var name, ref, ref1, value;
      ref1 = this.input, ref = ref1.ref, name = ref1.name;
      value = this.getValue(event);
      if (value === ref.get(name)) {
        return;
      }
      this.input.ref.set(name, value);
      this.clearError();
      return this.validate();
    };
  
    Input.prototype.error = function(err) {
      var ref1;
      return this.errorMessage = (ref1 = err != null ? err.message : void 0) != null ? ref1 : err;
    };
  
    Input.prototype.changed = function() {};
  
    Input.prototype.clearError = function() {
      return this.errorMessage = '';
    };
  
    Input.prototype.validate = function(pRef) {
      var p;
      p = this.input.validate(this.input.ref, this.input.name).then((function(_this) {
        return function(value) {
          _this.changed(value);
          return _this.update();
        };
      })(this))["catch"]((function(_this) {
        return function(err) {
          _this.error(err);
          _this.update();
          throw err;
        };
      })(this));
      if (pRef != null) {
        pRef.p = p;
      }
      return p;
    };
  
    return Input;
  
  })(View);
  
  module.exports = Input;
  
  
  
  },{"./view":70}],69:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Promise, inputify, isFunction, isRef, refer;
  
  Promise = require('broken');
  
  isFunction = require('is-function');
  
  refer = require('referential');
  
  isRef = function(o) {
    return (o != null) && isFunction(o.ref);
  };
  
  inputify = function(data, configs) {
    var config, fn, inputs, name, ref;
    ref = data;
    if (!isRef(ref)) {
      ref = refer(data);
    }
    inputs = {};
    fn = function(name, config) {
      var fn1, i, input, len, middleware, middlewareFn, validate;
      middleware = [];
      if (config && config.length > 0) {
        fn1 = function(name, middlewareFn) {
          return middleware.push(function(pair) {
            ref = pair[0], name = pair[1];
            return Promise.resolve(pair).then(function(pair) {
              return middlewareFn.call(pair[0], pair[0].get(pair[1]), pair[1], pair[0]);
            }).then(function(v) {
              ref.set(name, v);
              return pair;
            });
          });
        };
        for (i = 0, len = config.length; i < len; i++) {
          middlewareFn = config[i];
          fn1(name, middlewareFn);
        }
      }
      middleware.push(function(pair) {
        ref = pair[0], name = pair[1];
        return Promise.resolve(ref.get(name));
      });
      validate = function(ref, name) {
        var j, len1, p;
        p = Promise.resolve([ref, name]);
        for (j = 0, len1 = middleware.length; j < len1; j++) {
          middlewareFn = middleware[j];
          p = p.then(middlewareFn);
        }
        return p;
      };
      input = {
        name: name,
        ref: ref,
        config: config,
        validate: validate
      };
      return inputs[name] = input;
    };
    for (name in configs) {
      config = configs[name];
      fn(name, config);
    }
    return inputs;
  };
  
  module.exports = inputify;
  
  
  
  },{"broken":59,"is-function":71,"referential":75}],70:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var View, collapsePrototype, isFunction, objectAssign, riot, setPrototypeOf;
  
  riot = require('../riot')();
  
  objectAssign = require('object-assign');
  
  setPrototypeOf = (function() {
    var mixinProperties, setProtoOf;
    setProtoOf = function(obj, proto) {
      return obj.__proto__ = proto;
    };
    mixinProperties = function(obj, proto) {
      var prop, results;
      results = [];
      for (prop in proto) {
        if (obj[prop] == null) {
          results.push(obj[prop] = proto[prop]);
        } else {
          results.push(void 0);
        }
      }
      return results;
    };
    if (Object.setPrototypeOf || {
      __proto__: []
    } instanceof Array) {
      return setProtoOf;
    } else {
      return mixinProperties;
    }
  })();
  
  isFunction = require('is-function');
  
  collapsePrototype = function(collapse, proto) {
    var parentProto;
    if (proto === View.prototype) {
      return;
    }
    parentProto = Object.getPrototypeOf(proto);
    collapsePrototype(collapse, parentProto);
    return objectAssign(collapse, parentProto);
  };
  
  View = (function() {
    View.register = function() {
      return new this;
    };
  
    View.prototype.tag = '';
  
    View.prototype.html = '';
  
    View.prototype.css = '';
  
    View.prototype.attrs = '';
  
    View.prototype.events = null;
  
    function View() {
      var newProto;
      newProto = collapsePrototype({}, this);
      this.beforeInit();
      riot.tag(this.tag, this.html, this.css, this.attrs, function(opts) {
        var fn, handler, k, name, parent, proto, ref, self, v;
        if (newProto != null) {
          for (k in newProto) {
            v = newProto[k];
            if (isFunction(v)) {
              (function(_this) {
                return (function(v) {
                  var oldFn;
                  if (_this[k] != null) {
                    oldFn = _this[k];
                    return _this[k] = function() {
                      oldFn.apply(_this, arguments);
                      return v.apply(_this, arguments);
                    };
                  } else {
                    return _this[k] = function() {
                      return v.apply(_this, arguments);
                    };
                  }
                });
              })(this)(v);
            } else {
              this[k] = v;
            }
          }
        }
        self = this;
        parent = self.parent;
        proto = Object.getPrototypeOf(self);
        while ((parent != null) && parent !== proto) {
          setPrototypeOf(self, parent);
          self = parent;
          parent = self.parent;
          proto = Object.getPrototypeOf(self);
        }
        if (opts != null) {
          for (k in opts) {
            v = opts[k];
            this[k] = v;
          }
        }
        if (this.events != null) {
          ref = this.events;
          fn = (function(_this) {
            return function(name, handler) {
              if (typeof handler === 'string') {
                return _this.on(name, function() {
                  return _this[handler].apply(_this, arguments);
                });
              } else {
                return _this.on(name, function() {
                  return handler.apply(_this, arguments);
                });
              }
            };
          })(this);
          for (name in ref) {
            handler = ref[name];
            fn(name, handler);
          }
        }
        return this.init(opts);
      });
    }
  
    View.prototype.beforeInit = function() {};
  
    View.prototype.init = function() {};
  
    return View;
  
  })();
  
  module.exports = View;
  
  
  
  },{"../riot":65,"is-function":71,"object-assign":72}],71:[function(require,module,exports){
  module.exports = isFunction
  
  var toString = Object.prototype.toString
  
  function isFunction (fn) {
    var string = toString.call(fn)
    return string === '[object Function]' ||
      (typeof fn === 'function' && string !== '[object RegExp]') ||
      (typeof window !== 'undefined' &&
       // IE8 and below
       (fn === window.setTimeout ||
        fn === window.alert ||
        fn === window.confirm ||
        fn === window.prompt))
  };
  
  },{}],72:[function(require,module,exports){
  /* eslint-disable no-unused-vars */
  'use strict';
  var hasOwnProperty = Object.prototype.hasOwnProperty;
  var propIsEnumerable = Object.prototype.propertyIsEnumerable;
  
  function toObject(val) {
  	if (val === null || val === undefined) {
  		throw new TypeError('Object.assign cannot be called with null or undefined');
  	}
  
  	return Object(val);
  }
  
  module.exports = Object.assign || function (target, source) {
  	var from;
  	var to = toObject(target);
  	var symbols;
  
  	for (var s = 1; s < arguments.length; s++) {
  		from = Object(arguments[s]);
  
  		for (var key in from) {
  			if (hasOwnProperty.call(from, key)) {
  				to[key] = from[key];
  			}
  		}
  
  		if (Object.getOwnPropertySymbols) {
  			symbols = Object.getOwnPropertySymbols(from);
  			for (var i = 0; i < symbols.length; i++) {
  				if (propIsEnumerable.call(from, symbols[i])) {
  					to[symbols[i]] = from[symbols[i]];
  				}
  			}
  		}
  	}
  
  	return to;
  };
  
  },{}],73:[function(require,module,exports){
  'use strict';
  
  module.exports = require('./lib/promise-settle');
  
  },{"./lib/promise-settle":74}],74:[function(require,module,exports){
  'use strict';
  
  module.exports = settle;
  
  function settle(promises) {
    return Promise.resolve()
      .then(function () {
        return promises;
      })
      .then(function (promises) {
        if (!Array.isArray(promises)) throw new TypeError('Expected an array of Promises');
  
        var promiseResults = promises.map(function (promise) {
          return Promise.resolve()
            .then(function () {
              return promise;
            })
            .then(function (result) {
              return promiseResult(result);
            })
            .catch(function (err) {
              return promiseResult(null, err);
            });
        });
  
        return Promise.all(promiseResults);
      });
  }
  
  function promiseResult(result, err) {
    var isFulfilled = (typeof err === 'undefined');
    var value = isFulfilled
      ? returns.bind(result)
      : throws.bind(new Error('Promise is rejected'));
  
    var isRejected = !isFulfilled;
    var reason = isRejected
      ? returns.bind(err)
      : throws.bind(new Error('Promise is fulfilled'));
  
    return {
      isFulfilled: returns.bind(isFulfilled),
      isRejected: returns.bind(isRejected),
      value: value,
      reason: reason
    };
  }
  
  function returns() {
    return this;
  }
  
  function throws() {
    throw this;
  }
  
  },{}],75:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var refer;
  
  refer = require('./refer');
  
  refer.Ref = require('./ref');
  
  module.exports = refer;
  
  
  
  },{"./ref":76,"./refer":77}],76:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Ref, extend, isArray, isNumber, isObject, isString;
  
  extend = require('node.extend');
  
  isArray = require('is-array');
  
  isNumber = require('is-number');
  
  isObject = require('is-object');
  
  isString = require('is-string');
  
  module.exports = Ref = (function() {
    function Ref(_value, parent, key1) {
      this._value = _value;
      this.parent = parent;
      this.key = key1;
      this._cache = {};
    }
  
    Ref.prototype._mutate = function() {
      return this._cache = {};
    };
  
    Ref.prototype.value = function(state) {
      if (!this.parent) {
        if (state != null) {
          this._value = state;
        }
        return this._value;
      }
      if (state != null) {
        return this.parent.set(this.key, state);
      } else {
        return this.parent.get(this.key);
      }
    };
  
    Ref.prototype.ref = function(key) {
      if (!key) {
        return this;
      }
      return new Ref(null, this, key);
    };
  
    Ref.prototype.get = function(key) {
      if (!key) {
        return this.value();
      } else {
        if (this._cache[key]) {
          return this._cache[key];
        }
        return this._cache[key] = this.index(key);
      }
    };
  
    Ref.prototype.set = function(key, value) {
      this._mutate();
      if (value == null) {
        this.value(extend(this.value(), key));
      } else {
        this.index(key, value);
      }
      return this;
    };
  
    Ref.prototype.extend = function(key, value) {
      var clone;
      this._mutate();
      if (value == null) {
        this.value(extend(true, this.value(), key));
      } else {
        if (isObject(value)) {
          this.value(extend(true, (this.ref(key)).get(), value));
        } else {
          clone = this.clone();
          this.set(key, value);
          this.value(extend(true, clone.get(), this.value()));
        }
      }
      return this;
    };
  
    Ref.prototype.clone = function(key) {
      return new Ref(extend(true, {}, this.get(key)));
    };
  
    Ref.prototype.index = function(key, value, obj, prev) {
      var next, prop, props;
      if (obj == null) {
        obj = this.value();
      }
      if (this.parent) {
        return this.parent.index(this.key + '.' + key, value);
      }
      if (isNumber(key)) {
        key = String(key);
      }
      props = key.split('.');
      if (value == null) {
        while (prop = props.shift()) {
          if (!props.length) {
            return obj != null ? obj[prop] : void 0;
          }
          obj = obj != null ? obj[prop] : void 0;
        }
        return;
      }
      while (prop = props.shift()) {
        if (!props.length) {
          return obj[prop] = value;
        } else {
          next = props[0];
          if (obj[next] == null) {
            if (isNumber(next)) {
              if (obj[prop] == null) {
                obj[prop] = [];
              }
            } else {
              if (obj[prop] == null) {
                obj[prop] = {};
              }
            }
          }
        }
        obj = obj[prop];
      }
    };
  
    return Ref;
  
  })();
  
  
  
  },{"is-array":78,"is-number":79,"is-object":99,"is-string":82,"node.extend":83}],77:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Ref, refer;
  
  Ref = require('./ref');
  
  module.exports = refer = function(state, ref) {
    var fn, i, len, method, ref1, wrapper;
    if (ref == null) {
      ref = null;
    }
    if (ref == null) {
      ref = new Ref(state);
    }
    wrapper = function(key) {
      return ref.get(key);
    };
    ref1 = ['value', 'get', 'set', 'extend', 'index', 'ref'];
    fn = function(method) {
      return wrapper[method] = function() {
        return ref[method].apply(ref, arguments);
      };
    };
    for (i = 0, len = ref1.length; i < len; i++) {
      method = ref1[i];
      fn(method);
    }
    wrapper.refer = function(key) {
      return refer(null, ref.ref(key));
    };
    wrapper.clone = function(key) {
      return refer(null, ref.clone(key));
    };
    return wrapper;
  };
  
  
  
  },{"./ref":76}],78:[function(require,module,exports){
  
  /**
   * isArray
   */
  
  var isArray = Array.isArray;
  
  /**
   * toString
   */
  
  var str = Object.prototype.toString;
  
  /**
   * Whether or not the given `val`
   * is an array.
   *
   * example:
   *
   *        isArray([]);
   *        // > true
   *        isArray(arguments);
   *        // > false
   *        isArray('');
   *        // > false
   *
   * @param {mixed} val
   * @return {bool}
   */
  
  module.exports = isArray || function (val) {
    return !! val && '[object Array]' == str.call(val);
  };
  
  },{}],79:[function(require,module,exports){
  /*!
   * is-number <https://github.com/jonschlinkert/is-number>
   *
   * Copyright (c) 2014-2015, Jon Schlinkert.
   * Licensed under the MIT License.
   */
  
  'use strict';
  
  var typeOf = require('kind-of');
  
  module.exports = function isNumber(num) {
    var type = typeOf(num);
    if (type !== 'number' && type !== 'string') {
      return false;
    }
    var n = +num;
    return (n - n + 1) >= 0 && num !== '';
  };
  
  },{"kind-of":80}],80:[function(require,module,exports){
  (function (Buffer){
  var isBuffer = require('is-buffer');
  var toString = Object.prototype.toString;
  
  /**
   * Get the native `typeof` a value.
   *
   * @param  {*} `val`
   * @return {*} Native javascript type
   */
  
  module.exports = function kindOf(val) {
    // primitivies
    if (typeof val === 'undefined') {
      return 'undefined';
    }
    if (val === null) {
      return 'null';
    }
    if (val === true || val === false || val instanceof Boolean) {
      return 'boolean';
    }
    if (typeof val === 'string' || val instanceof String) {
      return 'string';
    }
    if (typeof val === 'number' || val instanceof Number) {
      return 'number';
    }
  
    // functions
    if (typeof val === 'function' || val instanceof Function) {
      return 'function';
    }
  
    // array
    if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) {
      return 'array';
    }
  
    // check for instances of RegExp and Date before calling `toString`
    if (val instanceof RegExp) {
      return 'regexp';
    }
    if (val instanceof Date) {
      return 'date';
    }
  
    // other objects
    var type = toString.call(val);
  
    if (type === '[object RegExp]') {
      return 'regexp';
    }
    if (type === '[object Date]') {
      return 'date';
    }
    if (type === '[object Arguments]') {
      return 'arguments';
    }
  
    // buffer
    if (typeof Buffer !== 'undefined' && isBuffer(val)) {
      return 'buffer';
    }
  
    // es6: Map, WeakMap, Set, WeakSet
    if (type === '[object Set]') {
      return 'set';
    }
    if (type === '[object WeakSet]') {
      return 'weakset';
    }
    if (type === '[object Map]') {
      return 'map';
    }
    if (type === '[object WeakMap]') {
      return 'weakmap';
    }
    if (type === '[object Symbol]') {
      return 'symbol';
    }
  
    // typed arrays
    if (type === '[object Int8Array]') {
      return 'int8array';
    }
    if (type === '[object Uint8Array]') {
      return 'uint8array';
    }
    if (type === '[object Uint8ClampedArray]') {
      return 'uint8clampedarray';
    }
    if (type === '[object Int16Array]') {
      return 'int16array';
    }
    if (type === '[object Uint16Array]') {
      return 'uint16array';
    }
    if (type === '[object Int32Array]') {
      return 'int32array';
    }
    if (type === '[object Uint32Array]') {
      return 'uint32array';
    }
    if (type === '[object Float32Array]') {
      return 'float32array';
    }
    if (type === '[object Float64Array]') {
      return 'float64array';
    }
  
    // must be a plain object
    return 'object';
  };
  
  }).call(this,require("buffer").Buffer)
  },{"buffer":116,"is-buffer":81}],81:[function(require,module,exports){
  /**
   * Determine if an object is Buffer
   *
   * Author:   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
   * License:  MIT
   *
   * `npm install is-buffer`
   */
  
  module.exports = function (obj) {
    return !!(obj != null &&
      (obj._isBuffer || // For Safari 5-7 (missing Object.prototype.constructor)
        (obj.constructor &&
        typeof obj.constructor.isBuffer === 'function' &&
        obj.constructor.isBuffer(obj))
      ))
  }
  
  },{}],82:[function(require,module,exports){
  'use strict';
  
  var strValue = String.prototype.valueOf;
  var tryStringObject = function tryStringObject(value) {
  	try {
  		strValue.call(value);
  		return true;
  	} catch (e) {
  		return false;
  	}
  };
  var toStr = Object.prototype.toString;
  var strClass = '[object String]';
  var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
  
  module.exports = function isString(value) {
  	if (typeof value === 'string') { return true; }
  	if (typeof value !== 'object') { return false; }
  	return hasToStringTag ? tryStringObject(value) : toStr.call(value) === strClass;
  };
  
  },{}],83:[function(require,module,exports){
  module.exports = require('./lib/extend');
  
  
  },{"./lib/extend":84}],84:[function(require,module,exports){
  /*!
   * node.extend
   * Copyright 2011, John Resig
   * Dual licensed under the MIT or GPL Version 2 licenses.
   * http://jquery.org/license
   *
   * @fileoverview
   * Port of jQuery.extend that actually works on node.js
   */
  var is = require('is');
  
  function extend() {
    var target = arguments[0] || {};
    var i = 1;
    var length = arguments.length;
    var deep = false;
    var options, name, src, copy, copy_is_array, clone;
  
    // Handle a deep copy situation
    if (typeof target === 'boolean') {
      deep = target;
      target = arguments[1] || {};
      // skip the boolean and the target
      i = 2;
    }
  
    // Handle case when target is a string or something (possible in deep copy)
    if (typeof target !== 'object' && !is.fn(target)) {
      target = {};
    }
  
    for (; i < length; i++) {
      // Only deal with non-null/undefined values
      options = arguments[i]
      if (options != null) {
        if (typeof options === 'string') {
            options = options.split('');
        }
        // Extend the base object
        for (name in options) {
          src = target[name];
          copy = options[name];
  
          // Prevent never-ending loop
          if (target === copy) {
            continue;
          }
  
          // Recurse if we're merging plain objects or arrays
          if (deep && copy && (is.hash(copy) || (copy_is_array = is.array(copy)))) {
            if (copy_is_array) {
              copy_is_array = false;
              clone = src && is.array(src) ? src : [];
            } else {
              clone = src && is.hash(src) ? src : {};
            }
  
            // Never move original objects, clone them
            target[name] = extend(deep, clone, copy);
  
          // Don't bring in undefined values
          } else if (typeof copy !== 'undefined') {
            target[name] = copy;
          }
        }
      }
    }
  
    // Return the modified object
    return target;
  };
  
  /**
   * @public
   */
  extend.version = '1.1.3';
  
  /**
   * Exports module.
   */
  module.exports = extend;
  
  
  },{"is":85}],85:[function(require,module,exports){
  /* globals window, HTMLElement */
  /**!
   * is
   * the definitive JavaScript type testing library
   *
   * @copyright 2013-2014 Enrico Marino / Jordan Harband
   * @license MIT
   */
  
  var objProto = Object.prototype;
  var owns = objProto.hasOwnProperty;
  var toStr = objProto.toString;
  var symbolValueOf;
  if (typeof Symbol === 'function') {
    symbolValueOf = Symbol.prototype.valueOf;
  }
  var isActualNaN = function (value) {
    return value !== value;
  };
  var NON_HOST_TYPES = {
    'boolean': 1,
    number: 1,
    string: 1,
    undefined: 1
  };
  
  var base64Regex = /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$/;
  var hexRegex = /^[A-Fa-f0-9]+$/;
  
  /**
   * Expose `is`
   */
  
  var is = module.exports = {};
  
  /**
   * Test general.
   */
  
  /**
   * is.type
   * Test if `value` is a type of `type`.
   *
   * @param {Mixed} value value to test
   * @param {String} type type
   * @return {Boolean} true if `value` is a type of `type`, false otherwise
   * @api public
   */
  
  is.a = is.type = function (value, type) {
    return typeof value === type;
  };
  
  /**
   * is.defined
   * Test if `value` is defined.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if 'value' is defined, false otherwise
   * @api public
   */
  
  is.defined = function (value) {
    return typeof value !== 'undefined';
  };
  
  /**
   * is.empty
   * Test if `value` is empty.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is empty, false otherwise
   * @api public
   */
  
  is.empty = function (value) {
    var type = toStr.call(value);
    var key;
  
    if (type === '[object Array]' || type === '[object Arguments]' || type === '[object String]') {
      return value.length === 0;
    }
  
    if (type === '[object Object]') {
      for (key in value) {
        if (owns.call(value, key)) { return false; }
      }
      return true;
    }
  
    return !value;
  };
  
  /**
   * is.equal
   * Test if `value` is equal to `other`.
   *
   * @param {Mixed} value value to test
   * @param {Mixed} other value to compare with
   * @return {Boolean} true if `value` is equal to `other`, false otherwise
   */
  
  is.equal = function equal(value, other) {
    if (value === other) {
      return true;
    }
  
    var type = toStr.call(value);
    var key;
  
    if (type !== toStr.call(other)) {
      return false;
    }
  
    if (type === '[object Object]') {
      for (key in value) {
        if (!is.equal(value[key], other[key]) || !(key in other)) {
          return false;
        }
      }
      for (key in other) {
        if (!is.equal(value[key], other[key]) || !(key in value)) {
          return false;
        }
      }
      return true;
    }
  
    if (type === '[object Array]') {
      key = value.length;
      if (key !== other.length) {
        return false;
      }
      while (--key) {
        if (!is.equal(value[key], other[key])) {
          return false;
        }
      }
      return true;
    }
  
    if (type === '[object Function]') {
      return value.prototype === other.prototype;
    }
  
    if (type === '[object Date]') {
      return value.getTime() === other.getTime();
    }
  
    return false;
  };
  
  /**
   * is.hosted
   * Test if `value` is hosted by `host`.
   *
   * @param {Mixed} value to test
   * @param {Mixed} host host to test with
   * @return {Boolean} true if `value` is hosted by `host`, false otherwise
   * @api public
   */
  
  is.hosted = function (value, host) {
    var type = typeof host[value];
    return type === 'object' ? !!host[value] : !NON_HOST_TYPES[type];
  };
  
  /**
   * is.instance
   * Test if `value` is an instance of `constructor`.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is an instance of `constructor`
   * @api public
   */
  
  is.instance = is['instanceof'] = function (value, constructor) {
    return value instanceof constructor;
  };
  
  /**
   * is.nil / is.null
   * Test if `value` is null.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is null, false otherwise
   * @api public
   */
  
  is.nil = is['null'] = function (value) {
    return value === null;
  };
  
  /**
   * is.undef / is.undefined
   * Test if `value` is undefined.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is undefined, false otherwise
   * @api public
   */
  
  is.undef = is.undefined = function (value) {
    return typeof value === 'undefined';
  };
  
  /**
   * Test arguments.
   */
  
  /**
   * is.args
   * Test if `value` is an arguments object.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is an arguments object, false otherwise
   * @api public
   */
  
  is.args = is.arguments = function (value) {
    var isStandardArguments = toStr.call(value) === '[object Arguments]';
    var isOldArguments = !is.array(value) && is.arraylike(value) && is.object(value) && is.fn(value.callee);
    return isStandardArguments || isOldArguments;
  };
  
  /**
   * Test array.
   */
  
  /**
   * is.array
   * Test if 'value' is an array.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is an array, false otherwise
   * @api public
   */
  
  is.array = Array.isArray || function (value) {
    return toStr.call(value) === '[object Array]';
  };
  
  /**
   * is.arguments.empty
   * Test if `value` is an empty arguments object.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is an empty arguments object, false otherwise
   * @api public
   */
  is.args.empty = function (value) {
    return is.args(value) && value.length === 0;
  };
  
  /**
   * is.array.empty
   * Test if `value` is an empty array.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is an empty array, false otherwise
   * @api public
   */
  is.array.empty = function (value) {
    return is.array(value) && value.length === 0;
  };
  
  /**
   * is.arraylike
   * Test if `value` is an arraylike object.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is an arguments object, false otherwise
   * @api public
   */
  
  is.arraylike = function (value) {
    return !!value && !is.bool(value)
      && owns.call(value, 'length')
      && isFinite(value.length)
      && is.number(value.length)
      && value.length >= 0;
  };
  
  /**
   * Test boolean.
   */
  
  /**
   * is.bool
   * Test if `value` is a boolean.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is a boolean, false otherwise
   * @api public
   */
  
  is.bool = is['boolean'] = function (value) {
    return toStr.call(value) === '[object Boolean]';
  };
  
  /**
   * is.false
   * Test if `value` is false.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is false, false otherwise
   * @api public
   */
  
  is['false'] = function (value) {
    return is.bool(value) && Boolean(Number(value)) === false;
  };
  
  /**
   * is.true
   * Test if `value` is true.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is true, false otherwise
   * @api public
   */
  
  is['true'] = function (value) {
    return is.bool(value) && Boolean(Number(value)) === true;
  };
  
  /**
   * Test date.
   */
  
  /**
   * is.date
   * Test if `value` is a date.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is a date, false otherwise
   * @api public
   */
  
  is.date = function (value) {
    return toStr.call(value) === '[object Date]';
  };
  
  /**
   * Test element.
   */
  
  /**
   * is.element
   * Test if `value` is an html element.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is an HTML Element, false otherwise
   * @api public
   */
  
  is.element = function (value) {
    return value !== undefined
      && typeof HTMLElement !== 'undefined'
      && value instanceof HTMLElement
      && value.nodeType === 1;
  };
  
  /**
   * Test error.
   */
  
  /**
   * is.error
   * Test if `value` is an error object.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is an error object, false otherwise
   * @api public
   */
  
  is.error = function (value) {
    return toStr.call(value) === '[object Error]';
  };
  
  /**
   * Test function.
   */
  
  /**
   * is.fn / is.function (deprecated)
   * Test if `value` is a function.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is a function, false otherwise
   * @api public
   */
  
  is.fn = is['function'] = function (value) {
    var isAlert = typeof window !== 'undefined' && value === window.alert;
    return isAlert || toStr.call(value) === '[object Function]';
  };
  
  /**
   * Test number.
   */
  
  /**
   * is.number
   * Test if `value` is a number.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is a number, false otherwise
   * @api public
   */
  
  is.number = function (value) {
    return toStr.call(value) === '[object Number]';
  };
  
  /**
   * is.infinite
   * Test if `value` is positive or negative infinity.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is positive or negative Infinity, false otherwise
   * @api public
   */
  is.infinite = function (value) {
    return value === Infinity || value === -Infinity;
  };
  
  /**
   * is.decimal
   * Test if `value` is a decimal number.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is a decimal number, false otherwise
   * @api public
   */
  
  is.decimal = function (value) {
    return is.number(value) && !isActualNaN(value) && !is.infinite(value) && value % 1 !== 0;
  };
  
  /**
   * is.divisibleBy
   * Test if `value` is divisible by `n`.
   *
   * @param {Number} value value to test
   * @param {Number} n dividend
   * @return {Boolean} true if `value` is divisible by `n`, false otherwise
   * @api public
   */
  
  is.divisibleBy = function (value, n) {
    var isDividendInfinite = is.infinite(value);
    var isDivisorInfinite = is.infinite(n);
    var isNonZeroNumber = is.number(value) && !isActualNaN(value) && is.number(n) && !isActualNaN(n) && n !== 0;
    return isDividendInfinite || isDivisorInfinite || (isNonZeroNumber && value % n === 0);
  };
  
  /**
   * is.integer
   * Test if `value` is an integer.
   *
   * @param value to test
   * @return {Boolean} true if `value` is an integer, false otherwise
   * @api public
   */
  
  is.integer = is['int'] = function (value) {
    return is.number(value) && !isActualNaN(value) && value % 1 === 0;
  };
  
  /**
   * is.maximum
   * Test if `value` is greater than 'others' values.
   *
   * @param {Number} value value to test
   * @param {Array} others values to compare with
   * @return {Boolean} true if `value` is greater than `others` values
   * @api public
   */
  
  is.maximum = function (value, others) {
    if (isActualNaN(value)) {
      throw new TypeError('NaN is not a valid value');
    } else if (!is.arraylike(others)) {
      throw new TypeError('second argument must be array-like');
    }
    var len = others.length;
  
    while (--len >= 0) {
      if (value < others[len]) {
        return false;
      }
    }
  
    return true;
  };
  
  /**
   * is.minimum
   * Test if `value` is less than `others` values.
   *
   * @param {Number} value value to test
   * @param {Array} others values to compare with
   * @return {Boolean} true if `value` is less than `others` values
   * @api public
   */
  
  is.minimum = function (value, others) {
    if (isActualNaN(value)) {
      throw new TypeError('NaN is not a valid value');
    } else if (!is.arraylike(others)) {
      throw new TypeError('second argument must be array-like');
    }
    var len = others.length;
  
    while (--len >= 0) {
      if (value > others[len]) {
        return false;
      }
    }
  
    return true;
  };
  
  /**
   * is.nan
   * Test if `value` is not a number.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is not a number, false otherwise
   * @api public
   */
  
  is.nan = function (value) {
    return !is.number(value) || value !== value;
  };
  
  /**
   * is.even
   * Test if `value` is an even number.
   *
   * @param {Number} value value to test
   * @return {Boolean} true if `value` is an even number, false otherwise
   * @api public
   */
  
  is.even = function (value) {
    return is.infinite(value) || (is.number(value) && value === value && value % 2 === 0);
  };
  
  /**
   * is.odd
   * Test if `value` is an odd number.
   *
   * @param {Number} value value to test
   * @return {Boolean} true if `value` is an odd number, false otherwise
   * @api public
   */
  
  is.odd = function (value) {
    return is.infinite(value) || (is.number(value) && value === value && value % 2 !== 0);
  };
  
  /**
   * is.ge
   * Test if `value` is greater than or equal to `other`.
   *
   * @param {Number} value value to test
   * @param {Number} other value to compare with
   * @return {Boolean}
   * @api public
   */
  
  is.ge = function (value, other) {
    if (isActualNaN(value) || isActualNaN(other)) {
      throw new TypeError('NaN is not a valid value');
    }
    return !is.infinite(value) && !is.infinite(other) && value >= other;
  };
  
  /**
   * is.gt
   * Test if `value` is greater than `other`.
   *
   * @param {Number} value value to test
   * @param {Number} other value to compare with
   * @return {Boolean}
   * @api public
   */
  
  is.gt = function (value, other) {
    if (isActualNaN(value) || isActualNaN(other)) {
      throw new TypeError('NaN is not a valid value');
    }
    return !is.infinite(value) && !is.infinite(other) && value > other;
  };
  
  /**
   * is.le
   * Test if `value` is less than or equal to `other`.
   *
   * @param {Number} value value to test
   * @param {Number} other value to compare with
   * @return {Boolean} if 'value' is less than or equal to 'other'
   * @api public
   */
  
  is.le = function (value, other) {
    if (isActualNaN(value) || isActualNaN(other)) {
      throw new TypeError('NaN is not a valid value');
    }
    return !is.infinite(value) && !is.infinite(other) && value <= other;
  };
  
  /**
   * is.lt
   * Test if `value` is less than `other`.
   *
   * @param {Number} value value to test
   * @param {Number} other value to compare with
   * @return {Boolean} if `value` is less than `other`
   * @api public
   */
  
  is.lt = function (value, other) {
    if (isActualNaN(value) || isActualNaN(other)) {
      throw new TypeError('NaN is not a valid value');
    }
    return !is.infinite(value) && !is.infinite(other) && value < other;
  };
  
  /**
   * is.within
   * Test if `value` is within `start` and `finish`.
   *
   * @param {Number} value value to test
   * @param {Number} start lower bound
   * @param {Number} finish upper bound
   * @return {Boolean} true if 'value' is is within 'start' and 'finish'
   * @api public
   */
  is.within = function (value, start, finish) {
    if (isActualNaN(value) || isActualNaN(start) || isActualNaN(finish)) {
      throw new TypeError('NaN is not a valid value');
    } else if (!is.number(value) || !is.number(start) || !is.number(finish)) {
      throw new TypeError('all arguments must be numbers');
    }
    var isAnyInfinite = is.infinite(value) || is.infinite(start) || is.infinite(finish);
    return isAnyInfinite || (value >= start && value <= finish);
  };
  
  /**
   * Test object.
   */
  
  /**
   * is.object
   * Test if `value` is an object.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is an object, false otherwise
   * @api public
   */
  
  is.object = function (value) {
    return toStr.call(value) === '[object Object]';
  };
  
  /**
   * is.hash
   * Test if `value` is a hash - a plain object literal.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is a hash, false otherwise
   * @api public
   */
  
  is.hash = function (value) {
    return is.object(value) && value.constructor === Object && !value.nodeType && !value.setInterval;
  };
  
  /**
   * Test regexp.
   */
  
  /**
   * is.regexp
   * Test if `value` is a regular expression.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is a regexp, false otherwise
   * @api public
   */
  
  is.regexp = function (value) {
    return toStr.call(value) === '[object RegExp]';
  };
  
  /**
   * Test string.
   */
  
  /**
   * is.string
   * Test if `value` is a string.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if 'value' is a string, false otherwise
   * @api public
   */
  
  is.string = function (value) {
    return toStr.call(value) === '[object String]';
  };
  
  /**
   * Test base64 string.
   */
  
  /**
   * is.base64
   * Test if `value` is a valid base64 encoded string.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if 'value' is a base64 encoded string, false otherwise
   * @api public
   */
  
  is.base64 = function (value) {
    return is.string(value) && (!value.length || base64Regex.test(value));
  };
  
  /**
   * Test base64 string.
   */
  
  /**
   * is.hex
   * Test if `value` is a valid hex encoded string.
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if 'value' is a hex encoded string, false otherwise
   * @api public
   */
  
  is.hex = function (value) {
    return is.string(value) && (!value.length || hexRegex.test(value));
  };
  
  /**
   * is.symbol
   * Test if `value` is an ES6 Symbol
   *
   * @param {Mixed} value value to test
   * @return {Boolean} true if `value` is a Symbol, false otherise
   * @api public
   */
  
  is.symbol = function (value) {
    return typeof Symbol === 'function' && toStr.call(value) === '[object Symbol]' && typeof symbolValueOf.call(value) === 'symbol';
  };
  
  },{}],86:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Api, isFunction, isString, newError, ref, statusOk;
  
  ref = require('./utils'), isFunction = ref.isFunction, isString = ref.isString, newError = ref.newError, statusOk = ref.statusOk;
  
  module.exports = Api = (function() {
    Api.BLUEPRINTS = {};
  
    Api.CLIENT = null;
  
    function Api(opts) {
      var blueprints, client, debug, endpoint, k, key, v;
      if (opts == null) {
        opts = {};
      }
      if (!(this instanceof Api)) {
        return new Api(opts);
      }
      endpoint = opts.endpoint, debug = opts.debug, key = opts.key, client = opts.client, blueprints = opts.blueprints;
      this.debug = debug;
      if (blueprints == null) {
        blueprints = this.constructor.BLUEPRINTS;
      }
      if (client) {
        this.client = client;
      } else {
        this.client = new this.constructor.CLIENT({
          debug: debug,
          endpoint: endpoint,
          key: key
        });
      }
      for (k in blueprints) {
        v = blueprints[k];
        this.addBlueprints(k, v);
      }
    }
  
    Api.prototype.addBlueprints = function(api, blueprints) {
      var bp, fn, name;
      if (this[api] == null) {
        this[api] = {};
      }
      fn = (function(_this) {
        return function(name, bp) {
          var method;
          if (isFunction(bp)) {
            return _this[api][name] = function() {
              return bp.apply(_this, arguments);
            };
          }
          if (bp.expects == null) {
            bp.expects = statusOk;
          }
          if (bp.method == null) {
            bp.method = 'POST';
          }
          method = function(data, cb) {
            return _this.client.request(bp, data).then(function(res) {
              var ref1, ref2;
              if (((ref1 = res.data) != null ? ref1.error : void 0) != null) {
                throw newError(data, res);
              }
              if (!bp.expects(res)) {
                throw newError(data, res);
              }
              if (bp.process != null) {
                bp.process.call(_this, res);
              }
              return (ref2 = res.data) != null ? ref2 : res.body;
            }).callback(cb);
          };
          return _this[api][name] = method;
        };
      })(this);
      for (name in blueprints) {
        bp = blueprints[name];
        fn(name, bp);
      }
    };
  
    Api.prototype.setKey = function(key) {
      return this.client.setKey(key);
    };
  
    Api.prototype.setUserKey = function(key) {
      return this.client.setUserKey(key);
    };
  
    Api.prototype.deleteUserKey = function() {
      return this.client.deleteUserKey();
    };
  
    Api.prototype.setStore = function(id) {
      this.storeId = id;
      return this.client.setStore(id);
    };
  
    return Api;
  
  })();
  
  
  
  },{"./utils":91}],87:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var blueprints, byId, createBlueprint, fn, i, isFunction, len, model, models, ref, ref1, statusCreated, statusNoContent, statusOk, storePrefixed, userModels;
  
  ref = require('../utils'), isFunction = ref.isFunction, statusCreated = ref.statusCreated, statusNoContent = ref.statusNoContent, statusOk = ref.statusOk;
  
  ref1 = require('./url'), byId = ref1.byId, storePrefixed = ref1.storePrefixed;
  
  createBlueprint = function(name) {
    var endpoint;
    endpoint = "/" + name;
    return {
      list: {
        url: endpoint,
        method: 'GET',
        expects: statusOk
      },
      get: {
        url: byId(name),
        method: 'GET',
        expects: statusOk
      }
    };
  };
  
  blueprints = {
    account: {
      get: {
        url: '/account',
        method: 'GET',
        expects: statusOk
      },
      update: {
        url: '/account',
        method: 'PATCH',
        expects: statusOk
      },
      exists: {
        url: function(x) {
          var ref2, ref3, ref4;
          return "/account/exists/" + ((ref2 = (ref3 = (ref4 = x.email) != null ? ref4 : x.username) != null ? ref3 : x.id) != null ? ref2 : x);
        },
        method: 'GET',
        expects: statusOk,
        process: function(res) {
          return res.data.exists;
        }
      },
      create: {
        url: '/account/create',
        method: 'POST',
        expects: statusCreated
      },
      enable: {
        url: function(x) {
          var ref2;
          return "/account/enable/" + ((ref2 = x.tokenId) != null ? ref2 : x);
        },
        method: 'POST',
        expects: statusOk
      },
      login: {
        url: '/account/login',
        method: 'POST',
        expects: statusOk,
        process: function(res) {
          this.setUserKey(res.data.token);
          return res;
        }
      },
      logout: function() {
        return this.deleteUserKey();
      },
      reset: {
        url: '/account/reset',
        method: 'POST',
        expects: statusOk
      },
      confirm: {
        url: function(x) {
          var ref2;
          return "/account/confirm/" + ((ref2 = x.tokenId) != null ? ref2 : x);
        },
        method: 'POST',
        expects: statusOk
      }
    },
    checkout: {
      authorize: {
        url: storePrefixed('/checkout/authorize'),
        method: 'POST',
        expects: statusOk
      },
      capture: {
        url: storePrefixed(function(x) {
          var ref2;
          return "/checkout/capture/" + ((ref2 = x.orderId) != null ? ref2 : x);
        }),
        method: 'POST',
        expects: statusOk
      },
      charge: {
        url: storePrefixed('/checkout/charge'),
        method: 'POST',
        expects: statusOk
      },
      paypal: {
        url: storePrefixed('/checkout/paypal'),
        method: 'POST',
        expects: statusOk
      }
    },
    referrer: {
      create: {
        url: '/referrer',
        method: 'POST',
        expects: statusCreated
      }
    }
  };
  
  models = ['collection', 'coupon', 'product', 'variant'];
  
  userModels = ['order', 'subscription'];
  
  fn = function(model) {
    return blueprints[model] = createBlueprint(model);
  };
  for (i = 0, len = models.length; i < len; i++) {
    model = models[i];
    fn(model);
  }
  
  module.exports = blueprints;
  
  
  
  },{"../utils":91,"./url":88}],88:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var isFunction, sp;
  
  isFunction = require('../utils').isFunction;
  
  exports.storePrefixed = sp = function(u) {
    return function(x) {
      var url;
      if (isFunction(u)) {
        url = u(x);
      } else {
        url = u;
      }
      if (this.storeId != null) {
        return ("/store/" + this.storeId) + url;
      } else {
        return url;
      }
    };
  };
  
  exports.byId = function(name) {
    switch (name) {
      case 'coupon':
        return sp(function(x) {
          var ref;
          return "/coupon/" + ((ref = x.code) != null ? ref : x);
        });
      case 'collection':
        return sp(function(x) {
          var ref;
          return "/collection/" + ((ref = x.slug) != null ? ref : x);
        });
      case 'product':
        return sp(function(x) {
          var ref, ref1;
          return "/product/" + ((ref = (ref1 = x.id) != null ? ref1 : x.slug) != null ? ref : x);
        });
      case 'variant':
        return sp(function(x) {
          var ref, ref1;
          return "/variant/" + ((ref = (ref1 = x.id) != null ? ref1 : x.sku) != null ? ref : x);
        });
      default:
        return function(x) {
          var ref;
          return "/" + name + "/" + ((ref = x.id) != null ? ref : x);
        };
    }
  };
  
  
  
  },{"../utils":91}],89:[function(require,module,exports){
  (function (global){
  // Generated by CoffeeScript 1.10.0
  var Api, Client;
  
  if (global.Crowdstart == null) {
    global.Crowdstart = {};
  }
  
  Api = require('./api');
  
  Client = require('./client/xhr');
  
  Api.CLIENT = Client;
  
  Api.BLUEPRINTS = require('./blueprints/browser');
  
  Crowdstart.Api = Api;
  
  Crowdstart.Client = Client;
  
  module.exports = Crowdstart;
  
  
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"./api":86,"./blueprints/browser":87,"./client/xhr":90}],90:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Xhr, XhrClient, cookie, isFunction, newError, ref, updateQuery;
  
  Xhr = require('xhr-promise-es6');
  
  Xhr.Promise = require('broken');
  
  cookie = require('js-cookie');
  
  ref = require('../utils'), isFunction = ref.isFunction, newError = ref.newError, updateQuery = ref.updateQuery;
  
  module.exports = XhrClient = (function() {
    XhrClient.prototype.sessionName = 'crwdst';
  
    function XhrClient(opts) {
      if (opts == null) {
        opts = {};
      }
      if (!(this instanceof XhrClient)) {
        return new XhrClient(opts);
      }
      this.endpoint = 'https://api.crowdstart.com';
      this.key = opts.key, this.debug = opts.debug;
      if (opts.endpoint) {
        this.setEndpoint(opts.endpoint);
      }
      this.getUserKey();
    }
  
    XhrClient.prototype.setEndpoint = function(endpoint) {
      return this.endpoint = endpoint.replace(/\/$/, '');
    };
  
    XhrClient.prototype.setStore = function(id) {
      return this.storeId = id;
    };
  
    XhrClient.prototype.setKey = function(key) {
      return this.key = key;
    };
  
    XhrClient.prototype.getKey = function() {
      return this.userKey || this.key || this.constructor.KEY;
    };
  
    XhrClient.prototype.getUserKey = function() {
      var session;
      if ((session = cookie.getJSON(this.sessionName)) != null) {
        if (session.userKey != null) {
          this.userKey = session.userKey;
        }
      }
      return this.userKey;
    };
  
    XhrClient.prototype.setUserKey = function(key) {
      cookie.set(this.sessionName, {
        userKey: key
      }, {
        expires: 7 * 24 * 3600 * 1000
      });
      return this.userKey = key;
    };
  
    XhrClient.prototype.deleteUserKey = function() {
      cookie.set(this.sessionName, {
        userKey: null
      }, {
        expires: 7 * 24 * 3600 * 1000
      });
      return this.userKey;
    };
  
    XhrClient.prototype.getUrl = function(url, data, key) {
      if (isFunction(url)) {
        url = url.call(this, data);
      }
      return updateQuery(this.endpoint + url, 'token', key);
    };
  
    XhrClient.prototype.request = function(blueprint, data, key) {
      var opts;
      if (key == null) {
        key = this.getKey();
      }
      opts = {
        url: this.getUrl(blueprint.url, data, key),
        method: blueprint.method,
        data: JSON.stringify(data)
      };
      if (this.debug) {
        console.log('--REQUEST--');
        console.log(opts);
      }
      return (new Xhr).send(opts).then(function(res) {
        if (this.debug) {
          console.log('--RESPONSE--');
          console.log(res);
        }
        res.data = res.responseText;
        return res;
      })["catch"](function(res) {
        var err, error, ref1;
        try {
          res.data = (ref1 = res.responseText) != null ? ref1 : JSON.parse(res.xhr.responseText);
        } catch (error) {
          err = error;
        }
        err = newError(data, res);
        if (this.debug) {
          console.log('--RESPONSE--');
          console.log(res);
          console.log('ERROR:', err);
        }
        throw err;
      });
    };
  
    return XhrClient;
  
  })();
  
  
  
  },{"../utils":91,"broken":59,"js-cookie":100,"xhr-promise-es6":92}],91:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  exports.isFunction = function(fn) {
    return typeof fn === 'function';
  };
  
  exports.isString = function(s) {
    return typeof s === 'string';
  };
  
  exports.statusOk = function(res) {
    return res.status === 200;
  };
  
  exports.statusCreated = function(res) {
    return res.status === 201;
  };
  
  exports.statusNoContent = function(res) {
    return res.status === 204;
  };
  
  exports.newError = function(data, res) {
    var err, message, ref, ref1, ref2, ref3, ref4;
    if (res == null) {
      res = {};
    }
    message = (ref = res != null ? (ref1 = res.data) != null ? (ref2 = ref1.error) != null ? ref2.message : void 0 : void 0 : void 0) != null ? ref : 'Request failed';
    err = new Error(message);
    err.message = message;
    err.req = data;
    err.data = res.data;
    err.responseText = res.data;
    err.status = res.status;
    err.type = (ref3 = res.data) != null ? (ref4 = ref3.error) != null ? ref4.type : void 0 : void 0;
    return err;
  };
  
  exports.updateQuery = function(url, key, value) {
    var hash, re, separator;
    re = new RegExp('([?&])' + key + '=.*?(&|#|$)(.*)', 'gi');
    if (re.test(url)) {
      if (value != null) {
        return url.replace(re, '$1' + key + '=' + value + '$2$3');
      } else {
        hash = url.split('#');
        url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
        if (hash[1] != null) {
          url += '#' + hash[1];
        }
        return url;
      }
    } else {
      if (value != null) {
        separator = url.indexOf('?') !== -1 ? '&' : '?';
        hash = url.split('#');
        url = hash[0] + separator + key + '=' + value;
        if (hash[1] != null) {
          url += '#' + hash[1];
        }
        return url;
      } else {
        return url;
      }
    }
  };
  
  
  
  },{}],92:[function(require,module,exports){
  (function (global){
  
  /*
   * Copyright 2015 Scott Brady
   * MIT License
   * https://github.com/scottbrady/xhr-promise/blob/master/LICENSE
   */
  var ParseHeaders, XMLHttpRequestPromise, objectAssign;
  
  ParseHeaders = require('parse-headers');
  
  objectAssign = require('object-assign');
  
  
  /*
   * Module to wrap an XMLHttpRequest in a promise.
   */
  
  module.exports = XMLHttpRequestPromise = (function() {
    function XMLHttpRequestPromise() {}
  
    XMLHttpRequestPromise.DEFAULT_CONTENT_TYPE = 'application/x-www-form-urlencoded; charset=UTF-8';
  
    XMLHttpRequestPromise.Promise = global.Promise;
  
  
    /*
     * XMLHttpRequestPromise.send(options) -> Promise
     * - options (Object): URL, method, data, etc.
     *
     * Create the XHR object and wire up event handlers to use a promise.
     */
  
    XMLHttpRequestPromise.prototype.send = function(options) {
      var defaults;
      if (options == null) {
        options = {};
      }
      defaults = {
        method: 'GET',
        data: null,
        headers: {},
        async: true,
        username: null,
        password: null
      };
      options = objectAssign({}, defaults, options);
      return new this.constructor.Promise((function(_this) {
        return function(resolve, reject) {
          var e, header, ref, value, xhr;
          if (!XMLHttpRequest) {
            _this._handleError('browser', reject, null, "browser doesn't support XMLHttpRequest");
            return;
          }
          if (typeof options.url !== 'string' || options.url.length === 0) {
            _this._handleError('url', reject, null, 'URL is a required parameter');
            return;
          }
          _this._xhr = xhr = new XMLHttpRequest;
          xhr.onload = function() {
            var responseText;
            _this._detachWindowUnload();
            try {
              responseText = _this._getResponseText();
            } catch (_error) {
              _this._handleError('parse', reject, null, 'invalid JSON response');
              return;
            }
            return resolve({
              url: _this._getResponseUrl(),
              status: xhr.status,
              statusText: xhr.statusText,
              responseText: responseText,
              headers: _this._getHeaders(),
              xhr: xhr
            });
          };
          xhr.onerror = function() {
            return _this._handleError('error', reject);
          };
          xhr.ontimeout = function() {
            return _this._handleError('timeout', reject);
          };
          xhr.onabort = function() {
            return _this._handleError('abort', reject);
          };
          _this._attachWindowUnload();
          xhr.open(options.method, options.url, options.async, options.username, options.password);
          if ((options.data != null) && !options.headers['Content-Type']) {
            options.headers['Content-Type'] = _this.constructor.DEFAULT_CONTENT_TYPE;
          }
          ref = options.headers;
          for (header in ref) {
            value = ref[header];
            xhr.setRequestHeader(header, value);
          }
          try {
            return xhr.send(options.data);
          } catch (_error) {
            e = _error;
            return _this._handleError('send', reject, null, e.toString());
          }
        };
      })(this));
    };
  
  
    /*
     * XMLHttpRequestPromise.getXHR() -> XMLHttpRequest
     */
  
    XMLHttpRequestPromise.prototype.getXHR = function() {
      return this._xhr;
    };
  
  
    /*
     * XMLHttpRequestPromise._attachWindowUnload()
     *
     * Fix for IE 9 and IE 10
     * Internet Explorer freezes when you close a webpage during an XHR request
     * https://support.microsoft.com/kb/2856746
     *
     */
  
    XMLHttpRequestPromise.prototype._attachWindowUnload = function() {
      this._unloadHandler = this._handleWindowUnload.bind(this);
      if (window.attachEvent) {
        return window.attachEvent('onunload', this._unloadHandler);
      }
    };
  
  
    /*
     * XMLHttpRequestPromise._detachWindowUnload()
     */
  
    XMLHttpRequestPromise.prototype._detachWindowUnload = function() {
      if (window.detachEvent) {
        return window.detachEvent('onunload', this._unloadHandler);
      }
    };
  
  
    /*
     * XMLHttpRequestPromise._getHeaders() -> Object
     */
  
    XMLHttpRequestPromise.prototype._getHeaders = function() {
      return ParseHeaders(this._xhr.getAllResponseHeaders());
    };
  
  
    /*
     * XMLHttpRequestPromise._getResponseText() -> Mixed
     *
     * Parses response text JSON if present.
     */
  
    XMLHttpRequestPromise.prototype._getResponseText = function() {
      var responseText;
      responseText = typeof this._xhr.responseText === 'string' ? this._xhr.responseText : '';
      switch (this._xhr.getResponseHeader('Content-Type')) {
        case 'application/json':
        case 'text/javascript':
          responseText = JSON.parse(responseText + '');
      }
      return responseText;
    };
  
  
    /*
     * XMLHttpRequestPromise._getResponseUrl() -> String
     *
     * Actual response URL after following redirects.
     */
  
    XMLHttpRequestPromise.prototype._getResponseUrl = function() {
      if (this._xhr.responseURL != null) {
        return this._xhr.responseURL;
      }
      if (/^X-Request-URL:/m.test(this._xhr.getAllResponseHeaders())) {
        return this._xhr.getResponseHeader('X-Request-URL');
      }
      return '';
    };
  
  
    /*
     * XMLHttpRequestPromise._handleError(reason, reject, status, statusText)
     * - reason (String)
     * - reject (Function)
     * - status (String)
     * - statusText (String)
     */
  
    XMLHttpRequestPromise.prototype._handleError = function(reason, reject, status, statusText) {
      this._detachWindowUnload();
      return reject({
        reason: reason,
        status: status || this._xhr.status,
        statusText: statusText || this._xhr.statusText,
        xhr: this._xhr
      });
    };
  
  
    /*
     * XMLHttpRequestPromise._handleWindowUnload()
     */
  
    XMLHttpRequestPromise.prototype._handleWindowUnload = function() {
      return this._xhr.abort();
    };
  
    return XMLHttpRequestPromise;
  
  })();
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"object-assign":93,"parse-headers":97}],93:[function(require,module,exports){
  arguments[4][72][0].apply(exports,arguments)
  },{"dup":72}],94:[function(require,module,exports){
  var isFunction = require('is-function')
  
  module.exports = forEach
  
  var toString = Object.prototype.toString
  var hasOwnProperty = Object.prototype.hasOwnProperty
  
  function forEach(list, iterator, context) {
      if (!isFunction(iterator)) {
          throw new TypeError('iterator must be a function')
      }
  
      if (arguments.length < 3) {
          context = this
      }
      
      if (toString.call(list) === '[object Array]')
          forEachArray(list, iterator, context)
      else if (typeof list === 'string')
          forEachString(list, iterator, context)
      else
          forEachObject(list, iterator, context)
  }
  
  function forEachArray(array, iterator, context) {
      for (var i = 0, len = array.length; i < len; i++) {
          if (hasOwnProperty.call(array, i)) {
              iterator.call(context, array[i], i, array)
          }
      }
  }
  
  function forEachString(string, iterator, context) {
      for (var i = 0, len = string.length; i < len; i++) {
          // no such thing as a sparse string.
          iterator.call(context, string.charAt(i), i, string)
      }
  }
  
  function forEachObject(object, iterator, context) {
      for (var k in object) {
          if (hasOwnProperty.call(object, k)) {
              iterator.call(context, object[k], k, object)
          }
      }
  }
  
  },{"is-function":95}],95:[function(require,module,exports){
  arguments[4][71][0].apply(exports,arguments)
  },{"dup":71}],96:[function(require,module,exports){
  
  exports = module.exports = trim;
  
  function trim(str){
    return str.replace(/^\s*|\s*$/g, '');
  }
  
  exports.left = function(str){
    return str.replace(/^\s*/, '');
  };
  
  exports.right = function(str){
    return str.replace(/\s*$/, '');
  };
  
  },{}],97:[function(require,module,exports){
  var trim = require('trim')
    , forEach = require('for-each')
    , isArray = function(arg) {
        return Object.prototype.toString.call(arg) === '[object Array]';
      }
  
  module.exports = function (headers) {
    if (!headers)
      return {}
  
    var result = {}
  
    forEach(
        trim(headers).split('\n')
      , function (row) {
          var index = row.indexOf(':')
            , key = trim(row.slice(0, index)).toLowerCase()
            , value = trim(row.slice(index + 1))
  
          if (typeof(result[key]) === 'undefined') {
            result[key] = value
          } else if (isArray(result[key])) {
            result[key].push(value)
          } else {
            result[key] = [ result[key], value ]
          }
        }
    )
  
    return result
  }
  },{"for-each":94,"trim":96}],98:[function(require,module,exports){
  'use strict';
  
  var hasOwn = Object.prototype.hasOwnProperty;
  var toStr = Object.prototype.toString;
  
  var isArray = function isArray(arr) {
  	if (typeof Array.isArray === 'function') {
  		return Array.isArray(arr);
  	}
  
  	return toStr.call(arr) === '[object Array]';
  };
  
  var isPlainObject = function isPlainObject(obj) {
  	if (!obj || toStr.call(obj) !== '[object Object]') {
  		return false;
  	}
  
  	var hasOwnConstructor = hasOwn.call(obj, 'constructor');
  	var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf');
  	// Not own constructor property must be Object
  	if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) {
  		return false;
  	}
  
  	// Own properties are enumerated firstly, so to speed up,
  	// if last one is own, then all properties are own.
  	var key;
  	for (key in obj) {/**/}
  
  	return typeof key === 'undefined' || hasOwn.call(obj, key);
  };
  
  module.exports = function extend() {
  	var options, name, src, copy, copyIsArray, clone,
  		target = arguments[0],
  		i = 1,
  		length = arguments.length,
  		deep = false;
  
  	// Handle a deep copy situation
  	if (typeof target === 'boolean') {
  		deep = target;
  		target = arguments[1] || {};
  		// skip the boolean and the target
  		i = 2;
  	} else if ((typeof target !== 'object' && typeof target !== 'function') || target == null) {
  		target = {};
  	}
  
  	for (; i < length; ++i) {
  		options = arguments[i];
  		// Only deal with non-null/undefined values
  		if (options != null) {
  			// Extend the base object
  			for (name in options) {
  				src = target[name];
  				copy = options[name];
  
  				// Prevent never-ending loop
  				if (target !== copy) {
  					// Recurse if we're merging plain objects or arrays
  					if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) {
  						if (copyIsArray) {
  							copyIsArray = false;
  							clone = src && isArray(src) ? src : [];
  						} else {
  							clone = src && isPlainObject(src) ? src : {};
  						}
  
  						// Never move original objects, clone them
  						target[name] = extend(deep, clone, copy);
  
  					// Don't bring in undefined values
  					} else if (typeof copy !== 'undefined') {
  						target[name] = copy;
  					}
  				}
  			}
  		}
  	}
  
  	// Return the modified object
  	return target;
  };
  
  
  },{}],99:[function(require,module,exports){
  "use strict";
  
  module.exports = function isObject(x) {
  	return typeof x === "object" && x !== null;
  };
  
  },{}],100:[function(require,module,exports){
  /*!
   * JavaScript Cookie v2.1.0
   * https://github.com/js-cookie/js-cookie
   *
   * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
   * Released under the MIT license
   */
  (function (factory) {
  	if (typeof define === 'function' && define.amd) {
  		define(factory);
  	} else if (typeof exports === 'object') {
  		module.exports = factory();
  	} else {
  		var _OldCookies = window.Cookies;
  		var api = window.Cookies = factory();
  		api.noConflict = function () {
  			window.Cookies = _OldCookies;
  			return api;
  		};
  	}
  }(function () {
  	function extend () {
  		var i = 0;
  		var result = {};
  		for (; i < arguments.length; i++) {
  			var attributes = arguments[ i ];
  			for (var key in attributes) {
  				result[key] = attributes[key];
  			}
  		}
  		return result;
  	}
  
  	function init (converter) {
  		function api (key, value, attributes) {
  			var result;
  
  			// Write
  
  			if (arguments.length > 1) {
  				attributes = extend({
  					path: '/'
  				}, api.defaults, attributes);
  
  				if (typeof attributes.expires === 'number') {
  					var expires = new Date();
  					expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
  					attributes.expires = expires;
  				}
  
  				try {
  					result = JSON.stringify(value);
  					if (/^[\{\[]/.test(result)) {
  						value = result;
  					}
  				} catch (e) {}
  
  				if (!converter.write) {
  					value = encodeURIComponent(String(value))
  						.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
  				} else {
  					value = converter.write(value, key);
  				}
  
  				key = encodeURIComponent(String(key));
  				key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
  				key = key.replace(/[\(\)]/g, escape);
  
  				return (document.cookie = [
  					key, '=', value,
  					attributes.expires && '; expires=' + attributes.expires.toUTCString(), // use expires attribute, max-age is not supported by IE
  					attributes.path    && '; path=' + attributes.path,
  					attributes.domain  && '; domain=' + attributes.domain,
  					attributes.secure ? '; secure' : ''
  				].join(''));
  			}
  
  			// Read
  
  			if (!key) {
  				result = {};
  			}
  
  			// To prevent the for loop in the first place assign an empty array
  			// in case there are no cookies at all. Also prevents odd result when
  			// calling "get()"
  			var cookies = document.cookie ? document.cookie.split('; ') : [];
  			var rdecode = /(%[0-9A-Z]{2})+/g;
  			var i = 0;
  
  			for (; i < cookies.length; i++) {
  				var parts = cookies[i].split('=');
  				var name = parts[0].replace(rdecode, decodeURIComponent);
  				var cookie = parts.slice(1).join('=');
  
  				if (cookie.charAt(0) === '"') {
  					cookie = cookie.slice(1, -1);
  				}
  
  				try {
  					cookie = converter.read ?
  						converter.read(cookie, name) : converter(cookie, name) ||
  						cookie.replace(rdecode, decodeURIComponent);
  
  					if (this.json) {
  						try {
  							cookie = JSON.parse(cookie);
  						} catch (e) {}
  					}
  
  					if (key === name) {
  						result = cookie;
  						break;
  					}
  
  					if (!key) {
  						result[name] = cookie;
  					}
  				} catch (e) {}
  			}
  
  			return result;
  		}
  
  		api.get = api.set = api;
  		api.getJSON = function () {
  			return api.apply({
  				json: true
  			}, [].slice.call(arguments));
  		};
  		api.defaults = {};
  
  		api.remove = function (key, attributes) {
  			api(key, '', extend(attributes, {
  				expires: -1
  			}));
  		};
  
  		api.withConverter = init;
  
  		return api;
  	}
  
  	return init(function () {});
  }));
  
  },{}],101:[function(require,module,exports){
  var now = require('performance-now')
    , global = typeof window === 'undefined' ? {} : window
    , vendors = ['moz', 'webkit']
    , suffix = 'AnimationFrame'
    , raf = global['request' + suffix]
    , caf = global['cancel' + suffix] || global['cancelRequest' + suffix]
  
  for(var i = 0; i < vendors.length && !raf; i++) {
    raf = global[vendors[i] + 'Request' + suffix]
    caf = global[vendors[i] + 'Cancel' + suffix]
        || global[vendors[i] + 'CancelRequest' + suffix]
  }
  
  // Some versions of FF have rAF but not cAF
  if(!raf || !caf) {
    var last = 0
      , id = 0
      , queue = []
      , frameDuration = 1000 / 60
  
    raf = function(callback) {
      if(queue.length === 0) {
        var _now = now()
          , next = Math.max(0, frameDuration - (_now - last))
        last = next + _now
        setTimeout(function() {
          var cp = queue.slice(0)
          // Clear queue here to prevent
          // callbacks from appending listeners
          // to the current frame's queue
          queue.length = 0
          for(var i = 0; i < cp.length; i++) {
            if(!cp[i].cancelled) {
              try{
                cp[i].callback(last)
              } catch(e) {
                setTimeout(function() { throw e }, 0)
              }
            }
          }
        }, Math.round(next))
      }
      queue.push({
        handle: ++id,
        callback: callback,
        cancelled: false
      })
      return id
    }
  
    caf = function(handle) {
      for(var i = 0; i < queue.length; i++) {
        if(queue[i].handle === handle) {
          queue[i].cancelled = true
        }
      }
    }
  }
  
  module.exports = function(fn) {
    // Wrap in a new function to prevent
    // `cancel` potentially being assigned
    // to the native rAF function
    return raf.call(global, fn)
  }
  module.exports.cancel = function() {
    caf.apply(global, arguments)
  }
  
  },{"performance-now":102}],102:[function(require,module,exports){
  (function (process){
  // Generated by CoffeeScript 1.7.1
  (function() {
    var getNanoSeconds, hrtime, loadTime;
  
    if ((typeof performance !== "undefined" && performance !== null) && performance.now) {
      module.exports = function() {
        return performance.now();
      };
    } else if ((typeof process !== "undefined" && process !== null) && process.hrtime) {
      module.exports = function() {
        return (getNanoSeconds() - loadTime) / 1e6;
      };
      hrtime = process.hrtime;
      getNanoSeconds = function() {
        var hr;
        hr = hrtime();
        return hr[0] * 1e9 + hr[1];
      };
      loadTime = getNanoSeconds();
    } else if (Date.now) {
      module.exports = function() {
        return Date.now() - loadTime;
      };
      loadTime = Date.now();
    } else {
      module.exports = function() {
        return new Date().getTime() - loadTime;
      };
      loadTime = new Date().getTime();
    }
  
  }).call(this);
  
  }).call(this,require('_process'))
  },{"_process":120}],103:[function(require,module,exports){
  arguments[4][75][0].apply(exports,arguments)
  },{"./ref":104,"./refer":105,"dup":75}],104:[function(require,module,exports){
  // Generated by CoffeeScript 1.10.0
  var Ref, extend, isArray, isNumber, isObject, isString, nextId;
  
  extend = require('node.extend');
  
  isArray = require('is-array');
  
  isNumber = require('is-number');
  
  isObject = require('is-object');
  
  isString = require('is-string');
  
  nextId = (function() {
    var ids;
    ids = 0;
    return function() {
      return ids++;
    };
  })();
  
  module.exports = Ref = (function() {
    function Ref(_value, parent, key1) {
      this._value = _value;
      this.parent = parent;
      this.key = key1;
      this._cache = {};
      this._children = {};
      this._id = nextId();
      if (this.parent != null) {
        this.parent._children[this._id] = this;
      }
      this;
    }
  
    Ref.prototype._mutate = function(key) {
      var child, id, ref;
      this._cache = {};
      ref = this._children;
      for (id in ref) {
        child = ref[id];
        child._mutate();
      }
      return this;
    };
  
    Ref.prototype.destroy = function() {
      var child, id, ref;
      ref = this._children;
      for (id in ref) {
        child = ref[id];
        child.destroy();
      }
      delete this._cache;
      delete this._children;
      delete this.parent._children[this._id];
      return this;
    };
  
    Ref.prototype.value = function(state) {
      if (!this.parent) {
        if (state != null) {
          this._value = state;
        }
        return this._value;
      }
      if (state != null) {
        return this.parent.set(this.key, state);
      } else {
        return this.parent.get(this.key);
      }
    };
  
    Ref.prototype.ref = function(key) {
      if (!key) {
        return this;
      }
      return new Ref(null, this, key);
    };
  
    Ref.prototype.get = function(key) {
      if (!key) {
        return this.value();
      } else {
        if (this._cache[key]) {
          return this._cache[key];
        }
        return this._cache[key] = this.index(key);
      }
    };
  
    Ref.prototype.set = function(key, value) {
      this._mutate(key);
      if (value == null) {
        this.value(extend(this.value(), key));
      } else {
        this.index(key, value);
      }
      return this;
    };
  
    Ref.prototype.extend = function(key, value) {
      var clone;
      this._mutate(key);
      if (value == null) {
        this.value(extend(true, this.value(), key));
      } else {
        if (isObject(value)) {
          this.value(extend(true, (this.ref(key)).get(), value));
        } else {
          clone = this.clone();
          this.set(key, value);
          this.value(extend(true, clone.get(), this.value()));
        }
      }
      return this;
    };
  
    Ref.prototype.clone = function(key) {
      return new Ref(extend(true, {}, this.get(key)));
    };
  
    Ref.prototype.index = function(key, value, obj, prev) {
      var next, prop, props;
      if (obj == null) {
        obj = this.value();
      }
      if (this.parent) {
        return this.parent.index(this.key + '.' + key, value);
      }
      if (isNumber(key)) {
        key = String(key);
      }
      props = key.split('.');
      if (value == null) {
        while (prop = props.shift()) {
          if (!props.length) {
            return obj != null ? obj[prop] : void 0;
          }
          obj = obj != null ? obj[prop] : void 0;
        }
        return;
      }
      while (prop = props.shift()) {
        if (!props.length) {
          return obj[prop] = value;
        } else {
          next = props[0];
          if (obj[next] == null) {
            if (isNumber(next)) {
              if (obj[prop] == null) {
                obj[prop] = [];
              }
            } else {
              if (obj[prop] == null) {
                obj[prop] = {};
              }
            }
          }
        }
        obj = obj[prop];
      }
    };
  
    return Ref;
  
  })();
  
  
  
  },{"is-array":106,"is-number":107,"is-object":99,"is-string":110,"node.extend":111}],105:[function(require,module,exports){
  arguments[4][77][0].apply(exports,arguments)
  },{"./ref":104,"dup":77}],106:[function(require,module,exports){
  arguments[4][78][0].apply(exports,arguments)
  },{"dup":78}],107:[function(require,module,exports){
  arguments[4][79][0].apply(exports,arguments)
  },{"dup":79,"kind-of":108}],108:[function(require,module,exports){
  arguments[4][80][0].apply(exports,arguments)
  },{"buffer":116,"dup":80,"is-buffer":109}],109:[function(require,module,exports){
  arguments[4][81][0].apply(exports,arguments)
  },{"dup":81}],110:[function(require,module,exports){
  arguments[4][82][0].apply(exports,arguments)
  },{"dup":82}],111:[function(require,module,exports){
  arguments[4][83][0].apply(exports,arguments)
  },{"./lib/extend":112,"dup":83}],112:[function(require,module,exports){
  arguments[4][84][0].apply(exports,arguments)
  },{"dup":84,"is":113}],113:[function(require,module,exports){
  arguments[4][85][0].apply(exports,arguments)
  },{"dup":85}],114:[function(require,module,exports){
  /* Riot v2.3.18, @license MIT */
  
  ;(function(window, undefined) {
    'use strict';
  var riot = { version: 'v2.3.18', settings: {} },
    // be aware, internal usage
    // ATTENTION: prefix the global dynamic variables with `__`
  
    // counter to give a unique id to all the Tag instances
    __uid = 0,
    // tags instances cache
    __virtualDom = [],
    // tags implementation cache
    __tagImpl = {},
  
    /**
     * Const
     */
    GLOBAL_MIXIN = '__global_mixin',
  
    // riot specific prefixes
    RIOT_PREFIX = 'riot-',
    RIOT_TAG = RIOT_PREFIX + 'tag',
    RIOT_TAG_IS = 'data-is',
  
    // for typeof == '' comparisons
    T_STRING = 'string',
    T_OBJECT = 'object',
    T_UNDEF  = 'undefined',
    T_FUNCTION = 'function',
    // special native tags that cannot be treated like the others
    SPECIAL_TAGS_REGEX = /^(?:t(?:body|head|foot|[rhd])|caption|col(?:group)?|opt(?:ion|group))$/,
    RESERVED_WORDS_BLACKLIST = ['_item', '_id', '_parent', 'update', 'root', 'mount', 'unmount', 'mixin', 'isMounted', 'isLoop', 'tags', 'parent', 'opts', 'trigger', 'on', 'off', 'one'],
  
    // version# for IE 8-11, 0 for others
    IE_VERSION = (window && window.document || {}).documentMode | 0,
  
    // detect firefox to fix #1374
    FIREFOX = window && !!window.InstallTrigger
  /* istanbul ignore next */
  riot.observable = function(el) {
  
    /**
     * Extend the original object or create a new empty one
     * @type { Object }
     */
  
    el = el || {}
  
    /**
     * Private variables and methods
     */
    var callbacks = {},
      slice = Array.prototype.slice,
      onEachEvent = function(e, fn) { e.replace(/\S+/g, fn) }
  
    // extend the object adding the observable methods
    Object.defineProperties(el, {
      /**
       * Listen to the given space separated list of `events` and execute the `callback` each time an event is triggered.
       * @param  { String } events - events ids
       * @param  { Function } fn - callback function
       * @returns { Object } el
       */
      on: {
        value: function(events, fn) {
          if (typeof fn != 'function')  return el
  
          onEachEvent(events, function(name, pos) {
            (callbacks[name] = callbacks[name] || []).push(fn)
            fn.typed = pos > 0
          })
  
          return el
        },
        enumerable: false,
        writable: false,
        configurable: false
      },
  
      /**
       * Removes the given space separated list of `events` listeners
       * @param   { String } events - events ids
       * @param   { Function } fn - callback function
       * @returns { Object } el
       */
      off: {
        value: function(events, fn) {
          if (events == '*' && !fn) callbacks = {}
          else {
            onEachEvent(events, function(name) {
              if (fn) {
                var arr = callbacks[name]
                for (var i = 0, cb; cb = arr && arr[i]; ++i) {
                  if (cb == fn) arr.splice(i--, 1)
                }
              } else delete callbacks[name]
            })
          }
          return el
        },
        enumerable: false,
        writable: false,
        configurable: false
      },
  
      /**
       * Listen to the given space separated list of `events` and execute the `callback` at most once
       * @param   { String } events - events ids
       * @param   { Function } fn - callback function
       * @returns { Object } el
       */
      one: {
        value: function(events, fn) {
          function on() {
            el.off(events, on)
            fn.apply(el, arguments)
          }
          return el.on(events, on)
        },
        enumerable: false,
        writable: false,
        configurable: false
      },
  
      /**
       * Execute all callback functions that listen to the given space separated list of `events`
       * @param   { String } events - events ids
       * @returns { Object } el
       */
      trigger: {
        value: function(events) {
  
          // getting the arguments
          var arglen = arguments.length - 1,
            args = new Array(arglen),
            fns
  
          for (var i = 0; i < arglen; i++) {
            args[i] = arguments[i + 1] // skip first argument
          }
  
          onEachEvent(events, function(name) {
  
            fns = slice.call(callbacks[name] || [], 0)
  
            for (var i = 0, fn; fn = fns[i]; ++i) {
              if (fn.busy) return
              fn.busy = 1
              fn.apply(el, fn.typed ? [name].concat(args) : args)
              if (fns[i] !== fn) { i-- }
              fn.busy = 0
            }
  
            if (callbacks['*'] && name != '*')
              el.trigger.apply(el, ['*', name].concat(args))
  
          })
  
          return el
        },
        enumerable: false,
        writable: false,
        configurable: false
      }
    })
  
    return el
  
  }
  /* istanbul ignore next */
  ;(function(riot) {
  
  /**
   * Simple client-side router
   * @module riot-route
   */
  
  
  var RE_ORIGIN = /^.+?\/\/+[^\/]+/,
    EVENT_LISTENER = 'EventListener',
    REMOVE_EVENT_LISTENER = 'remove' + EVENT_LISTENER,
    ADD_EVENT_LISTENER = 'add' + EVENT_LISTENER,
    HAS_ATTRIBUTE = 'hasAttribute',
    REPLACE = 'replace',
    POPSTATE = 'popstate',
    HASHCHANGE = 'hashchange',
    TRIGGER = 'trigger',
    MAX_EMIT_STACK_LEVEL = 3,
    win = typeof window != 'undefined' && window,
    doc = typeof document != 'undefined' && document,
    hist = win && history,
    loc = win && (hist.location || win.location), // see html5-history-api
    prot = Router.prototype, // to minify more
    clickEvent = doc && doc.ontouchstart ? 'touchstart' : 'click',
    started = false,
    central = riot.observable(),
    routeFound = false,
    debouncedEmit,
    base, current, parser, secondParser, emitStack = [], emitStackLevel = 0
  
  /**
   * Default parser. You can replace it via router.parser method.
   * @param {string} path - current path (normalized)
   * @returns {array} array
   */
  function DEFAULT_PARSER(path) {
    return path.split(/[/?#]/)
  }
  
  /**
   * Default parser (second). You can replace it via router.parser method.
   * @param {string} path - current path (normalized)
   * @param {string} filter - filter string (normalized)
   * @returns {array} array
   */
  function DEFAULT_SECOND_PARSER(path, filter) {
    var re = new RegExp('^' + filter[REPLACE](/\*/g, '([^/?#]+?)')[REPLACE](/\.\./, '.*') + '$'),
      args = path.match(re)
  
    if (args) return args.slice(1)
  }
  
  /**
   * Simple/cheap debounce implementation
   * @param   {function} fn - callback
   * @param   {number} delay - delay in seconds
   * @returns {function} debounced function
   */
  function debounce(fn, delay) {
    var t
    return function () {
      clearTimeout(t)
      t = setTimeout(fn, delay)
    }
  }
  
  /**
   * Set the window listeners to trigger the routes
   * @param {boolean} autoExec - see route.start
   */
  function start(autoExec) {
    debouncedEmit = debounce(emit, 1)
    win[ADD_EVENT_LISTENER](POPSTATE, debouncedEmit)
    win[ADD_EVENT_LISTENER](HASHCHANGE, debouncedEmit)
    doc[ADD_EVENT_LISTENER](clickEvent, click)
    if (autoExec) emit(true)
  }
  
  /**
   * Router class
   */
  function Router() {
    this.$ = []
    riot.observable(this) // make it observable
    central.on('stop', this.s.bind(this))
    central.on('emit', this.e.bind(this))
  }
  
  function normalize(path) {
    return path[REPLACE](/^\/|\/$/, '')
  }
  
  function isString(str) {
    return typeof str == 'string'
  }
  
  /**
   * Get the part after domain name
   * @param {string} href - fullpath
   * @returns {string} path from root
   */
  function getPathFromRoot(href) {
    return (href || loc.href)[REPLACE](RE_ORIGIN, '')
  }
  
  /**
   * Get the part after base
   * @param {string} href - fullpath
   * @returns {string} path from base
   */
  function getPathFromBase(href) {
    return base[0] == '#'
      ? (href || loc.href || '').split(base)[1] || ''
      : (loc ? getPathFromRoot(href) : href || '')[REPLACE](base, '')
  }
  
  function emit(force) {
    // the stack is needed for redirections
    var isRoot = emitStackLevel == 0
    if (MAX_EMIT_STACK_LEVEL <= emitStackLevel) return
  
    emitStackLevel++
    emitStack.push(function() {
      var path = getPathFromBase()
      if (force || path != current) {
        central[TRIGGER]('emit', path)
        current = path
      }
    })
    if (isRoot) {
      while (emitStack.length) {
        emitStack[0]()
        emitStack.shift()
      }
      emitStackLevel = 0
    }
  }
  
  function click(e) {
    if (
      e.which != 1 // not left click
      || e.metaKey || e.ctrlKey || e.shiftKey // or meta keys
      || e.defaultPrevented // or default prevented
    ) return
  
    var el = e.target
    while (el && el.nodeName != 'A') el = el.parentNode
  
    if (
      !el || el.nodeName != 'A' // not A tag
      || el[HAS_ATTRIBUTE]('download') // has download attr
      || !el[HAS_ATTRIBUTE]('href') // has no href attr
      || el.target && el.target != '_self' // another window or frame
      || el.href.indexOf(loc.href.match(RE_ORIGIN)[0]) == -1 // cross origin
    ) return
  
    if (el.href != loc.href) {
      if (
        el.href.split('#')[0] == loc.href.split('#')[0] // internal jump
        || base != '#' && getPathFromRoot(el.href).indexOf(base) !== 0 // outside of base
        || !go(getPathFromBase(el.href), el.title || doc.title) // route not found
      ) return
    }
  
    e.preventDefault()
  }
  
  /**
   * Go to the path
   * @param {string} path - destination path
   * @param {string} title - page title
   * @param {boolean} shouldReplace - use replaceState or pushState
   * @returns {boolean} - route not found flag
   */
  function go(path, title, shouldReplace) {
    if (hist) { // if a browser
      path = base + normalize(path)
      title = title || doc.title
      // browsers ignores the second parameter `title`
      shouldReplace
        ? hist.replaceState(null, title, path)
        : hist.pushState(null, title, path)
      // so we need to set it manually
      doc.title = title
      routeFound = false
      emit()
      return routeFound
    }
  
    // Server-side usage: directly execute handlers for the path
    return central[TRIGGER]('emit', getPathFromBase(path))
  }
  
  /**
   * Go to path or set action
   * a single string:                go there
   * two strings:                    go there with setting a title
   * two strings and boolean:        replace history with setting a title
   * a single function:              set an action on the default route
   * a string/RegExp and a function: set an action on the route
   * @param {(string|function)} first - path / action / filter
   * @param {(string|RegExp|function)} second - title / action
   * @param {boolean} third - replace flag
   */
  prot.m = function(first, second, third) {
    if (isString(first) && (!second || isString(second))) go(first, second, third || false)
    else if (second) this.r(first, second)
    else this.r('@', first)
  }
  
  /**
   * Stop routing
   */
  prot.s = function() {
    this.off('*')
    this.$ = []
  }
  
  /**
   * Emit
   * @param {string} path - path
   */
  prot.e = function(path) {
    this.$.concat('@').some(function(filter) {
      var args = (filter == '@' ? parser : secondParser)(normalize(path), normalize(filter))
      if (typeof args != 'undefined') {
        this[TRIGGER].apply(null, [filter].concat(args))
        return routeFound = true // exit from loop
      }
    }, this)
  }
  
  /**
   * Register route
   * @param {string} filter - filter for matching to url
   * @param {function} action - action to register
   */
  prot.r = function(filter, action) {
    if (filter != '@') {
      filter = '/' + normalize(filter)
      this.$.push(filter)
    }
    this.on(filter, action)
  }
  
  var mainRouter = new Router()
  var route = mainRouter.m.bind(mainRouter)
  
  /**
   * Create a sub router
   * @returns {function} the method of a new Router object
   */
  route.create = function() {
    var newSubRouter = new Router()
    // assign sub-router's main method
    var router = newSubRouter.m.bind(newSubRouter)
    // stop only this sub-router
    router.stop = newSubRouter.s.bind(newSubRouter)
    return router
  }
  
  /**
   * Set the base of url
   * @param {(str|RegExp)} arg - a new base or '#' or '#!'
   */
  route.base = function(arg) {
    base = arg || '#'
    current = getPathFromBase() // recalculate current path
  }
  
  /** Exec routing right now **/
  route.exec = function() {
    emit(true)
  }
  
  /**
   * Replace the default router to yours
   * @param {function} fn - your parser function
   * @param {function} fn2 - your secondParser function
   */
  route.parser = function(fn, fn2) {
    if (!fn && !fn2) {
      // reset parser for testing...
      parser = DEFAULT_PARSER
      secondParser = DEFAULT_SECOND_PARSER
    }
    if (fn) parser = fn
    if (fn2) secondParser = fn2
  }
  
  /**
   * Helper function to get url query as an object
   * @returns {object} parsed query
   */
  route.query = function() {
    var q = {}
    var href = loc.href || current
    href[REPLACE](/[?&](.+?)=([^&]*)/g, function(_, k, v) { q[k] = v })
    return q
  }
  
  /** Stop routing **/
  route.stop = function () {
    if (started) {
      if (win) {
        win[REMOVE_EVENT_LISTENER](POPSTATE, debouncedEmit)
        win[REMOVE_EVENT_LISTENER](HASHCHANGE, debouncedEmit)
        doc[REMOVE_EVENT_LISTENER](clickEvent, click)
      }
      central[TRIGGER]('stop')
      started = false
    }
  }
  
  /**
   * Start routing
   * @param {boolean} autoExec - automatically exec after starting if true
   */
  route.start = function (autoExec) {
    if (!started) {
      if (win) {
        if (document.readyState == 'complete') start(autoExec)
        // the timeout is needed to solve
        // a weird safari bug https://github.com/riot/route/issues/33
        else win[ADD_EVENT_LISTENER]('load', function() {
          setTimeout(function() { start(autoExec) }, 1)
        })
      }
      started = true
    }
  }
  
  /** Prepare the router **/
  route.base()
  route.parser()
  
  riot.route = route
  })(riot)
  /* istanbul ignore next */
  
  /**
   * The riot template engine
   * @version v2.3.22
   */
  
  /**
   * riot.util.brackets
   *
   * - `brackets    ` - Returns a string or regex based on its parameter
   * - `brackets.set` - Change the current riot brackets
   *
   * @module
   */
  
  var brackets = (function (UNDEF) {
  
    var
      REGLOB = 'g',
  
      R_MLCOMMS = /\/\*[^*]*\*+(?:[^*\/][^*]*\*+)*\//g,
  
      R_STRINGS = /"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'/g,
  
      S_QBLOCKS = R_STRINGS.source + '|' +
        /(?:\breturn\s+|(?:[$\w\)\]]|\+\+|--)\s*(\/)(?![*\/]))/.source + '|' +
        /\/(?=[^*\/])[^[\/\\]*(?:(?:\[(?:\\.|[^\]\\]*)*\]|\\.)[^[\/\\]*)*?(\/)[gim]*/.source,
  
      FINDBRACES = {
        '(': RegExp('([()])|'   + S_QBLOCKS, REGLOB),
        '[': RegExp('([[\\]])|' + S_QBLOCKS, REGLOB),
        '{': RegExp('([{}])|'   + S_QBLOCKS, REGLOB)
      },
  
      DEFAULT = '{ }'
  
    var _pairs = [
      '{', '}',
      '{', '}',
      /{[^}]*}/,
      /\\([{}])/g,
      /\\({)|{/g,
      RegExp('\\\\(})|([[({])|(})|' + S_QBLOCKS, REGLOB),
      DEFAULT,
      /^\s*{\^?\s*([$\w]+)(?:\s*,\s*(\S+))?\s+in\s+(\S.*)\s*}/,
      /(^|[^\\]){=[\S\s]*?}/
    ]
  
    var
      cachedBrackets = UNDEF,
      _regex,
      _cache = [],
      _settings
  
    function _loopback (re) { return re }
  
    function _rewrite (re, bp) {
      if (!bp) bp = _cache
      return new RegExp(
        re.source.replace(/{/g, bp[2]).replace(/}/g, bp[3]), re.global ? REGLOB : ''
      )
    }
  
    function _create (pair) {
      if (pair === DEFAULT) return _pairs
  
      var arr = pair.split(' ')
  
      if (arr.length !== 2 || /[\x00-\x1F<>a-zA-Z0-9'",;\\]/.test(pair)) {
        throw new Error('Unsupported brackets "' + pair + '"')
      }
      arr = arr.concat(pair.replace(/(?=[[\]()*+?.^$|])/g, '\\').split(' '))
  
      arr[4] = _rewrite(arr[1].length > 1 ? /{[\S\s]*?}/ : _pairs[4], arr)
      arr[5] = _rewrite(pair.length > 3 ? /\\({|})/g : _pairs[5], arr)
      arr[6] = _rewrite(_pairs[6], arr)
      arr[7] = RegExp('\\\\(' + arr[3] + ')|([[({])|(' + arr[3] + ')|' + S_QBLOCKS, REGLOB)
      arr[8] = pair
      return arr
    }
  
    function _brackets (reOrIdx) {
      return reOrIdx instanceof RegExp ? _regex(reOrIdx) : _cache[reOrIdx]
    }
  
    _brackets.split = function split (str, tmpl, _bp) {
      // istanbul ignore next: _bp is for the compiler
      if (!_bp) _bp = _cache
  
      var
        parts = [],
        match,
        isexpr,
        start,
        pos,
        re = _bp[6]
  
      isexpr = start = re.lastIndex = 0
  
      while ((match = re.exec(str))) {
  
        pos = match.index
  
        if (isexpr) {
  
          if (match[2]) {
            re.lastIndex = skipBraces(str, match[2], re.lastIndex)
            continue
          }
          if (!match[3]) {
            continue
          }
        }
  
        if (!match[1]) {
          unescapeStr(str.slice(start, pos))
          start = re.lastIndex
          re = _bp[6 + (isexpr ^= 1)]
          re.lastIndex = start
        }
      }
  
      if (str && start < str.length) {
        unescapeStr(str.slice(start))
      }
  
      return parts
  
      function unescapeStr (s) {
        if (tmpl || isexpr) {
          parts.push(s && s.replace(_bp[5], '$1'))
        } else {
          parts.push(s)
        }
      }
  
      function skipBraces (s, ch, ix) {
        var
          match,
          recch = FINDBRACES[ch]
  
        recch.lastIndex = ix
        ix = 1
        while ((match = recch.exec(s))) {
          if (match[1] &&
            !(match[1] === ch ? ++ix : --ix)) break
        }
        return ix ? s.length : recch.lastIndex
      }
    }
  
    _brackets.hasExpr = function hasExpr (str) {
      return _cache[4].test(str)
    }
  
    _brackets.loopKeys = function loopKeys (expr) {
      var m = expr.match(_cache[9])
  
      return m
        ? { key: m[1], pos: m[2], val: _cache[0] + m[3].trim() + _cache[1] }
        : { val: expr.trim() }
    }
  
    _brackets.array = function array (pair) {
      return pair ? _create(pair) : _cache
    }
  
    function _reset (pair) {
      if ((pair || (pair = DEFAULT)) !== _cache[8]) {
        _cache = _create(pair)
        _regex = pair === DEFAULT ? _loopback : _rewrite
        _cache[9] = _regex(_pairs[9])
      }
      cachedBrackets = pair
    }
  
    function _setSettings (o) {
      var b
  
      o = o || {}
      b = o.brackets
      Object.defineProperty(o, 'brackets', {
        set: _reset,
        get: function () { return cachedBrackets },
        enumerable: true
      })
      _settings = o
      _reset(b)
    }
  
    Object.defineProperty(_brackets, 'settings', {
      set: _setSettings,
      get: function () { return _settings }
    })
  
    /* istanbul ignore next: in the browser riot is always in the scope */
    _brackets.settings = typeof riot !== 'undefined' && riot.settings || {}
    _brackets.set = _reset
  
    _brackets.R_STRINGS = R_STRINGS
    _brackets.R_MLCOMMS = R_MLCOMMS
    _brackets.S_QBLOCKS = S_QBLOCKS
  
    return _brackets
  
  })()
  
  /**
   * @module tmpl
   *
   * tmpl          - Root function, returns the template value, render with data
   * tmpl.hasExpr  - Test the existence of a expression inside a string
   * tmpl.loopKeys - Get the keys for an 'each' loop (used by `_each`)
   */
  
  var tmpl = (function () {
  
    var _cache = {}
  
    function _tmpl (str, data) {
      if (!str) return str
  
      return (_cache[str] || (_cache[str] = _create(str))).call(data, _logErr)
    }
  
    _tmpl.haveRaw = brackets.hasRaw
  
    _tmpl.hasExpr = brackets.hasExpr
  
    _tmpl.loopKeys = brackets.loopKeys
  
    _tmpl.errorHandler = null
  
    function _logErr (err, ctx) {
  
      if (_tmpl.errorHandler) {
  
        err.riotData = {
          tagName: ctx && ctx.root && ctx.root.tagName,
          _riot_id: ctx && ctx._riot_id  //eslint-disable-line camelcase
        }
        _tmpl.errorHandler(err)
      }
    }
  
    function _create (str) {
      var expr = _getTmpl(str)
  
      if (expr.slice(0, 11) !== 'try{return ') expr = 'return ' + expr
  
      return new Function('E', expr + ';')    //eslint-disable-line no-new-func
    }
  
    var
      CH_IDEXPR = '\u2057',
      RE_CSNAME = /^(?:(-?[_A-Za-z\xA0-\xFF][-\w\xA0-\xFF]*)|\u2057(\d+)~):/,
      RE_QBLOCK = RegExp(brackets.S_QBLOCKS, 'g'),
      RE_DQUOTE = /\u2057/g,
      RE_QBMARK = /\u2057(\d+)~/g
  
    function _getTmpl (str) {
      var
        qstr = [],
        expr,
        parts = brackets.split(str.replace(RE_DQUOTE, '"'), 1)
  
      if (parts.length > 2 || parts[0]) {
        var i, j, list = []
  
        for (i = j = 0; i < parts.length; ++i) {
  
          expr = parts[i]
  
          if (expr && (expr = i & 1
  
              ? _parseExpr(expr, 1, qstr)
  
              : '"' + expr
                  .replace(/\\/g, '\\\\')
                  .replace(/\r\n?|\n/g, '\\n')
                  .replace(/"/g, '\\"') +
                '"'
  
            )) list[j++] = expr
  
        }
  
        expr = j < 2 ? list[0]
             : '[' + list.join(',') + '].join("")'
  
      } else {
  
        expr = _parseExpr(parts[1], 0, qstr)
      }
  
      if (qstr[0]) {
        expr = expr.replace(RE_QBMARK, function (_, pos) {
          return qstr[pos]
            .replace(/\r/g, '\\r')
            .replace(/\n/g, '\\n')
        })
      }
      return expr
    }
  
    var
      RE_BREND = {
        '(': /[()]/g,
        '[': /[[\]]/g,
        '{': /[{}]/g
      }
  
    function _parseExpr (expr, asText, qstr) {
  
      expr = expr
            .replace(RE_QBLOCK, function (s, div) {
              return s.length > 2 && !div ? CH_IDEXPR + (qstr.push(s) - 1) + '~' : s
            })
            .replace(/\s+/g, ' ').trim()
            .replace(/\ ?([[\({},?\.:])\ ?/g, '$1')
  
      if (expr) {
        var
          list = [],
          cnt = 0,
          match
  
        while (expr &&
              (match = expr.match(RE_CSNAME)) &&
              !match.index
          ) {
          var
            key,
            jsb,
            re = /,|([[{(])|$/g
  
          expr = RegExp.rightContext
          key  = match[2] ? qstr[match[2]].slice(1, -1).trim().replace(/\s+/g, ' ') : match[1]
  
          while (jsb = (match = re.exec(expr))[1]) skipBraces(jsb, re)
  
          jsb  = expr.slice(0, match.index)
          expr = RegExp.rightContext
  
          list[cnt++] = _wrapExpr(jsb, 1, key)
        }
  
        expr = !cnt ? _wrapExpr(expr, asText)
             : cnt > 1 ? '[' + list.join(',') + '].join(" ").trim()' : list[0]
      }
      return expr
  
      function skipBraces (ch, re) {
        var
          mm,
          lv = 1,
          ir = RE_BREND[ch]
  
        ir.lastIndex = re.lastIndex
        while (mm = ir.exec(expr)) {
          if (mm[0] === ch) ++lv
          else if (!--lv) break
        }
        re.lastIndex = lv ? expr.length : ir.lastIndex
      }
    }
  
    // istanbul ignore next: not both
    var // eslint-disable-next-line max-len
      JS_CONTEXT = '"in this?this:' + (typeof window !== 'object' ? 'global' : 'window') + ').',
      JS_VARNAME = /[,{][$\w]+:|(^ *|[^$\w\.])(?!(?:typeof|true|false|null|undefined|in|instanceof|is(?:Finite|NaN)|void|NaN|new|Date|RegExp|Math)(?![$\w]))([$_A-Za-z][$\w]*)/g,
      JS_NOPROPS = /^(?=(\.[$\w]+))\1(?:[^.[(]|$)/
  
    function _wrapExpr (expr, asText, key) {
      var tb
  
      expr = expr.replace(JS_VARNAME, function (match, p, mvar, pos, s) {
        if (mvar) {
          pos = tb ? 0 : pos + match.length
  
          if (mvar !== 'this' && mvar !== 'global' && mvar !== 'window') {
            match = p + '("' + mvar + JS_CONTEXT + mvar
            if (pos) tb = (s = s[pos]) === '.' || s === '(' || s === '['
          } else if (pos) {
            tb = !JS_NOPROPS.test(s.slice(pos))
          }
        }
        return match
      })
  
      if (tb) {
        expr = 'try{return ' + expr + '}catch(e){E(e,this)}'
      }
  
      if (key) {
  
        expr = (tb
            ? 'function(){' + expr + '}.call(this)' : '(' + expr + ')'
          ) + '?"' + key + '":""'
  
      } else if (asText) {
  
        expr = 'function(v){' + (tb
            ? expr.replace('return ', 'v=') : 'v=(' + expr + ')'
          ) + ';return v||v===0?v:""}.call(this)'
      }
  
      return expr
    }
  
    // istanbul ignore next: compatibility fix for beta versions
    _tmpl.parse = function (s) { return s }
  
    _tmpl.version = brackets.version = 'v2.3.22'
  
    return _tmpl
  
  })()
  
  /*
    lib/browser/tag/mkdom.js
  
    Includes hacks needed for the Internet Explorer version 9 and below
    See: http://kangax.github.io/compat-table/es5/#ie8
         http://codeplanet.io/dropping-ie8/
  */
  var mkdom = (function _mkdom() {
    var
      reHasYield  = /<yield\b/i,
      reYieldAll  = /<yield\s*(?:\/>|>([\S\s]*?)<\/yield\s*>)/ig,
      reYieldSrc  = /<yield\s+to=['"]([^'">]*)['"]\s*>([\S\s]*?)<\/yield\s*>/ig,
      reYieldDest = /<yield\s+from=['"]?([-\w]+)['"]?\s*(?:\/>|>([\S\s]*?)<\/yield\s*>)/ig
    var
      rootEls = { tr: 'tbody', th: 'tr', td: 'tr', col: 'colgroup' },
      tblTags = IE_VERSION && IE_VERSION < 10
        ? SPECIAL_TAGS_REGEX : /^(?:t(?:body|head|foot|[rhd])|caption|col(?:group)?)$/
  
    /**
     * Creates a DOM element to wrap the given content. Normally an `DIV`, but can be
     * also a `TABLE`, `SELECT`, `TBODY`, `TR`, or `COLGROUP` element.
     *
     * @param   {string} templ  - The template coming from the custom tag definition
     * @param   {string} [html] - HTML content that comes from the DOM element where you
     *           will mount the tag, mostly the original tag in the page
     * @returns {HTMLElement} DOM element with _templ_ merged through `YIELD` with the _html_.
     */
    function _mkdom(templ, html) {
      var
        match   = templ && templ.match(/^\s*<([-\w]+)/),
        tagName = match && match[1].toLowerCase(),
        el = mkEl('div')
  
      // replace all the yield tags with the tag inner html
      templ = replaceYield(templ, html)
  
      /* istanbul ignore next */
      if (tblTags.test(tagName))
        el = specialTags(el, templ, tagName)
      else
        el.innerHTML = templ
  
      el.stub = true
  
      return el
    }
  
    /*
      Creates the root element for table or select child elements:
      tr/th/td/thead/tfoot/tbody/caption/col/colgroup/option/optgroup
    */
    function specialTags(el, templ, tagName) {
      var
        select = tagName[0] === 'o',
        parent = select ? 'select>' : 'table>'
  
      // trim() is important here, this ensures we don't have artifacts,
      // so we can check if we have only one element inside the parent
      el.innerHTML = '<' + parent + templ.trim() + '</' + parent
      parent = el.firstChild
  
      // returns the immediate parent if tr/th/td/col is the only element, if not
      // returns the whole tree, as this can include additional elements
      if (select) {
        parent.selectedIndex = -1  // for IE9, compatible w/current riot behavior
      } else {
        // avoids insertion of cointainer inside container (ex: tbody inside tbody)
        var tname = rootEls[tagName]
        if (tname && parent.childElementCount === 1) parent = $(tname, parent)
      }
      return parent
    }
  
    /*
      Replace the yield tag from any tag template with the innerHTML of the
      original tag in the page
    */
    function replaceYield(templ, html) {
      // do nothing if no yield
      if (!reHasYield.test(templ)) return templ
  
      // be careful with #1343 - string on the source having `$1`
      var src = {}
  
      html = html && html.replace(reYieldSrc, function (_, ref, text) {
        src[ref] = src[ref] || text   // preserve first definition
        return ''
      }).trim()
  
      return templ
        .replace(reYieldDest, function (_, ref, def) {  // yield with from - to attrs
          return src[ref] || def || ''
        })
        .replace(reYieldAll, function (_, def) {        // yield without any "from"
          return html || def || ''
        })
    }
  
    return _mkdom
  
  })()
  
  /**
   * Convert the item looped into an object used to extend the child tag properties
   * @param   { Object } expr - object containing the keys used to extend the children tags
   * @param   { * } key - value to assign to the new object returned
   * @param   { * } val - value containing the position of the item in the array
   * @returns { Object } - new object containing the values of the original item
   *
   * The variables 'key' and 'val' are arbitrary.
   * They depend on the collection type looped (Array, Object)
   * and on the expression used on the each tag
   *
   */
  function mkitem(expr, key, val) {
    var item = {}
    item[expr.key] = key
    if (expr.pos) item[expr.pos] = val
    return item
  }
  
  /**
   * Unmount the redundant tags
   * @param   { Array } items - array containing the current items to loop
   * @param   { Array } tags - array containing all the children tags
   */
  function unmountRedundant(items, tags) {
  
    var i = tags.length,
      j = items.length,
      t
  
    while (i > j) {
      t = tags[--i]
      tags.splice(i, 1)
      t.unmount()
    }
  }
  
  /**
   * Move the nested custom tags in non custom loop tags
   * @param   { Object } child - non custom loop tag
   * @param   { Number } i - current position of the loop tag
   */
  function moveNestedTags(child, i) {
    Object.keys(child.tags).forEach(function(tagName) {
      var tag = child.tags[tagName]
      if (isArray(tag))
        each(tag, function (t) {
          moveChildTag(t, tagName, i)
        })
      else
        moveChildTag(tag, tagName, i)
    })
  }
  
  /**
   * Adds the elements for a virtual tag
   * @param { Tag } tag - the tag whose root's children will be inserted or appended
   * @param { Node } src - the node that will do the inserting or appending
   * @param { Tag } target - only if inserting, insert before this tag's first child
   */
  function addVirtual(tag, src, target) {
    var el = tag._root, sib
    tag._virts = []
    while (el) {
      sib = el.nextSibling
      if (target)
        src.insertBefore(el, target._root)
      else
        src.appendChild(el)
  
      tag._virts.push(el) // hold for unmounting
      el = sib
    }
  }
  
  /**
   * Move virtual tag and all child nodes
   * @param { Tag } tag - first child reference used to start move
   * @param { Node } src  - the node that will do the inserting
   * @param { Tag } target - insert before this tag's first child
   * @param { Number } len - how many child nodes to move
   */
  function moveVirtual(tag, src, target, len) {
    var el = tag._root, sib, i = 0
    for (; i < len; i++) {
      sib = el.nextSibling
      src.insertBefore(el, target._root)
      el = sib
    }
  }
  
  
  /**
   * Manage tags having the 'each'
   * @param   { Object } dom - DOM node we need to loop
   * @param   { Tag } parent - parent tag instance where the dom node is contained
   * @param   { String } expr - string contained in the 'each' attribute
   */
  function _each(dom, parent, expr) {
  
    // remove the each property from the original tag
    remAttr(dom, 'each')
  
    var mustReorder = typeof getAttr(dom, 'no-reorder') !== T_STRING || remAttr(dom, 'no-reorder'),
      tagName = getTagName(dom),
      impl = __tagImpl[tagName] || { tmpl: dom.outerHTML },
      useRoot = SPECIAL_TAGS_REGEX.test(tagName),
      root = dom.parentNode,
      ref = document.createTextNode(''),
      child = getTag(dom),
      isOption = tagName.toLowerCase() === 'option', // the option tags must be treated differently
      tags = [],
      oldItems = [],
      hasKeys,
      isVirtual = dom.tagName == 'VIRTUAL'
  
    // parse the each expression
    expr = tmpl.loopKeys(expr)
  
    // insert a marked where the loop tags will be injected
    root.insertBefore(ref, dom)
  
    // clean template code
    parent.one('before-mount', function () {
  
      // remove the original DOM node
      dom.parentNode.removeChild(dom)
      if (root.stub) root = parent.root
  
    }).on('update', function () {
      // get the new items collection
      var items = tmpl(expr.val, parent),
        // create a fragment to hold the new DOM nodes to inject in the parent tag
        frag = document.createDocumentFragment()
  
      // object loop. any changes cause full redraw
      if (!isArray(items)) {
        hasKeys = items || false
        items = hasKeys ?
          Object.keys(items).map(function (key) {
            return mkitem(expr, key, items[key])
          }) : []
      }
  
      // loop all the new items
      var i = 0,
        itemsLength = items.length
  
      for (; i < itemsLength; i++) {
        // reorder only if the items are objects
        var
          item = items[i],
          _mustReorder = mustReorder && item instanceof Object && !hasKeys,
          oldPos = oldItems.indexOf(item),
          pos = ~oldPos && _mustReorder ? oldPos : i,
          // does a tag exist in this position?
          tag = tags[pos]
  
        item = !hasKeys && expr.key ? mkitem(expr, item, i) : item
  
        // new tag
        if (
          !_mustReorder && !tag // with no-reorder we just update the old tags
          ||
          _mustReorder && !~oldPos || !tag // by default we always try to reorder the DOM elements
        ) {
  
          tag = new Tag(impl, {
            parent: parent,
            isLoop: true,
            hasImpl: !!__tagImpl[tagName],
            root: useRoot ? root : dom.cloneNode(),
            item: item
          }, dom.innerHTML)
  
          tag.mount()
  
          if (isVirtual) tag._root = tag.root.firstChild // save reference for further moves or inserts
          // this tag must be appended
          if (i == tags.length || !tags[i]) { // fix 1581
            if (isVirtual)
              addVirtual(tag, frag)
            else frag.appendChild(tag.root)
          }
          // this tag must be insert
          else {
            if (isVirtual)
              addVirtual(tag, root, tags[i])
            else root.insertBefore(tag.root, tags[i].root) // #1374 some browsers reset selected here
            oldItems.splice(i, 0, item)
          }
  
          tags.splice(i, 0, tag)
          pos = i // handled here so no move
        } else tag.update(item, true)
  
        // reorder the tag if it's not located in its previous position
        if (
          pos !== i && _mustReorder &&
          tags[i] // fix 1581 unable to reproduce it in a test!
        ) {
          // update the DOM
          if (isVirtual)
            moveVirtual(tag, root, tags[i], dom.childNodes.length)
          else root.insertBefore(tag.root, tags[i].root)
          // update the position attribute if it exists
          if (expr.pos)
            tag[expr.pos] = i
          // move the old tag instance
          tags.splice(i, 0, tags.splice(pos, 1)[0])
          // move the old item
          oldItems.splice(i, 0, oldItems.splice(pos, 1)[0])
          // if the loop tags are not custom
          // we need to move all their custom tags into the right position
          if (!child && tag.tags) moveNestedTags(tag, i)
        }
  
        // cache the original item to use it in the events bound to this node
        // and its children
        tag._item = item
        // cache the real parent tag internally
        defineProperty(tag, '_parent', parent)
      }
  
      // remove the redundant tags
      unmountRedundant(items, tags)
  
      // insert the new nodes
      if (isOption) {
        root.appendChild(frag)
  
        // #1374 FireFox bug in <option selected={expression}>
        if (FIREFOX && !root.multiple) {
          for (var n = 0; n < root.length; n++) {
            if (root[n].__riot1374) {
              root.selectedIndex = n  // clear other options
              delete root[n].__riot1374
              break
            }
          }
        }
      }
      else root.insertBefore(frag, ref)
  
      // set the 'tags' property of the parent tag
      // if child is 'undefined' it means that we don't need to set this property
      // for example:
      // we don't need store the `myTag.tags['div']` property if we are looping a div tag
      // but we need to track the `myTag.tags['child']` property looping a custom child node named `child`
      if (child) parent.tags[tagName] = tags
  
      // clone the items array
      oldItems = items.slice()
  
    })
  
  }
  /**
   * Object that will be used to inject and manage the css of every tag instance
   */
  var styleManager = (function(_riot) {
  
    if (!window) return { // skip injection on the server
      add: function () {},
      inject: function () {}
    }
  
    var styleNode = (function () {
      // create a new style element with the correct type
      var newNode = mkEl('style')
      setAttr(newNode, 'type', 'text/css')
  
      // replace any user node or insert the new one into the head
      var userNode = $('style[type=riot]')
      if (userNode) {
        if (userNode.id) newNode.id = userNode.id
        userNode.parentNode.replaceChild(newNode, userNode)
      }
      else document.getElementsByTagName('head')[0].appendChild(newNode)
  
      return newNode
    })()
  
    // Create cache and shortcut to the correct property
    var cssTextProp = styleNode.styleSheet,
      stylesToInject = ''
  
    // Expose the style node in a non-modificable property
    Object.defineProperty(_riot, 'styleNode', {
      value: styleNode,
      writable: true
    })
  
    /**
     * Public api
     */
    return {
      /**
       * Save a tag style to be later injected into DOM
       * @param   { String } css [description]
       */
      add: function(css) {
        stylesToInject += css
      },
      /**
       * Inject all previously saved tag styles into DOM
       * innerHTML seems slow: http://jsperf.com/riot-insert-style
       */
      inject: function() {
        if (stylesToInject) {
          if (cssTextProp) cssTextProp.cssText += stylesToInject
          else styleNode.innerHTML += stylesToInject
          stylesToInject = ''
        }
      }
    }
  
  })(riot)
  
  
  function parseNamedElements(root, tag, childTags, forceParsingNamed) {
  
    walk(root, function(dom) {
      if (dom.nodeType == 1) {
        dom.isLoop = dom.isLoop ||
                    (dom.parentNode && dom.parentNode.isLoop || getAttr(dom, 'each'))
                      ? 1 : 0
  
        // custom child tag
        if (childTags) {
          var child = getTag(dom)
  
          if (child && !dom.isLoop)
            childTags.push(initChildTag(child, {root: dom, parent: tag}, dom.innerHTML, tag))
        }
  
        if (!dom.isLoop || forceParsingNamed)
          setNamed(dom, tag, [])
      }
  
    })
  
  }
  
  function parseExpressions(root, tag, expressions) {
  
    function addExpr(dom, val, extra) {
      if (tmpl.hasExpr(val)) {
        expressions.push(extend({ dom: dom, expr: val }, extra))
      }
    }
  
    walk(root, function(dom) {
      var type = dom.nodeType,
        attr
  
      // text node
      if (type == 3 && dom.parentNode.tagName != 'STYLE') addExpr(dom, dom.nodeValue)
      if (type != 1) return
  
      /* element */
  
      // loop
      attr = getAttr(dom, 'each')
  
      if (attr) { _each(dom, tag, attr); return false }
  
      // attribute expressions
      each(dom.attributes, function(attr) {
        var name = attr.name,
          bool = name.split('__')[1]
  
        addExpr(dom, attr.value, { attr: bool || name, bool: bool })
        if (bool) { remAttr(dom, name); return false }
  
      })
  
      // skip custom tags
      if (getTag(dom)) return false
  
    })
  
  }
  function Tag(impl, conf, innerHTML) {
  
    var self = riot.observable(this),
      opts = inherit(conf.opts) || {},
      parent = conf.parent,
      isLoop = conf.isLoop,
      hasImpl = conf.hasImpl,
      item = cleanUpData(conf.item),
      expressions = [],
      childTags = [],
      root = conf.root,
      tagName = root.tagName.toLowerCase(),
      attr = {},
      propsInSyncWithParent = [],
      dom
  
    // only call unmount if we have a valid __tagImpl (has name property)
    if (impl.name && root._tag) root._tag.unmount(true)
  
    // not yet mounted
    this.isMounted = false
    root.isLoop = isLoop
  
    // keep a reference to the tag just created
    // so we will be able to mount this tag multiple times
    root._tag = this
  
    // create a unique id to this tag
    // it could be handy to use it also to improve the virtual dom rendering speed
    defineProperty(this, '_riot_id', ++__uid) // base 1 allows test !t._riot_id
  
    extend(this, { parent: parent, root: root, opts: opts, tags: {} }, item)
  
    // grab attributes
    each(root.attributes, function(el) {
      var val = el.value
      // remember attributes with expressions only
      if (tmpl.hasExpr(val)) attr[el.name] = val
    })
  
    dom = mkdom(impl.tmpl, innerHTML)
  
    // options
    function updateOpts() {
      var ctx = hasImpl && isLoop ? self : parent || self
  
      // update opts from current DOM attributes
      each(root.attributes, function(el) {
        var val = el.value
        opts[toCamel(el.name)] = tmpl.hasExpr(val) ? tmpl(val, ctx) : val
      })
      // recover those with expressions
      each(Object.keys(attr), function(name) {
        opts[toCamel(name)] = tmpl(attr[name], ctx)
      })
    }
  
    function normalizeData(data) {
      for (var key in item) {
        if (typeof self[key] !== T_UNDEF && isWritable(self, key))
          self[key] = data[key]
      }
    }
  
    function inheritFromParent () {
      if (!self.parent || !isLoop) return
      each(Object.keys(self.parent), function(k) {
        // some properties must be always in sync with the parent tag
        var mustSync = !contains(RESERVED_WORDS_BLACKLIST, k) && contains(propsInSyncWithParent, k)
        if (typeof self[k] === T_UNDEF || mustSync) {
          // track the property to keep in sync
          // so we can keep it updated
          if (!mustSync) propsInSyncWithParent.push(k)
          self[k] = self.parent[k]
        }
      })
    }
  
    /**
     * Update the tag expressions and options
     * @param   { * }  data - data we want to use to extend the tag properties
     * @param   { Boolean } isInherited - is this update coming from a parent tag?
     * @returns { self }
     */
    defineProperty(this, 'update', function(data, isInherited) {
  
      // make sure the data passed will not override
      // the component core methods
      data = cleanUpData(data)
      // inherit properties from the parent
      inheritFromParent()
      // normalize the tag properties in case an item object was initially passed
      if (data && isObject(item)) {
        normalizeData(data)
        item = data
      }
      extend(self, data)
      updateOpts()
      self.trigger('update', data)
      update(expressions, self)
  
      // the updated event will be triggered
      // once the DOM will be ready and all the re-flows are completed
      // this is useful if you want to get the "real" root properties
      // 4 ex: root.offsetWidth ...
      if (isInherited && self.parent)
        // closes #1599
        self.parent.one('updated', function() { self.trigger('updated') })
      else rAF(function() { self.trigger('updated') })
  
      return this
    })
  
    defineProperty(this, 'mixin', function() {
      each(arguments, function(mix) {
        var instance
  
        mix = typeof mix === T_STRING ? riot.mixin(mix) : mix
  
        // check if the mixin is a function
        if (isFunction(mix)) {
          // create the new mixin instance
          instance = new mix()
          // save the prototype to loop it afterwards
          mix = mix.prototype
        } else instance = mix
  
        // loop the keys in the function prototype or the all object keys
        each(Object.getOwnPropertyNames(mix), function(key) {
          // bind methods to self
          if (key != 'init')
            self[key] = isFunction(instance[key]) ?
                          instance[key].bind(self) :
                          instance[key]
        })
  
        // init method will be called automatically
        if (instance.init) instance.init.bind(self)()
      })
      return this
    })
  
    defineProperty(this, 'mount', function() {
  
      updateOpts()
  
      // add global mixin
      var globalMixin = riot.mixin(GLOBAL_MIXIN)
      if (globalMixin) self.mixin(globalMixin)
  
      // initialiation
      if (impl.fn) impl.fn.call(self, opts)
  
      // parse layout after init. fn may calculate args for nested custom tags
      parseExpressions(dom, self, expressions)
  
      // mount the child tags
      toggle(true)
  
      // update the root adding custom attributes coming from the compiler
      // it fixes also #1087
      if (impl.attrs)
        walkAttributes(impl.attrs, function (k, v) { setAttr(root, k, v) })
      if (impl.attrs || hasImpl)
        parseExpressions(self.root, self, expressions)
  
      if (!self.parent || isLoop) self.update(item)
  
      // internal use only, fixes #403
      self.trigger('before-mount')
  
      if (isLoop && !hasImpl) {
        // update the root attribute for the looped elements
        root = dom.firstChild
      } else {
        while (dom.firstChild) root.appendChild(dom.firstChild)
        if (root.stub) root = parent.root
      }
  
      defineProperty(self, 'root', root)
  
      // parse the named dom nodes in the looped child
      // adding them to the parent as well
      if (isLoop)
        parseNamedElements(self.root, self.parent, null, true)
  
      // if it's not a child tag we can trigger its mount event
      if (!self.parent || self.parent.isMounted) {
        self.isMounted = true
        self.trigger('mount')
      }
      // otherwise we need to wait that the parent event gets triggered
      else self.parent.one('mount', function() {
        // avoid to trigger the `mount` event for the tags
        // not visible included in an if statement
        if (!isInStub(self.root)) {
          self.parent.isMounted = self.isMounted = true
          self.trigger('mount')
        }
      })
    })
  
  
    defineProperty(this, 'unmount', function(keepRootTag) {
      var el = root,
        p = el.parentNode,
        ptag,
        tagIndex = __virtualDom.indexOf(self)
  
      self.trigger('before-unmount')
  
      // remove this tag instance from the global virtualDom variable
      if (~tagIndex)
        __virtualDom.splice(tagIndex, 1)
  
      if (p) {
  
        if (parent) {
          ptag = getImmediateCustomParentTag(parent)
          // remove this tag from the parent tags object
          // if there are multiple nested tags with same name..
          // remove this element form the array
          if (isArray(ptag.tags[tagName]))
            each(ptag.tags[tagName], function(tag, i) {
              if (tag._riot_id == self._riot_id)
                ptag.tags[tagName].splice(i, 1)
            })
          else
            // otherwise just delete the tag instance
            ptag.tags[tagName] = undefined
        }
  
        else
          while (el.firstChild) el.removeChild(el.firstChild)
  
        if (!keepRootTag)
          p.removeChild(el)
        else {
          // the riot-tag and the data-is attributes aren't needed anymore, remove them
          remAttr(p, RIOT_TAG_IS)
          remAttr(p, RIOT_TAG) // this will be removed in riot 3.0.0
        }
  
      }
  
      if (this._virts) {
        each(this._virts, function(v) {
          if (v.parentNode) v.parentNode.removeChild(v)
        })
      }
  
      self.trigger('unmount')
      toggle()
      self.off('*')
      self.isMounted = false
      delete root._tag
  
    })
  
    // proxy function to bind updates
    // dispatched from a parent tag
    function onChildUpdate(data) { self.update(data, true) }
  
    function toggle(isMount) {
  
      // mount/unmount children
      each(childTags, function(child) { child[isMount ? 'mount' : 'unmount']() })
  
      // listen/unlisten parent (events flow one way from parent to children)
      if (!parent) return
      var evt = isMount ? 'on' : 'off'
  
      // the loop tags will be always in sync with the parent automatically
      if (isLoop)
        parent[evt]('unmount', self.unmount)
      else {
        parent[evt]('update', onChildUpdate)[evt]('unmount', self.unmount)
      }
    }
  
  
    // named elements available for fn
    parseNamedElements(dom, this, childTags)
  
  }
  /**
   * Attach an event to a DOM node
   * @param { String } name - event name
   * @param { Function } handler - event callback
   * @param { Object } dom - dom node
   * @param { Tag } tag - tag instance
   */
  function setEventHandler(name, handler, dom, tag) {
  
    dom[name] = function(e) {
  
      var ptag = tag._parent,
        item = tag._item,
        el
  
      if (!item)
        while (ptag && !item) {
          item = ptag._item
          ptag = ptag._parent
        }
  
      // cross browser event fix
      e = e || window.event
  
      // override the event properties
      if (isWritable(e, 'currentTarget')) e.currentTarget = dom
      if (isWritable(e, 'target')) e.target = e.srcElement
      if (isWritable(e, 'which')) e.which = e.charCode || e.keyCode
  
      e.item = item
  
      // prevent default behaviour (by default)
      if (handler.call(tag, e) !== true && !/radio|check/.test(dom.type)) {
        if (e.preventDefault) e.preventDefault()
        e.returnValue = false
      }
  
      if (!e.preventUpdate) {
        el = item ? getImmediateCustomParentTag(ptag) : tag
        el.update()
      }
  
    }
  
  }
  
  
  /**
   * Insert a DOM node replacing another one (used by if- attribute)
   * @param   { Object } root - parent node
   * @param   { Object } node - node replaced
   * @param   { Object } before - node added
   */
  function insertTo(root, node, before) {
    if (!root) return
    root.insertBefore(before, node)
    root.removeChild(node)
  }
  
  /**
   * Update the expressions in a Tag instance
   * @param   { Array } expressions - expression that must be re evaluated
   * @param   { Tag } tag - tag instance
   */
  function update(expressions, tag) {
  
    each(expressions, function(expr, i) {
  
      var dom = expr.dom,
        attrName = expr.attr,
        value = tmpl(expr.expr, tag),
        parent = expr.dom.parentNode
  
      if (expr.bool) {
        value = !!value
      } else if (value == null) {
        value = ''
      }
  
      // #1638: regression of #1612, update the dom only if the value of the
      // expression was changed
      if (expr.value === value) {
        return
      }
      expr.value = value
  
      // textarea and text nodes has no attribute name
      if (!attrName) {
        // about #815 w/o replace: the browser converts the value to a string,
        // the comparison by "==" does too, but not in the server
        value += ''
        // test for parent avoids error with invalid assignment to nodeValue
        if (parent) {
          if (parent.tagName === 'TEXTAREA') {
            parent.value = value                    // #1113
            if (!IE_VERSION) dom.nodeValue = value  // #1625 IE throws here, nodeValue
          }                                         // will be available on 'updated'
          else dom.nodeValue = value
        }
        return
      }
  
      // ~~#1612: look for changes in dom.value when updating the value~~
      if (attrName === 'value') {
        dom.value = value
        return
      }
  
      // remove original attribute
      remAttr(dom, attrName)
  
      // event handler
      if (isFunction(value)) {
        setEventHandler(attrName, value, dom, tag)
  
      // if- conditional
      } else if (attrName == 'if') {
        var stub = expr.stub,
          add = function() { insertTo(stub.parentNode, stub, dom) },
          remove = function() { insertTo(dom.parentNode, dom, stub) }
  
        // add to DOM
        if (value) {
          if (stub) {
            add()
            dom.inStub = false
            // avoid to trigger the mount event if the tags is not visible yet
            // maybe we can optimize this avoiding to mount the tag at all
            if (!isInStub(dom)) {
              walk(dom, function(el) {
                if (el._tag && !el._tag.isMounted)
                  el._tag.isMounted = !!el._tag.trigger('mount')
              })
            }
          }
        // remove from DOM
        } else {
          stub = expr.stub = stub || document.createTextNode('')
          // if the parentNode is defined we can easily replace the tag
          if (dom.parentNode)
            remove()
          // otherwise we need to wait the updated event
          else (tag.parent || tag).one('updated', remove)
  
          dom.inStub = true
        }
      // show / hide
      } else if (attrName === 'show') {
        dom.style.display = value ? '' : 'none'
  
      } else if (attrName === 'hide') {
        dom.style.display = value ? 'none' : ''
  
      } else if (expr.bool) {
        dom[attrName] = value
        if (value) setAttr(dom, attrName, attrName)
        if (FIREFOX && attrName === 'selected' && dom.tagName === 'OPTION') {
          dom.__riot1374 = value   // #1374
        }
  
      } else if (value === 0 || value && typeof value !== T_OBJECT) {
        // <img src="{ expr }">
        if (startsWith(attrName, RIOT_PREFIX) && attrName != RIOT_TAG) {
          attrName = attrName.slice(RIOT_PREFIX.length)
        }
        setAttr(dom, attrName, value)
      }
  
    })
  
  }
  /**
   * Specialized function for looping an array-like collection with `each={}`
   * @param   { Array } els - collection of items
   * @param   {Function} fn - callback function
   * @returns { Array } the array looped
   */
  function each(els, fn) {
    var len = els ? els.length : 0
  
    for (var i = 0, el; i < len; i++) {
      el = els[i]
      // return false -> current item was removed by fn during the loop
      if (el != null && fn(el, i) === false) i--
    }
    return els
  }
  
  /**
   * Detect if the argument passed is a function
   * @param   { * } v - whatever you want to pass to this function
   * @returns { Boolean } -
   */
  function isFunction(v) {
    return typeof v === T_FUNCTION || false   // avoid IE problems
  }
  
  /**
   * Detect if the argument passed is an object, exclude null.
   * NOTE: Use isObject(x) && !isArray(x) to excludes arrays.
   * @param   { * } v - whatever you want to pass to this function
   * @returns { Boolean } -
   */
  function isObject(v) {
    return v && typeof v === T_OBJECT         // typeof null is 'object'
  }
  
  /**
   * Remove any DOM attribute from a node
   * @param   { Object } dom - DOM node we want to update
   * @param   { String } name - name of the property we want to remove
   */
  function remAttr(dom, name) {
    dom.removeAttribute(name)
  }
  
  /**
   * Convert a string containing dashes to camel case
   * @param   { String } string - input string
   * @returns { String } my-string -> myString
   */
  function toCamel(string) {
    return string.replace(/-(\w)/g, function(_, c) {
      return c.toUpperCase()
    })
  }
  
  /**
   * Get the value of any DOM attribute on a node
   * @param   { Object } dom - DOM node we want to parse
   * @param   { String } name - name of the attribute we want to get
   * @returns { String | undefined } name of the node attribute whether it exists
   */
  function getAttr(dom, name) {
    return dom.getAttribute(name)
  }
  
  /**
   * Set any DOM attribute
   * @param { Object } dom - DOM node we want to update
   * @param { String } name - name of the property we want to set
   * @param { String } val - value of the property we want to set
   */
  function setAttr(dom, name, val) {
    dom.setAttribute(name, val)
  }
  
  /**
   * Detect the tag implementation by a DOM node
   * @param   { Object } dom - DOM node we need to parse to get its tag implementation
   * @returns { Object } it returns an object containing the implementation of a custom tag (template and boot function)
   */
  function getTag(dom) {
    return dom.tagName && __tagImpl[getAttr(dom, RIOT_TAG_IS) ||
      getAttr(dom, RIOT_TAG) || dom.tagName.toLowerCase()]
  }
  /**
   * Add a child tag to its parent into the `tags` object
   * @param   { Object } tag - child tag instance
   * @param   { String } tagName - key where the new tag will be stored
   * @param   { Object } parent - tag instance where the new child tag will be included
   */
  function addChildTag(tag, tagName, parent) {
    var cachedTag = parent.tags[tagName]
  
    // if there are multiple children tags having the same name
    if (cachedTag) {
      // if the parent tags property is not yet an array
      // create it adding the first cached tag
      if (!isArray(cachedTag))
        // don't add the same tag twice
        if (cachedTag !== tag)
          parent.tags[tagName] = [cachedTag]
      // add the new nested tag to the array
      if (!contains(parent.tags[tagName], tag))
        parent.tags[tagName].push(tag)
    } else {
      parent.tags[tagName] = tag
    }
  }
  
  /**
   * Move the position of a custom tag in its parent tag
   * @param   { Object } tag - child tag instance
   * @param   { String } tagName - key where the tag was stored
   * @param   { Number } newPos - index where the new tag will be stored
   */
  function moveChildTag(tag, tagName, newPos) {
    var parent = tag.parent,
      tags
    // no parent no move
    if (!parent) return
  
    tags = parent.tags[tagName]
  
    if (isArray(tags))
      tags.splice(newPos, 0, tags.splice(tags.indexOf(tag), 1)[0])
    else addChildTag(tag, tagName, parent)
  }
  
  /**
   * Create a new child tag including it correctly into its parent
   * @param   { Object } child - child tag implementation
   * @param   { Object } opts - tag options containing the DOM node where the tag will be mounted
   * @param   { String } innerHTML - inner html of the child node
   * @param   { Object } parent - instance of the parent tag including the child custom tag
   * @returns { Object } instance of the new child tag just created
   */
  function initChildTag(child, opts, innerHTML, parent) {
    var tag = new Tag(child, opts, innerHTML),
      tagName = getTagName(opts.root),
      ptag = getImmediateCustomParentTag(parent)
    // fix for the parent attribute in the looped elements
    tag.parent = ptag
    // store the real parent tag
    // in some cases this could be different from the custom parent tag
    // for example in nested loops
    tag._parent = parent
  
    // add this tag to the custom parent tag
    addChildTag(tag, tagName, ptag)
    // and also to the real parent tag
    if (ptag !== parent)
      addChildTag(tag, tagName, parent)
    // empty the child node once we got its template
    // to avoid that its children get compiled multiple times
    opts.root.innerHTML = ''
  
    return tag
  }
  
  /**
   * Loop backward all the parents tree to detect the first custom parent tag
   * @param   { Object } tag - a Tag instance
   * @returns { Object } the instance of the first custom parent tag found
   */
  function getImmediateCustomParentTag(tag) {
    var ptag = tag
    while (!getTag(ptag.root)) {
      if (!ptag.parent) break
      ptag = ptag.parent
    }
    return ptag
  }
  
  /**
   * Helper function to set an immutable property
   * @param   { Object } el - object where the new property will be set
   * @param   { String } key - object key where the new property will be stored
   * @param   { * } value - value of the new property
  * @param   { Object } options - set the propery overriding the default options
   * @returns { Object } - the initial object
   */
  function defineProperty(el, key, value, options) {
    Object.defineProperty(el, key, extend({
      value: value,
      enumerable: false,
      writable: false,
      configurable: true
    }, options))
    return el
  }
  
  /**
   * Get the tag name of any DOM node
   * @param   { Object } dom - DOM node we want to parse
   * @returns { String } name to identify this dom node in riot
   */
  function getTagName(dom) {
    var child = getTag(dom),
      namedTag = getAttr(dom, 'name'),
      tagName = namedTag && !tmpl.hasExpr(namedTag) ?
                  namedTag :
                child ? child.name : dom.tagName.toLowerCase()
  
    return tagName
  }
  
  /**
   * Extend any object with other properties
   * @param   { Object } src - source object
   * @returns { Object } the resulting extended object
   *
   * var obj = { foo: 'baz' }
   * extend(obj, {bar: 'bar', foo: 'bar'})
   * console.log(obj) => {bar: 'bar', foo: 'bar'}
   *
   */
  function extend(src) {
    var obj, args = arguments
    for (var i = 1; i < args.length; ++i) {
      if (obj = args[i]) {
        for (var key in obj) {
          // check if this property of the source object could be overridden
          if (isWritable(src, key))
            src[key] = obj[key]
        }
      }
    }
    return src
  }
  
  /**
   * Check whether an array contains an item
   * @param   { Array } arr - target array
   * @param   { * } item - item to test
   * @returns { Boolean } Does 'arr' contain 'item'?
   */
  function contains(arr, item) {
    return ~arr.indexOf(item)
  }
  
  /**
   * Check whether an object is a kind of array
   * @param   { * } a - anything
   * @returns {Boolean} is 'a' an array?
   */
  function isArray(a) { return Array.isArray(a) || a instanceof Array }
  
  /**
   * Detect whether a property of an object could be overridden
   * @param   { Object }  obj - source object
   * @param   { String }  key - object property
   * @returns { Boolean } is this property writable?
   */
  function isWritable(obj, key) {
    var props = Object.getOwnPropertyDescriptor(obj, key)
    return typeof obj[key] === T_UNDEF || props && props.writable
  }
  
  
  /**
   * With this function we avoid that the internal Tag methods get overridden
   * @param   { Object } data - options we want to use to extend the tag instance
   * @returns { Object } clean object without containing the riot internal reserved words
   */
  function cleanUpData(data) {
    if (!(data instanceof Tag) && !(data && typeof data.trigger == T_FUNCTION))
      return data
  
    var o = {}
    for (var key in data) {
      if (!contains(RESERVED_WORDS_BLACKLIST, key))
        o[key] = data[key]
    }
    return o
  }
  
  /**
   * Walk down recursively all the children tags starting dom node
   * @param   { Object }   dom - starting node where we will start the recursion
   * @param   { Function } fn - callback to transform the child node just found
   */
  function walk(dom, fn) {
    if (dom) {
      // stop the recursion
      if (fn(dom) === false) return
      else {
        dom = dom.firstChild
  
        while (dom) {
          walk(dom, fn)
          dom = dom.nextSibling
        }
      }
    }
  }
  
  /**
   * Minimize risk: only zero or one _space_ between attr & value
   * @param   { String }   html - html string we want to parse
   * @param   { Function } fn - callback function to apply on any attribute found
   */
  function walkAttributes(html, fn) {
    var m,
      re = /([-\w]+) ?= ?(?:"([^"]*)|'([^']*)|({[^}]*}))/g
  
    while (m = re.exec(html)) {
      fn(m[1].toLowerCase(), m[2] || m[3] || m[4])
    }
  }
  
  /**
   * Check whether a DOM node is in stub mode, useful for the riot 'if' directive
   * @param   { Object }  dom - DOM node we want to parse
   * @returns { Boolean } -
   */
  function isInStub(dom) {
    while (dom) {
      if (dom.inStub) return true
      dom = dom.parentNode
    }
    return false
  }
  
  /**
   * Create a generic DOM node
   * @param   { String } name - name of the DOM node we want to create
   * @returns { Object } DOM node just created
   */
  function mkEl(name) {
    return document.createElement(name)
  }
  
  /**
   * Shorter and fast way to select multiple nodes in the DOM
   * @param   { String } selector - DOM selector
   * @param   { Object } ctx - DOM node where the targets of our search will is located
   * @returns { Object } dom nodes found
   */
  function $$(selector, ctx) {
    return (ctx || document).querySelectorAll(selector)
  }
  
  /**
   * Shorter and fast way to select a single node in the DOM
   * @param   { String } selector - unique dom selector
   * @param   { Object } ctx - DOM node where the target of our search will is located
   * @returns { Object } dom node found
   */
  function $(selector, ctx) {
    return (ctx || document).querySelector(selector)
  }
  
  /**
   * Simple object prototypal inheritance
   * @param   { Object } parent - parent object
   * @returns { Object } child instance
   */
  function inherit(parent) {
    function Child() {}
    Child.prototype = parent
    return new Child()
  }
  
  /**
   * Get the name property needed to identify a DOM node in riot
   * @param   { Object } dom - DOM node we need to parse
   * @returns { String | undefined } give us back a string to identify this dom node
   */
  function getNamedKey(dom) {
    return getAttr(dom, 'id') || getAttr(dom, 'name')
  }
  
  /**
   * Set the named properties of a tag element
   * @param { Object } dom - DOM node we need to parse
   * @param { Object } parent - tag instance where the named dom element will be eventually added
   * @param { Array } keys - list of all the tag instance properties
   */
  function setNamed(dom, parent, keys) {
    // get the key value we want to add to the tag instance
    var key = getNamedKey(dom),
      isArr,
      // add the node detected to a tag instance using the named property
      add = function(value) {
        // avoid to override the tag properties already set
        if (contains(keys, key)) return
        // check whether this value is an array
        isArr = isArray(value)
        // if the key was never set
        if (!value)
          // set it once on the tag instance
          parent[key] = dom
        // if it was an array and not yet set
        else if (!isArr || isArr && !contains(value, dom)) {
          // add the dom node into the array
          if (isArr)
            value.push(dom)
          else
            parent[key] = [value, dom]
        }
      }
  
    // skip the elements with no named properties
    if (!key) return
  
    // check whether this key has been already evaluated
    if (tmpl.hasExpr(key))
      // wait the first updated event only once
      parent.one('mount', function() {
        key = getNamedKey(dom)
        add(parent[key])
      })
    else
      add(parent[key])
  
  }
  
  /**
   * Faster String startsWith alternative
   * @param   { String } src - source string
   * @param   { String } str - test string
   * @returns { Boolean } -
   */
  function startsWith(src, str) {
    return src.slice(0, str.length) === str
  }
  
  /**
   * requestAnimationFrame function
   * Adapted from https://gist.github.com/paulirish/1579671, license MIT
   */
  var rAF = (function (w) {
    var raf = w.requestAnimationFrame    ||
              w.mozRequestAnimationFrame || w.webkitRequestAnimationFrame
  
    if (!raf || /iP(ad|hone|od).*OS 6/.test(w.navigator.userAgent)) {  // buggy iOS6
      var lastTime = 0
  
      raf = function (cb) {
        var nowtime = Date.now(), timeout = Math.max(16 - (nowtime - lastTime), 0)
        setTimeout(function () { cb(lastTime = nowtime + timeout) }, timeout)
      }
    }
    return raf
  
  })(window || {})
  
  /**
   * Mount a tag creating new Tag instance
   * @param   { Object } root - dom node where the tag will be mounted
   * @param   { String } tagName - name of the riot tag we want to mount
   * @param   { Object } opts - options to pass to the Tag instance
   * @returns { Tag } a new Tag instance
   */
  function mountTo(root, tagName, opts) {
    var tag = __tagImpl[tagName],
      // cache the inner HTML to fix #855
      innerHTML = root._innerHTML = root._innerHTML || root.innerHTML
  
    // clear the inner html
    root.innerHTML = ''
  
    if (tag && root) tag = new Tag(tag, { root: root, opts: opts }, innerHTML)
  
    if (tag && tag.mount) {
      tag.mount()
      // add this tag to the virtualDom variable
      if (!contains(__virtualDom, tag)) __virtualDom.push(tag)
    }
  
    return tag
  }
  /**
   * Riot public api
   */
  
  // share methods for other riot parts, e.g. compiler
  riot.util = { brackets: brackets, tmpl: tmpl }
  
  /**
   * Create a mixin that could be globally shared across all the tags
   */
  riot.mixin = (function() {
    var mixins = {}
  
    /**
     * Create/Return a mixin by its name
     * @param   { String } name - mixin name (global mixin if missing)
     * @param   { Object } mixin - mixin logic
     * @returns { Object } the mixin logic
     */
    return function(name, mixin) {
      if (isObject(name)) {
        mixin = name
        mixins[GLOBAL_MIXIN] = extend(mixins[GLOBAL_MIXIN] || {}, mixin)
        return
      }
  
      if (!mixin) return mixins[name]
      mixins[name] = mixin
    }
  
  })()
  
  /**
   * Create a new riot tag implementation
   * @param   { String }   name - name/id of the new riot tag
   * @param   { String }   html - tag template
   * @param   { String }   css - custom tag css
   * @param   { String }   attrs - root tag attributes
   * @param   { Function } fn - user function
   * @returns { String } name/id of the tag just created
   */
  riot.tag = function(name, html, css, attrs, fn) {
    if (isFunction(attrs)) {
      fn = attrs
      if (/^[\w\-]+\s?=/.test(css)) {
        attrs = css
        css = ''
      } else attrs = ''
    }
    if (css) {
      if (isFunction(css)) fn = css
      else styleManager.add(css)
    }
    name = name.toLowerCase()
    __tagImpl[name] = { name: name, tmpl: html, attrs: attrs, fn: fn }
    return name
  }
  
  /**
   * Create a new riot tag implementation (for use by the compiler)
   * @param   { String }   name - name/id of the new riot tag
   * @param   { String }   html - tag template
   * @param   { String }   css - custom tag css
   * @param   { String }   attrs - root tag attributes
   * @param   { Function } fn - user function
   * @returns { String } name/id of the tag just created
   */
  riot.tag2 = function(name, html, css, attrs, fn) {
    if (css) styleManager.add(css)
    //if (bpair) riot.settings.brackets = bpair
    __tagImpl[name] = { name: name, tmpl: html, attrs: attrs, fn: fn }
    return name
  }
  
  /**
   * Mount a tag using a specific tag implementation
   * @param   { String } selector - tag DOM selector
   * @param   { String } tagName - tag implementation name
   * @param   { Object } opts - tag logic
   * @returns { Array } new tags instances
   */
  riot.mount = function(selector, tagName, opts) {
  
    var els,
      allTags,
      tags = []
  
    // helper functions
  
    function addRiotTags(arr) {
      var list = ''
      each(arr, function (e) {
        if (!/[^-\w]/.test(e)) {
          e = e.trim().toLowerCase()
          list += ',[' + RIOT_TAG_IS + '="' + e + '"],[' + RIOT_TAG + '="' + e + '"]'
        }
      })
      return list
    }
  
    function selectAllTags() {
      var keys = Object.keys(__tagImpl)
      return keys + addRiotTags(keys)
    }
  
    function pushTags(root) {
      if (root.tagName) {
        var riotTag = getAttr(root, RIOT_TAG_IS) || getAttr(root, RIOT_TAG)
  
        // have tagName? force riot-tag to be the same
        if (tagName && riotTag !== tagName) {
          riotTag = tagName
          setAttr(root, RIOT_TAG_IS, tagName)
          setAttr(root, RIOT_TAG, tagName) // this will be removed in riot 3.0.0
        }
        var tag = mountTo(root, riotTag || root.tagName.toLowerCase(), opts)
  
        if (tag) tags.push(tag)
      } else if (root.length) {
        each(root, pushTags)   // assume nodeList
      }
    }
  
    // ----- mount code -----
  
    // inject styles into DOM
    styleManager.inject()
  
    if (isObject(tagName)) {
      opts = tagName
      tagName = 0
    }
  
    // crawl the DOM to find the tag
    if (typeof selector === T_STRING) {
      if (selector === '*')
        // select all the tags registered
        // and also the tags found with the riot-tag attribute set
        selector = allTags = selectAllTags()
      else
        // or just the ones named like the selector
        selector += addRiotTags(selector.split(/, */))
  
      // make sure to pass always a selector
      // to the querySelectorAll function
      els = selector ? $$(selector) : []
    }
    else
      // probably you have passed already a tag or a NodeList
      els = selector
  
    // select all the registered and mount them inside their root elements
    if (tagName === '*') {
      // get all custom tags
      tagName = allTags || selectAllTags()
      // if the root els it's just a single tag
      if (els.tagName)
        els = $$(tagName, els)
      else {
        // select all the children for all the different root elements
        var nodeList = []
        each(els, function (_el) {
          nodeList.push($$(tagName, _el))
        })
        els = nodeList
      }
      // get rid of the tagName
      tagName = 0
    }
  
    pushTags(els)
  
    return tags
  }
  
  /**
   * Update all the tags instances created
   * @returns { Array } all the tags instances
   */
  riot.update = function() {
    return each(__virtualDom, function(tag) {
      tag.update()
    })
  }
  
  /**
   * Export the Virtual DOM
   */
  riot.vdom = __virtualDom
  
  /**
   * Export the Tag constructor
   */
  riot.Tag = Tag
    // support CommonJS, AMD & browser
    /* istanbul ignore next */
    if (typeof exports === T_OBJECT)
      module.exports = riot
    else if (typeof define === T_FUNCTION && typeof define.amd !== T_UNDEF)
      define(function() { return riot })
    else
      window.riot = riot
  
  })(typeof window != 'undefined' ? window : void 0);
  
  },{}],115:[function(require,module,exports){
  (function (global){
  "use strict"
  // Module export pattern from
  // https://github.com/umdjs/umd/blob/master/returnExports.js
  ;(function (root, factory) {
      if (typeof define === 'function' && define.amd) {
          // AMD. Register as an anonymous module.
          define([], factory);
      } else if (typeof exports === 'object') {
          // Node. Does not work with strict CommonJS, but
          // only CommonJS-like environments that support module.exports,
          // like Node.
          module.exports = factory();
      } else {
          // Browser globals (root is window)
          root.store = factory();
    }
  }(this, function () {
  	
  	// Store.js
  	var store = {},
  		win = (typeof window != 'undefined' ? window : global),
  		doc = win.document,
  		localStorageName = 'localStorage',
  		scriptTag = 'script',
  		storage
  
  	store.disabled = false
  	store.version = '1.3.20'
  	store.set = function(key, value) {}
  	store.get = function(key, defaultVal) {}
  	store.has = function(key) { return store.get(key) !== undefined }
  	store.remove = function(key) {}
  	store.clear = function() {}
  	store.transact = function(key, defaultVal, transactionFn) {
  		if (transactionFn == null) {
  			transactionFn = defaultVal
  			defaultVal = null
  		}
  		if (defaultVal == null) {
  			defaultVal = {}
  		}
  		var val = store.get(key, defaultVal)
  		transactionFn(val)
  		store.set(key, val)
  	}
  	store.getAll = function() {}
  	store.forEach = function() {}
  
  	store.serialize = function(value) {
  		return JSON.stringify(value)
  	}
  	store.deserialize = function(value) {
  		if (typeof value != 'string') { return undefined }
  		try { return JSON.parse(value) }
  		catch(e) { return value || undefined }
  	}
  
  	// Functions to encapsulate questionable FireFox 3.6.13 behavior
  	// when about.config::dom.storage.enabled === false
  	// See https://github.com/marcuswestin/store.js/issues#issue/13
  	function isLocalStorageNameSupported() {
  		try { return (localStorageName in win && win[localStorageName]) }
  		catch(err) { return false }
  	}
  
  	if (isLocalStorageNameSupported()) {
  		storage = win[localStorageName]
  		store.set = function(key, val) {
  			if (val === undefined) { return store.remove(key) }
  			storage.setItem(key, store.serialize(val))
  			return val
  		}
  		store.get = function(key, defaultVal) {
  			var val = store.deserialize(storage.getItem(key))
  			return (val === undefined ? defaultVal : val)
  		}
  		store.remove = function(key) { storage.removeItem(key) }
  		store.clear = function() { storage.clear() }
  		store.getAll = function() {
  			var ret = {}
  			store.forEach(function(key, val) {
  				ret[key] = val
  			})
  			return ret
  		}
  		store.forEach = function(callback) {
  			for (var i=0; i<storage.length; i++) {
  				var key = storage.key(i)
  				callback(key, store.get(key))
  			}
  		}
  	} else if (doc && doc.documentElement.addBehavior) {
  		var storageOwner,
  			storageContainer
  		// Since #userData storage applies only to specific paths, we need to
  		// somehow link our data to a specific path.  We choose /favicon.ico
  		// as a pretty safe option, since all browsers already make a request to
  		// this URL anyway and being a 404 will not hurt us here.  We wrap an
  		// iframe pointing to the favicon in an ActiveXObject(htmlfile) object
  		// (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
  		// since the iframe access rules appear to allow direct access and
  		// manipulation of the document element, even for a 404 page.  This
  		// document can be used instead of the current document (which would
  		// have been limited to the current path) to perform #userData storage.
  		try {
  			storageContainer = new ActiveXObject('htmlfile')
  			storageContainer.open()
  			storageContainer.write('<'+scriptTag+'>document.w=window</'+scriptTag+'><iframe src="/favicon.ico"></iframe>')
  			storageContainer.close()
  			storageOwner = storageContainer.w.frames[0].document
  			storage = storageOwner.createElement('div')
  		} catch(e) {
  			// somehow ActiveXObject instantiation failed (perhaps some special
  			// security settings or otherwse), fall back to per-path storage
  			storage = doc.createElement('div')
  			storageOwner = doc.body
  		}
  		var withIEStorage = function(storeFunction) {
  			return function() {
  				var args = Array.prototype.slice.call(arguments, 0)
  				args.unshift(storage)
  				// See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
  				// and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
  				storageOwner.appendChild(storage)
  				storage.addBehavior('#default#userData')
  				storage.load(localStorageName)
  				var result = storeFunction.apply(store, args)
  				storageOwner.removeChild(storage)
  				return result
  			}
  		}
  
  		// In IE7, keys cannot start with a digit or contain certain chars.
  		// See https://github.com/marcuswestin/store.js/issues/40
  		// See https://github.com/marcuswestin/store.js/issues/83
  		var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g")
  		var ieKeyFix = function(key) {
  			return key.replace(/^d/, '___$&').replace(forbiddenCharsRegex, '___')
  		}
  		store.set = withIEStorage(function(storage, key, val) {
  			key = ieKeyFix(key)
  			if (val === undefined) { return store.remove(key) }
  			storage.setAttribute(key, store.serialize(val))
  			storage.save(localStorageName)
  			return val
  		})
  		store.get = withIEStorage(function(storage, key, defaultVal) {
  			key = ieKeyFix(key)
  			var val = store.deserialize(storage.getAttribute(key))
  			return (val === undefined ? defaultVal : val)
  		})
  		store.remove = withIEStorage(function(storage, key) {
  			key = ieKeyFix(key)
  			storage.removeAttribute(key)
  			storage.save(localStorageName)
  		})
  		store.clear = withIEStorage(function(storage) {
  			var attributes = storage.XMLDocument.documentElement.attributes
  			storage.load(localStorageName)
  			for (var i=attributes.length-1; i>=0; i--) {
  				storage.removeAttribute(attributes[i].name)
  			}
  			storage.save(localStorageName)
  		})
  		store.getAll = function(storage) {
  			var ret = {}
  			store.forEach(function(key, val) {
  				ret[key] = val
  			})
  			return ret
  		}
  		store.forEach = withIEStorage(function(storage, callback) {
  			var attributes = storage.XMLDocument.documentElement.attributes
  			for (var i=0, attr; attr=attributes[i]; ++i) {
  				callback(attr.name, store.deserialize(storage.getAttribute(attr.name)))
  			}
  		})
  	}
  
  	try {
  		var testKey = '__storejs__'
  		store.set(testKey, testKey)
  		if (store.get(testKey) != testKey) { store.disabled = true }
  		store.remove(testKey)
  	} catch(e) {
  		store.disabled = true
  	}
  	store.enabled = !store.disabled
  	
  	return store
  }));
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{}],116:[function(require,module,exports){
  (function (global){
  /*!
   * The buffer module from node.js, for the browser.
   *
   * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
   * @license  MIT
   */
  /* eslint-disable no-proto */
  
  'use strict'
  
  var base64 = require('base64-js')
  var ieee754 = require('ieee754')
  var isArray = require('isarray')
  
  exports.Buffer = Buffer
  exports.SlowBuffer = SlowBuffer
  exports.INSPECT_MAX_BYTES = 50
  Buffer.poolSize = 8192 // not used by this implementation
  
  var rootParent = {}
  
  /**
   * If `Buffer.TYPED_ARRAY_SUPPORT`:
   *   === true    Use Uint8Array implementation (fastest)
   *   === false   Use Object implementation (most compatible, even IE6)
   *
   * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
   * Opera 11.6+, iOS 4.2+.
   *
   * Due to various browser bugs, sometimes the Object implementation will be used even
   * when the browser supports typed arrays.
   *
   * Note:
   *
   *   - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
   *     See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
   *
   *   - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
   *
   *   - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
   *     incorrect length in some situations.
  
   * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
   * get the Object implementation, which is slower but behaves correctly.
   */
  Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
    ? global.TYPED_ARRAY_SUPPORT
    : typedArraySupport()
  
  function typedArraySupport () {
    try {
      var arr = new Uint8Array(1)
      arr.foo = function () { return 42 }
      return arr.foo() === 42 && // typed array instances can be augmented
          typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
          arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
    } catch (e) {
      return false
    }
  }
  
  function kMaxLength () {
    return Buffer.TYPED_ARRAY_SUPPORT
      ? 0x7fffffff
      : 0x3fffffff
  }
  
  /**
   * The Buffer constructor returns instances of `Uint8Array` that have their
   * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
   * `Uint8Array`, so the returned instances will have all the node `Buffer` methods
   * and the `Uint8Array` methods. Square bracket notation works as expected -- it
   * returns a single octet.
   *
   * The `Uint8Array` prototype remains unmodified.
   */
  function Buffer (arg) {
    if (!(this instanceof Buffer)) {
      // Avoid going through an ArgumentsAdaptorTrampoline in the common case.
      if (arguments.length > 1) return new Buffer(arg, arguments[1])
      return new Buffer(arg)
    }
  
    if (!Buffer.TYPED_ARRAY_SUPPORT) {
      this.length = 0
      this.parent = undefined
    }
  
    // Common case.
    if (typeof arg === 'number') {
      return fromNumber(this, arg)
    }
  
    // Slightly less common case.
    if (typeof arg === 'string') {
      return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8')
    }
  
    // Unusual.
    return fromObject(this, arg)
  }
  
  // TODO: Legacy, not needed anymore. Remove in next major version.
  Buffer._augment = function (arr) {
    arr.__proto__ = Buffer.prototype
    return arr
  }
  
  function fromNumber (that, length) {
    that = allocate(that, length < 0 ? 0 : checked(length) | 0)
    if (!Buffer.TYPED_ARRAY_SUPPORT) {
      for (var i = 0; i < length; i++) {
        that[i] = 0
      }
    }
    return that
  }
  
  function fromString (that, string, encoding) {
    if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8'
  
    // Assumption: byteLength() return value is always < kMaxLength.
    var length = byteLength(string, encoding) | 0
    that = allocate(that, length)
  
    that.write(string, encoding)
    return that
  }
  
  function fromObject (that, object) {
    if (Buffer.isBuffer(object)) return fromBuffer(that, object)
  
    if (isArray(object)) return fromArray(that, object)
  
    if (object == null) {
      throw new TypeError('must start with number, buffer, array or string')
    }
  
    if (typeof ArrayBuffer !== 'undefined') {
      if (object.buffer instanceof ArrayBuffer) {
        return fromTypedArray(that, object)
      }
      if (object instanceof ArrayBuffer) {
        return fromArrayBuffer(that, object)
      }
    }
  
    if (object.length) return fromArrayLike(that, object)
  
    return fromJsonObject(that, object)
  }
  
  function fromBuffer (that, buffer) {
    var length = checked(buffer.length) | 0
    that = allocate(that, length)
    buffer.copy(that, 0, 0, length)
    return that
  }
  
  function fromArray (that, array) {
    var length = checked(array.length) | 0
    that = allocate(that, length)
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  // Duplicate of fromArray() to keep fromArray() monomorphic.
  function fromTypedArray (that, array) {
    var length = checked(array.length) | 0
    that = allocate(that, length)
    // Truncating the elements is probably not what people expect from typed
    // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior
    // of the old Buffer constructor.
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  function fromArrayBuffer (that, array) {
    array.byteLength // this throws if `array` is not a valid ArrayBuffer
  
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      // Return an augmented `Uint8Array` instance, for best performance
      that = new Uint8Array(array)
      that.__proto__ = Buffer.prototype
    } else {
      // Fallback: Return an object instance of the Buffer class
      that = fromTypedArray(that, new Uint8Array(array))
    }
    return that
  }
  
  function fromArrayLike (that, array) {
    var length = checked(array.length) | 0
    that = allocate(that, length)
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  // Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object.
  // Returns a zero-length buffer for inputs that don't conform to the spec.
  function fromJsonObject (that, object) {
    var array
    var length = 0
  
    if (object.type === 'Buffer' && isArray(object.data)) {
      array = object.data
      length = checked(array.length) | 0
    }
    that = allocate(that, length)
  
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    Buffer.prototype.__proto__ = Uint8Array.prototype
    Buffer.__proto__ = Uint8Array
    if (typeof Symbol !== 'undefined' && Symbol.species &&
        Buffer[Symbol.species] === Buffer) {
      // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
      Object.defineProperty(Buffer, Symbol.species, {
        value: null,
        configurable: true
      })
    }
  } else {
    // pre-set for values that may exist in the future
    Buffer.prototype.length = undefined
    Buffer.prototype.parent = undefined
  }
  
  function allocate (that, length) {
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      // Return an augmented `Uint8Array` instance, for best performance
      that = new Uint8Array(length)
      that.__proto__ = Buffer.prototype
    } else {
      // Fallback: Return an object instance of the Buffer class
      that.length = length
    }
  
    var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1
    if (fromPool) that.parent = rootParent
  
    return that
  }
  
  function checked (length) {
    // Note: cannot use `length < kMaxLength` here because that fails when
    // length is NaN (which is otherwise coerced to zero.)
    if (length >= kMaxLength()) {
      throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
                           'size: 0x' + kMaxLength().toString(16) + ' bytes')
    }
    return length | 0
  }
  
  function SlowBuffer (subject, encoding) {
    if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding)
  
    var buf = new Buffer(subject, encoding)
    delete buf.parent
    return buf
  }
  
  Buffer.isBuffer = function isBuffer (b) {
    return !!(b != null && b._isBuffer)
  }
  
  Buffer.compare = function compare (a, b) {
    if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
      throw new TypeError('Arguments must be Buffers')
    }
  
    if (a === b) return 0
  
    var x = a.length
    var y = b.length
  
    for (var i = 0, len = Math.min(x, y); i < len; ++i) {
      if (a[i] !== b[i]) {
        x = a[i]
        y = b[i]
        break
      }
    }
  
    if (x < y) return -1
    if (y < x) return 1
    return 0
  }
  
  Buffer.isEncoding = function isEncoding (encoding) {
    switch (String(encoding).toLowerCase()) {
      case 'hex':
      case 'utf8':
      case 'utf-8':
      case 'ascii':
      case 'binary':
      case 'base64':
      case 'raw':
      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return true
      default:
        return false
    }
  }
  
  Buffer.concat = function concat (list, length) {
    if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.')
  
    if (list.length === 0) {
      return new Buffer(0)
    }
  
    var i
    if (length === undefined) {
      length = 0
      for (i = 0; i < list.length; i++) {
        length += list[i].length
      }
    }
  
    var buf = new Buffer(length)
    var pos = 0
    for (i = 0; i < list.length; i++) {
      var item = list[i]
      item.copy(buf, pos)
      pos += item.length
    }
    return buf
  }
  
  function byteLength (string, encoding) {
    if (typeof string !== 'string') string = '' + string
  
    var len = string.length
    if (len === 0) return 0
  
    // Use a for loop to avoid recursion
    var loweredCase = false
    for (;;) {
      switch (encoding) {
        case 'ascii':
        case 'binary':
        // Deprecated
        case 'raw':
        case 'raws':
          return len
        case 'utf8':
        case 'utf-8':
          return utf8ToBytes(string).length
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return len * 2
        case 'hex':
          return len >>> 1
        case 'base64':
          return base64ToBytes(string).length
        default:
          if (loweredCase) return utf8ToBytes(string).length // assume utf8
          encoding = ('' + encoding).toLowerCase()
          loweredCase = true
      }
    }
  }
  Buffer.byteLength = byteLength
  
  function slowToString (encoding, start, end) {
    var loweredCase = false
  
    start = start | 0
    end = end === undefined || end === Infinity ? this.length : end | 0
  
    if (!encoding) encoding = 'utf8'
    if (start < 0) start = 0
    if (end > this.length) end = this.length
    if (end <= start) return ''
  
    while (true) {
      switch (encoding) {
        case 'hex':
          return hexSlice(this, start, end)
  
        case 'utf8':
        case 'utf-8':
          return utf8Slice(this, start, end)
  
        case 'ascii':
          return asciiSlice(this, start, end)
  
        case 'binary':
          return binarySlice(this, start, end)
  
        case 'base64':
          return base64Slice(this, start, end)
  
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return utf16leSlice(this, start, end)
  
        default:
          if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
          encoding = (encoding + '').toLowerCase()
          loweredCase = true
      }
    }
  }
  
  // The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect
  // Buffer instances.
  Buffer.prototype._isBuffer = true
  
  Buffer.prototype.toString = function toString () {
    var length = this.length | 0
    if (length === 0) return ''
    if (arguments.length === 0) return utf8Slice(this, 0, length)
    return slowToString.apply(this, arguments)
  }
  
  Buffer.prototype.equals = function equals (b) {
    if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
    if (this === b) return true
    return Buffer.compare(this, b) === 0
  }
  
  Buffer.prototype.inspect = function inspect () {
    var str = ''
    var max = exports.INSPECT_MAX_BYTES
    if (this.length > 0) {
      str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
      if (this.length > max) str += ' ... '
    }
    return '<Buffer ' + str + '>'
  }
  
  Buffer.prototype.compare = function compare (b) {
    if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
    return Buffer.compare(this, b)
  }
  
  Buffer.prototype.indexOf = function indexOf (val, byteOffset) {
    if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff
    else if (byteOffset < -0x80000000) byteOffset = -0x80000000
    byteOffset >>= 0
  
    if (this.length === 0) return -1
    if (byteOffset >= this.length) return -1
  
    // Negative offsets start from the end of the buffer
    if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0)
  
    if (typeof val === 'string') {
      if (val.length === 0) return -1 // special case: looking for empty string always fails
      return String.prototype.indexOf.call(this, val, byteOffset)
    }
    if (Buffer.isBuffer(val)) {
      return arrayIndexOf(this, val, byteOffset)
    }
    if (typeof val === 'number') {
      if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') {
        return Uint8Array.prototype.indexOf.call(this, val, byteOffset)
      }
      return arrayIndexOf(this, [ val ], byteOffset)
    }
  
    function arrayIndexOf (arr, val, byteOffset) {
      var foundIndex = -1
      for (var i = 0; byteOffset + i < arr.length; i++) {
        if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) {
          if (foundIndex === -1) foundIndex = i
          if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex
        } else {
          foundIndex = -1
        }
      }
      return -1
    }
  
    throw new TypeError('val must be string, number or Buffer')
  }
  
  function hexWrite (buf, string, offset, length) {
    offset = Number(offset) || 0
    var remaining = buf.length - offset
    if (!length) {
      length = remaining
    } else {
      length = Number(length)
      if (length > remaining) {
        length = remaining
      }
    }
  
    // must be an even number of digits
    var strLen = string.length
    if (strLen % 2 !== 0) throw new Error('Invalid hex string')
  
    if (length > strLen / 2) {
      length = strLen / 2
    }
    for (var i = 0; i < length; i++) {
      var parsed = parseInt(string.substr(i * 2, 2), 16)
      if (isNaN(parsed)) throw new Error('Invalid hex string')
      buf[offset + i] = parsed
    }
    return i
  }
  
  function utf8Write (buf, string, offset, length) {
    return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
  }
  
  function asciiWrite (buf, string, offset, length) {
    return blitBuffer(asciiToBytes(string), buf, offset, length)
  }
  
  function binaryWrite (buf, string, offset, length) {
    return asciiWrite(buf, string, offset, length)
  }
  
  function base64Write (buf, string, offset, length) {
    return blitBuffer(base64ToBytes(string), buf, offset, length)
  }
  
  function ucs2Write (buf, string, offset, length) {
    return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
  }
  
  Buffer.prototype.write = function write (string, offset, length, encoding) {
    // Buffer#write(string)
    if (offset === undefined) {
      encoding = 'utf8'
      length = this.length
      offset = 0
    // Buffer#write(string, encoding)
    } else if (length === undefined && typeof offset === 'string') {
      encoding = offset
      length = this.length
      offset = 0
    // Buffer#write(string, offset[, length][, encoding])
    } else if (isFinite(offset)) {
      offset = offset | 0
      if (isFinite(length)) {
        length = length | 0
        if (encoding === undefined) encoding = 'utf8'
      } else {
        encoding = length
        length = undefined
      }
    // legacy write(string, encoding, offset, length) - remove in v0.13
    } else {
      var swap = encoding
      encoding = offset
      offset = length | 0
      length = swap
    }
  
    var remaining = this.length - offset
    if (length === undefined || length > remaining) length = remaining
  
    if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
      throw new RangeError('attempt to write outside buffer bounds')
    }
  
    if (!encoding) encoding = 'utf8'
  
    var loweredCase = false
    for (;;) {
      switch (encoding) {
        case 'hex':
          return hexWrite(this, string, offset, length)
  
        case 'utf8':
        case 'utf-8':
          return utf8Write(this, string, offset, length)
  
        case 'ascii':
          return asciiWrite(this, string, offset, length)
  
        case 'binary':
          return binaryWrite(this, string, offset, length)
  
        case 'base64':
          // Warning: maxLength not taken into account in base64Write
          return base64Write(this, string, offset, length)
  
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return ucs2Write(this, string, offset, length)
  
        default:
          if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
          encoding = ('' + encoding).toLowerCase()
          loweredCase = true
      }
    }
  }
  
  Buffer.prototype.toJSON = function toJSON () {
    return {
      type: 'Buffer',
      data: Array.prototype.slice.call(this._arr || this, 0)
    }
  }
  
  function base64Slice (buf, start, end) {
    if (start === 0 && end === buf.length) {
      return base64.fromByteArray(buf)
    } else {
      return base64.fromByteArray(buf.slice(start, end))
    }
  }
  
  function utf8Slice (buf, start, end) {
    end = Math.min(buf.length, end)
    var res = []
  
    var i = start
    while (i < end) {
      var firstByte = buf[i]
      var codePoint = null
      var bytesPerSequence = (firstByte > 0xEF) ? 4
        : (firstByte > 0xDF) ? 3
        : (firstByte > 0xBF) ? 2
        : 1
  
      if (i + bytesPerSequence <= end) {
        var secondByte, thirdByte, fourthByte, tempCodePoint
  
        switch (bytesPerSequence) {
          case 1:
            if (firstByte < 0x80) {
              codePoint = firstByte
            }
            break
          case 2:
            secondByte = buf[i + 1]
            if ((secondByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
              if (tempCodePoint > 0x7F) {
                codePoint = tempCodePoint
              }
            }
            break
          case 3:
            secondByte = buf[i + 1]
            thirdByte = buf[i + 2]
            if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
              if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
                codePoint = tempCodePoint
              }
            }
            break
          case 4:
            secondByte = buf[i + 1]
            thirdByte = buf[i + 2]
            fourthByte = buf[i + 3]
            if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
              if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
                codePoint = tempCodePoint
              }
            }
        }
      }
  
      if (codePoint === null) {
        // we did not generate a valid codePoint so insert a
        // replacement char (U+FFFD) and advance only 1 byte
        codePoint = 0xFFFD
        bytesPerSequence = 1
      } else if (codePoint > 0xFFFF) {
        // encode to utf16 (surrogate pair dance)
        codePoint -= 0x10000
        res.push(codePoint >>> 10 & 0x3FF | 0xD800)
        codePoint = 0xDC00 | codePoint & 0x3FF
      }
  
      res.push(codePoint)
      i += bytesPerSequence
    }
  
    return decodeCodePointsArray(res)
  }
  
  // Based on http://stackoverflow.com/a/22747272/680742, the browser with
  // the lowest limit is Chrome, with 0x10000 args.
  // We go 1 magnitude less, for safety
  var MAX_ARGUMENTS_LENGTH = 0x1000
  
  function decodeCodePointsArray (codePoints) {
    var len = codePoints.length
    if (len <= MAX_ARGUMENTS_LENGTH) {
      return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
    }
  
    // Decode in chunks to avoid "call stack size exceeded".
    var res = ''
    var i = 0
    while (i < len) {
      res += String.fromCharCode.apply(
        String,
        codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
      )
    }
    return res
  }
  
  function asciiSlice (buf, start, end) {
    var ret = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; i++) {
      ret += String.fromCharCode(buf[i] & 0x7F)
    }
    return ret
  }
  
  function binarySlice (buf, start, end) {
    var ret = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; i++) {
      ret += String.fromCharCode(buf[i])
    }
    return ret
  }
  
  function hexSlice (buf, start, end) {
    var len = buf.length
  
    if (!start || start < 0) start = 0
    if (!end || end < 0 || end > len) end = len
  
    var out = ''
    for (var i = start; i < end; i++) {
      out += toHex(buf[i])
    }
    return out
  }
  
  function utf16leSlice (buf, start, end) {
    var bytes = buf.slice(start, end)
    var res = ''
    for (var i = 0; i < bytes.length; i += 2) {
      res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
    }
    return res
  }
  
  Buffer.prototype.slice = function slice (start, end) {
    var len = this.length
    start = ~~start
    end = end === undefined ? len : ~~end
  
    if (start < 0) {
      start += len
      if (start < 0) start = 0
    } else if (start > len) {
      start = len
    }
  
    if (end < 0) {
      end += len
      if (end < 0) end = 0
    } else if (end > len) {
      end = len
    }
  
    if (end < start) end = start
  
    var newBuf
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      newBuf = this.subarray(start, end)
      newBuf.__proto__ = Buffer.prototype
    } else {
      var sliceLen = end - start
      newBuf = new Buffer(sliceLen, undefined)
      for (var i = 0; i < sliceLen; i++) {
        newBuf[i] = this[i + start]
      }
    }
  
    if (newBuf.length) newBuf.parent = this.parent || this
  
    return newBuf
  }
  
  /*
   * Need to make sure that buffer isn't trying to write out of bounds.
   */
  function checkOffset (offset, ext, length) {
    if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
    if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
  }
  
  Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var val = this[offset]
    var mul = 1
    var i = 0
    while (++i < byteLength && (mul *= 0x100)) {
      val += this[offset + i] * mul
    }
  
    return val
  }
  
  Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) {
      checkOffset(offset, byteLength, this.length)
    }
  
    var val = this[offset + --byteLength]
    var mul = 1
    while (byteLength > 0 && (mul *= 0x100)) {
      val += this[offset + --byteLength] * mul
    }
  
    return val
  }
  
  Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 1, this.length)
    return this[offset]
  }
  
  Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    return this[offset] | (this[offset + 1] << 8)
  }
  
  Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    return (this[offset] << 8) | this[offset + 1]
  }
  
  Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return ((this[offset]) |
        (this[offset + 1] << 8) |
        (this[offset + 2] << 16)) +
        (this[offset + 3] * 0x1000000)
  }
  
  Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset] * 0x1000000) +
      ((this[offset + 1] << 16) |
      (this[offset + 2] << 8) |
      this[offset + 3])
  }
  
  Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var val = this[offset]
    var mul = 1
    var i = 0
    while (++i < byteLength && (mul *= 0x100)) {
      val += this[offset + i] * mul
    }
    mul *= 0x80
  
    if (val >= mul) val -= Math.pow(2, 8 * byteLength)
  
    return val
  }
  
  Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var i = byteLength
    var mul = 1
    var val = this[offset + --i]
    while (i > 0 && (mul *= 0x100)) {
      val += this[offset + --i] * mul
    }
    mul *= 0x80
  
    if (val >= mul) val -= Math.pow(2, 8 * byteLength)
  
    return val
  }
  
  Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 1, this.length)
    if (!(this[offset] & 0x80)) return (this[offset])
    return ((0xff - this[offset] + 1) * -1)
  }
  
  Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    var val = this[offset] | (this[offset + 1] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    var val = this[offset + 1] | (this[offset] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset]) |
      (this[offset + 1] << 8) |
      (this[offset + 2] << 16) |
      (this[offset + 3] << 24)
  }
  
  Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset] << 24) |
      (this[offset + 1] << 16) |
      (this[offset + 2] << 8) |
      (this[offset + 3])
  }
  
  Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, true, 23, 4)
  }
  
  Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, false, 23, 4)
  }
  
  Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, true, 52, 8)
  }
  
  Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, false, 52, 8)
  }
  
  function checkInt (buf, value, offset, ext, max, min) {
    if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
    if (value > max || value < min) throw new RangeError('value is out of bounds')
    if (offset + ext > buf.length) throw new RangeError('index out of range')
  }
  
  Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
  
    var mul = 1
    var i = 0
    this[offset] = value & 0xFF
    while (++i < byteLength && (mul *= 0x100)) {
      this[offset + i] = (value / mul) & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
  
    var i = byteLength - 1
    var mul = 1
    this[offset + i] = value & 0xFF
    while (--i >= 0 && (mul *= 0x100)) {
      this[offset + i] = (value / mul) & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
    if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
    this[offset] = (value & 0xff)
    return offset + 1
  }
  
  function objectWriteUInt16 (buf, value, offset, littleEndian) {
    if (value < 0) value = 0xffff + value + 1
    for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
      buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
        (littleEndian ? i : 1 - i) * 8
    }
  }
  
  Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value & 0xff)
      this[offset + 1] = (value >>> 8)
    } else {
      objectWriteUInt16(this, value, offset, true)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 8)
      this[offset + 1] = (value & 0xff)
    } else {
      objectWriteUInt16(this, value, offset, false)
    }
    return offset + 2
  }
  
  function objectWriteUInt32 (buf, value, offset, littleEndian) {
    if (value < 0) value = 0xffffffff + value + 1
    for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
      buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
    }
  }
  
  Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset + 3] = (value >>> 24)
      this[offset + 2] = (value >>> 16)
      this[offset + 1] = (value >>> 8)
      this[offset] = (value & 0xff)
    } else {
      objectWriteUInt32(this, value, offset, true)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 24)
      this[offset + 1] = (value >>> 16)
      this[offset + 2] = (value >>> 8)
      this[offset + 3] = (value & 0xff)
    } else {
      objectWriteUInt32(this, value, offset, false)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) {
      var limit = Math.pow(2, 8 * byteLength - 1)
  
      checkInt(this, value, offset, byteLength, limit - 1, -limit)
    }
  
    var i = 0
    var mul = 1
    var sub = value < 0 ? 1 : 0
    this[offset] = value & 0xFF
    while (++i < byteLength && (mul *= 0x100)) {
      this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) {
      var limit = Math.pow(2, 8 * byteLength - 1)
  
      checkInt(this, value, offset, byteLength, limit - 1, -limit)
    }
  
    var i = byteLength - 1
    var mul = 1
    var sub = value < 0 ? 1 : 0
    this[offset + i] = value & 0xFF
    while (--i >= 0 && (mul *= 0x100)) {
      this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
    if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
    if (value < 0) value = 0xff + value + 1
    this[offset] = (value & 0xff)
    return offset + 1
  }
  
  Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value & 0xff)
      this[offset + 1] = (value >>> 8)
    } else {
      objectWriteUInt16(this, value, offset, true)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 8)
      this[offset + 1] = (value & 0xff)
    } else {
      objectWriteUInt16(this, value, offset, false)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value & 0xff)
      this[offset + 1] = (value >>> 8)
      this[offset + 2] = (value >>> 16)
      this[offset + 3] = (value >>> 24)
    } else {
      objectWriteUInt32(this, value, offset, true)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    if (value < 0) value = 0xffffffff + value + 1
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 24)
      this[offset + 1] = (value >>> 16)
      this[offset + 2] = (value >>> 8)
      this[offset + 3] = (value & 0xff)
    } else {
      objectWriteUInt32(this, value, offset, false)
    }
    return offset + 4
  }
  
  function checkIEEE754 (buf, value, offset, ext, max, min) {
    if (offset + ext > buf.length) throw new RangeError('index out of range')
    if (offset < 0) throw new RangeError('index out of range')
  }
  
  function writeFloat (buf, value, offset, littleEndian, noAssert) {
    if (!noAssert) {
      checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
    }
    ieee754.write(buf, value, offset, littleEndian, 23, 4)
    return offset + 4
  }
  
  Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
    return writeFloat(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
    return writeFloat(this, value, offset, false, noAssert)
  }
  
  function writeDouble (buf, value, offset, littleEndian, noAssert) {
    if (!noAssert) {
      checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
    }
    ieee754.write(buf, value, offset, littleEndian, 52, 8)
    return offset + 8
  }
  
  Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
    return writeDouble(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
    return writeDouble(this, value, offset, false, noAssert)
  }
  
  // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
  Buffer.prototype.copy = function copy (target, targetStart, start, end) {
    if (!start) start = 0
    if (!end && end !== 0) end = this.length
    if (targetStart >= target.length) targetStart = target.length
    if (!targetStart) targetStart = 0
    if (end > 0 && end < start) end = start
  
    // Copy 0 bytes; we're done
    if (end === start) return 0
    if (target.length === 0 || this.length === 0) return 0
  
    // Fatal error conditions
    if (targetStart < 0) {
      throw new RangeError('targetStart out of bounds')
    }
    if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
    if (end < 0) throw new RangeError('sourceEnd out of bounds')
  
    // Are we oob?
    if (end > this.length) end = this.length
    if (target.length - targetStart < end - start) {
      end = target.length - targetStart + start
    }
  
    var len = end - start
    var i
  
    if (this === target && start < targetStart && targetStart < end) {
      // descending copy from end
      for (i = len - 1; i >= 0; i--) {
        target[i + targetStart] = this[i + start]
      }
    } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
      // ascending copy from start
      for (i = 0; i < len; i++) {
        target[i + targetStart] = this[i + start]
      }
    } else {
      Uint8Array.prototype.set.call(
        target,
        this.subarray(start, start + len),
        targetStart
      )
    }
  
    return len
  }
  
  // fill(value, start=0, end=buffer.length)
  Buffer.prototype.fill = function fill (value, start, end) {
    if (!value) value = 0
    if (!start) start = 0
    if (!end) end = this.length
  
    if (end < start) throw new RangeError('end < start')
  
    // Fill 0 bytes; we're done
    if (end === start) return
    if (this.length === 0) return
  
    if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')
    if (end < 0 || end > this.length) throw new RangeError('end out of bounds')
  
    var i
    if (typeof value === 'number') {
      for (i = start; i < end; i++) {
        this[i] = value
      }
    } else {
      var bytes = utf8ToBytes(value.toString())
      var len = bytes.length
      for (i = start; i < end; i++) {
        this[i] = bytes[i % len]
      }
    }
  
    return this
  }
  
  // HELPER FUNCTIONS
  // ================
  
  var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
  
  function base64clean (str) {
    // Node strips out invalid characters like \n and \t from the string, base64-js does not
    str = stringtrim(str).replace(INVALID_BASE64_RE, '')
    // Node converts strings with length < 2 to ''
    if (str.length < 2) return ''
    // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
    while (str.length % 4 !== 0) {
      str = str + '='
    }
    return str
  }
  
  function stringtrim (str) {
    if (str.trim) return str.trim()
    return str.replace(/^\s+|\s+$/g, '')
  }
  
  function toHex (n) {
    if (n < 16) return '0' + n.toString(16)
    return n.toString(16)
  }
  
  function utf8ToBytes (string, units) {
    units = units || Infinity
    var codePoint
    var length = string.length
    var leadSurrogate = null
    var bytes = []
  
    for (var i = 0; i < length; i++) {
      codePoint = string.charCodeAt(i)
  
      // is surrogate component
      if (codePoint > 0xD7FF && codePoint < 0xE000) {
        // last char was a lead
        if (!leadSurrogate) {
          // no lead yet
          if (codePoint > 0xDBFF) {
            // unexpected trail
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          } else if (i + 1 === length) {
            // unpaired lead
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          }
  
          // valid lead
          leadSurrogate = codePoint
  
          continue
        }
  
        // 2 leads in a row
        if (codePoint < 0xDC00) {
          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
          leadSurrogate = codePoint
          continue
        }
  
        // valid surrogate pair
        codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
      } else if (leadSurrogate) {
        // valid bmp char, but last char was a lead
        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
      }
  
      leadSurrogate = null
  
      // encode utf8
      if (codePoint < 0x80) {
        if ((units -= 1) < 0) break
        bytes.push(codePoint)
      } else if (codePoint < 0x800) {
        if ((units -= 2) < 0) break
        bytes.push(
          codePoint >> 0x6 | 0xC0,
          codePoint & 0x3F | 0x80
        )
      } else if (codePoint < 0x10000) {
        if ((units -= 3) < 0) break
        bytes.push(
          codePoint >> 0xC | 0xE0,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        )
      } else if (codePoint < 0x110000) {
        if ((units -= 4) < 0) break
        bytes.push(
          codePoint >> 0x12 | 0xF0,
          codePoint >> 0xC & 0x3F | 0x80,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        )
      } else {
        throw new Error('Invalid code point')
      }
    }
  
    return bytes
  }
  
  function asciiToBytes (str) {
    var byteArray = []
    for (var i = 0; i < str.length; i++) {
      // Node's code seems to be doing this and not & 0x7F..
      byteArray.push(str.charCodeAt(i) & 0xFF)
    }
    return byteArray
  }
  
  function utf16leToBytes (str, units) {
    var c, hi, lo
    var byteArray = []
    for (var i = 0; i < str.length; i++) {
      if ((units -= 2) < 0) break
  
      c = str.charCodeAt(i)
      hi = c >> 8
      lo = c % 256
      byteArray.push(lo)
      byteArray.push(hi)
    }
  
    return byteArray
  }
  
  function base64ToBytes (str) {
    return base64.toByteArray(base64clean(str))
  }
  
  function blitBuffer (src, dst, offset, length) {
    for (var i = 0; i < length; i++) {
      if ((i + offset >= dst.length) || (i >= src.length)) break
      dst[i + offset] = src[i]
    }
    return i
  }
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"base64-js":117,"ieee754":118,"isarray":119}],117:[function(require,module,exports){
  'use strict'
  
  exports.toByteArray = toByteArray
  exports.fromByteArray = fromByteArray
  
  var lookup = []
  var revLookup = []
  var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
  
  function init () {
    var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    for (var i = 0, len = code.length; i < len; ++i) {
      lookup[i] = code[i]
      revLookup[code.charCodeAt(i)] = i
    }
  
    revLookup['-'.charCodeAt(0)] = 62
    revLookup['_'.charCodeAt(0)] = 63
  }
  
  init()
  
  function toByteArray (b64) {
    var i, j, l, tmp, placeHolders, arr
    var len = b64.length
  
    if (len % 4 > 0) {
      throw new Error('Invalid string. Length must be a multiple of 4')
    }
  
    // the number of equal signs (place holders)
    // if there are two placeholders, than the two characters before it
    // represent one byte
    // if there is only one, then the three characters before it represent 2 bytes
    // this is just a cheap hack to not do indexOf twice
    placeHolders = b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0
  
    // base64 is 4/3 + up to two characters of the original data
    arr = new Arr(len * 3 / 4 - placeHolders)
  
    // if there are placeholders, only get up to the last complete 4 chars
    l = placeHolders > 0 ? len - 4 : len
  
    var L = 0
  
    for (i = 0, j = 0; i < l; i += 4, j += 3) {
      tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]
      arr[L++] = (tmp >> 16) & 0xFF
      arr[L++] = (tmp >> 8) & 0xFF
      arr[L++] = tmp & 0xFF
    }
  
    if (placeHolders === 2) {
      tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)
      arr[L++] = tmp & 0xFF
    } else if (placeHolders === 1) {
      tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)
      arr[L++] = (tmp >> 8) & 0xFF
      arr[L++] = tmp & 0xFF
    }
  
    return arr
  }
  
  function tripletToBase64 (num) {
    return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]
  }
  
  function encodeChunk (uint8, start, end) {
    var tmp
    var output = []
    for (var i = start; i < end; i += 3) {
      tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
      output.push(tripletToBase64(tmp))
    }
    return output.join('')
  }
  
  function fromByteArray (uint8) {
    var tmp
    var len = uint8.length
    var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
    var output = ''
    var parts = []
    var maxChunkLength = 16383 // must be multiple of 3
  
    // go through the array every three bytes, we'll deal with trailing stuff later
    for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
      parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
    }
  
    // pad the end with zeros, but make sure to not forget the extra bytes
    if (extraBytes === 1) {
      tmp = uint8[len - 1]
      output += lookup[tmp >> 2]
      output += lookup[(tmp << 4) & 0x3F]
      output += '=='
    } else if (extraBytes === 2) {
      tmp = (uint8[len - 2] << 8) + (uint8[len - 1])
      output += lookup[tmp >> 10]
      output += lookup[(tmp >> 4) & 0x3F]
      output += lookup[(tmp << 2) & 0x3F]
      output += '='
    }
  
    parts.push(output)
  
    return parts.join('')
  }
  
  },{}],118:[function(require,module,exports){
  exports.read = function (buffer, offset, isLE, mLen, nBytes) {
    var e, m
    var eLen = nBytes * 8 - mLen - 1
    var eMax = (1 << eLen) - 1
    var eBias = eMax >> 1
    var nBits = -7
    var i = isLE ? (nBytes - 1) : 0
    var d = isLE ? -1 : 1
    var s = buffer[offset + i]
  
    i += d
  
    e = s & ((1 << (-nBits)) - 1)
    s >>= (-nBits)
    nBits += eLen
    for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
  
    m = e & ((1 << (-nBits)) - 1)
    e >>= (-nBits)
    nBits += mLen
    for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
  
    if (e === 0) {
      e = 1 - eBias
    } else if (e === eMax) {
      return m ? NaN : ((s ? -1 : 1) * Infinity)
    } else {
      m = m + Math.pow(2, mLen)
      e = e - eBias
    }
    return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
  }
  
  exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
    var e, m, c
    var eLen = nBytes * 8 - mLen - 1
    var eMax = (1 << eLen) - 1
    var eBias = eMax >> 1
    var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
    var i = isLE ? 0 : (nBytes - 1)
    var d = isLE ? 1 : -1
    var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
  
    value = Math.abs(value)
  
    if (isNaN(value) || value === Infinity) {
      m = isNaN(value) ? 1 : 0
      e = eMax
    } else {
      e = Math.floor(Math.log(value) / Math.LN2)
      if (value * (c = Math.pow(2, -e)) < 1) {
        e--
        c *= 2
      }
      if (e + eBias >= 1) {
        value += rt / c
      } else {
        value += rt * Math.pow(2, 1 - eBias)
      }
      if (value * c >= 2) {
        e++
        c /= 2
      }
  
      if (e + eBias >= eMax) {
        m = 0
        e = eMax
      } else if (e + eBias >= 1) {
        m = (value * c - 1) * Math.pow(2, mLen)
        e = e + eBias
      } else {
        m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
        e = 0
      }
    }
  
    for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
  
    e = (e << mLen) | m
    eLen += mLen
    for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
  
    buffer[offset + i - d] |= s * 128
  }
  
  },{}],119:[function(require,module,exports){
  var toString = {}.toString;
  
  module.exports = Array.isArray || function (arr) {
    return toString.call(arr) == '[object Array]';
  };
  
  },{}],120:[function(require,module,exports){
  // shim for using process in browser
  
  var process = module.exports = {};
  var queue = [];
  var draining = false;
  var currentQueue;
  var queueIndex = -1;
  
  function cleanUpNextTick() {
      draining = false;
      if (currentQueue.length) {
          queue = currentQueue.concat(queue);
      } else {
          queueIndex = -1;
      }
      if (queue.length) {
          drainQueue();
      }
  }
  
  function drainQueue() {
      if (draining) {
          return;
      }
      var timeout = setTimeout(cleanUpNextTick);
      draining = true;
  
      var len = queue.length;
      while(len) {
          currentQueue = queue;
          queue = [];
          while (++queueIndex < len) {
              if (currentQueue) {
                  currentQueue[queueIndex].run();
              }
          }
          queueIndex = -1;
          len = queue.length;
      }
      currentQueue = null;
      draining = false;
      clearTimeout(timeout);
  }
  
  process.nextTick = function (fun) {
      var args = new Array(arguments.length - 1);
      if (arguments.length > 1) {
          for (var i = 1; i < arguments.length; i++) {
              args[i - 1] = arguments[i];
          }
      }
      queue.push(new Item(fun, args));
      if (queue.length === 1 && !draining) {
          setTimeout(drainQueue, 0);
      }
  };
  
  // v8 likes predictible objects
  function Item(fun, array) {
      this.fun = fun;
      this.array = array;
  }
  Item.prototype.run = function () {
      this.fun.apply(null, this.array);
  };
  process.title = 'browser';
  process.browser = true;
  process.env = {};
  process.argv = [];
  process.version = ''; // empty string to avoid regexp issues
  process.versions = {};
  
  function noop() {}
  
  process.on = noop;
  process.addListener = noop;
  process.once = noop;
  process.off = noop;
  process.removeListener = noop;
  process.removeAllListeners = noop;
  process.emit = noop;
  
  process.binding = function (name) {
      throw new Error('process.binding is not supported');
  };
  
  process.cwd = function () { return '/' };
  process.chdir = function (dir) {
      throw new Error('process.chdir is not supported');
  };
  process.umask = function() { return 0; };
  
  },{}]},{},[1]);
  