var app = angular.module('plunker', ['ngMaterial']);

app.controller('MainCtrl', function($scope, $mdDialog) {
  $scope.openDialog = function(){
    var elementWrapper = {};
    elementWrapper.target = document.getElementById('someOtherElement');
    $mdDialog.show({
      controller: function($scope, $mdDialog){
        // do something with dialog scope
      },
      template: '<md-dialog aria-label="My Dialog" style="position: absolute; top: 0; right: 0;">'+
                    '<md-dialog-content class="sticky-container">Blah Blah' +
                    '</md-dialog-content>' +
                    '<md-button ng-click=close()>Close</md-button>' +
                    '</md-dialog>',
      targetEvent: elementWrapper
    });
  };
  
});
<!DOCTYPE html>
<html ng-app="plunker">

<head>
  <meta charset="utf-8" />
  <title>AngularJS material-sidenav Plunker</title>
  <!-- Angular Material CSS now available via Google CDN; version 0.8 used here -->
  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/0.8.3/angular-material.min.css">

  <link rel="stylesheet" href="style.css" />
  
  <!-- Angular Material Dependencies -->
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-animate.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-aria.min.js"></script>

  <!-- Angular Material Javascript now available via Google CDN; version 0.8 used here -->
  <script src="https://ajax.googleapis.com/ajax/libs/angular_material/0.8.3/angular-material.min.js"></script>

  
  <script src="app.js"></script>
  
</head>

<body ng-controller="MainCtrl">

  <md-button ng-click="openDialog()">Open</md-button>
  
  <div id="someOtherElement">Other Element</div>
</body>



</html>
/* Put your css in here */

#someOtherElement{
  position: relative;
  top: 0;
  left: 350px;
  background-color: red;
}
/*!
 * Angular Material Design
 * https://github.com/angular/material
 * @license MIT
 * v0.4.0
 */
(function(){
angular.module('ngMaterial', [ 'ng', 'ngAnimate', 'ngAria', 'material.core', 'material.services.attrBind', 'material.services.compiler', 'material.services.registry', 'material.decorators', 'material.services.aria', "material.components.bottomSheet","material.components.button","material.components.card","material.components.checkbox","material.components.circularProgress","material.components.content","material.components.dialog","material.components.divider","material.components.icon","material.components.linearProgress","material.components.list","material.components.radioButton","material.components.sidenav","material.components.slider","material.components.subheader","material.components.switch","material.components.tabs","material.components.textField","material.components.toast","material.components.toolbar","material.components.tooltip","material.components.whiteframe"]);
var Constant = {
  KEY_CODE: {
    ENTER: 13,
    ESCAPE: 27,
    SPACE: 32,
    LEFT_ARROW : 37,
    UP_ARROW : 38,
    RIGHT_ARROW : 39,
    DOWN_ARROW : 40
  }
};

  /**
   * Angular Materials initialization function that validates environment
   * requirements.
   */
  angular.module('material.core', ['ngAria'] )
    .run(function validateEnvironment() {

      if (angular.isUndefined( window.Hammer )) {
        throw new Error(
          '$materialSwipe requires HammerJS to be preloaded.'
        );
      }

    });





/*
 * iterator is a list facade to easily support iteration and accessors
 *
 * @param items Array list which this iterator will enumerate
 * @param reloop Boolean enables iterator to consider the list as an endless reloop
 */
function iterator(items, reloop) {
  var trueFn = function() { return true; };

  reloop = !!reloop;
  var _items = items || [ ];

  // Published API
  return {
    items: getItems,
    count: count,

    inRange: inRange,
    contains: contains,
    indexOf: indexOf,
    itemAt: itemAt,

    findBy: findBy,

    add: add,
    remove: remove,

    first: first,
    last: last,
    next: next,
    previous: previous,

    hasPrevious: hasPrevious,
    hasNext: hasNext

  };

  /*
   * Publish copy of the enumerable set
   * @returns {Array|*}
   */
  function getItems() {
    return [].concat(_items);
  }

  /*
   * Determine length of the list
   * @returns {Array.length|*|number}
   */
  function count() {
    return _items.length;
  }

  /*
   * Is the index specified valid
   * @param index
   * @returns {Array.length|*|number|boolean}
   */
  function inRange(index) {
    return _items.length && ( index > -1 ) && (index < _items.length );
  }

  /*
   * Can the iterator proceed to the next item in the list; relative to
   * the specified item.
   *
   * @param item
   * @returns {Array.length|*|number|boolean}
   */
  function hasNext(item) {
    return item ? inRange(indexOf(item) + 1) : false;
  }

  /*
   * Can the iterator proceed to the previous item in the list; relative to
   * the specified item.
   *
   * @param item
   * @returns {Array.length|*|number|boolean}
   */
  function hasPrevious(item) {
    return item ? inRange(indexOf(item) - 1) : false;
  }

  /*
   * Get item at specified index/position
   * @param index
   * @returns {*}
   */
  function itemAt(index) {
    return inRange(index) ? _items[index] : null;
  }

  /*
   * Find all elements matching the key/value pair
   * otherwise return null
   *
   * @param val
   * @param key
   *
   * @return array
   */
  function findBy(key, val) {
    return _items.filter(function(item) {
      return item[key] === val;
    });
  }

  /*
   * Add item to list
   * @param item
   * @param index
   * @returns {*}
   */
  function add(item, index) {
    if ( !item ) return -1;

    if (!angular.isNumber(index)) {
      index = _items.length;
    }

    _items.splice(index, 0, item);

    return indexOf(item);
  }

  /*
   * Remove item from list...
   * @param item
   */
  function remove(item) {
    if ( contains(item) ){
      _items.splice(indexOf(item), 1);
    }
  }

  /*
   * Get the zero-based index of the target item
   * @param item
   * @returns {*}
   */
  function indexOf(item) {
    return _items.indexOf(item);
  }

  /*
   * Boolean existence check
   * @param item
   * @returns {boolean}
   */
  function contains(item) {
    return item && (indexOf(item) > -1);
  }

  /*
   * Find the next item. If reloop is true and at the end of the list, it will 
   * go back to the first item. If given ,the `validate` callback will be used
   * determine whether the next item is valid. If not valid, it will try to find the
   * next item again.
   * @param item
   * @param {optional} validate
   * @returns {*}
   */
  function next(item, validate) {
    validate = validate || trueFn;

    if (contains(item)) {
      var index = indexOf(item) + 1,
      found = inRange(index) ? _items[ index ] : (reloop ? first() : null);

      return validate(found) ? found : next(found, validate);
    }

    return null;
  }

  /*
   * Find the previous item. If reloop is true and at the beginning of the list, it will 
   * go back to the last item. If given ,the `validate` callback will be used
   * determine whether the previous item is valid. If not valid, it will try to find the
   * previous item again.
   * @param item
   * @param {optional} validate
   * @returns {*}
   */
  function previous(item, validate) {
    validate = validate || trueFn;

    if (contains(item)) {
      var index = indexOf(item) - 1,
      found = inRange(index) ? _items[ index ] : (reloop ? last() : null);

      return validate(found) ? found : previous(found, validate);
    }

    return null;
  }

  /*
   * Return first item in the list
   * @returns {*}
   */
  function first() {
    return _items.length ? _items[0] : null;
  }

  /*
   * Return last item in the list...
   * @returns {*}
   */
  function last() {
    return _items.length ? _items[_items.length - 1] : null;
  }

}

var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;

/* for nextUid() function below */
var uid = ['0','0','0'];

var Util = {
  now: window.performance ? angular.bind(window.performance, window.performance.now) : Date.now,

  /**
   * Checks if the specified element has an ancestor (ancestor being parent, grandparent, etc)
   * with the given attribute defined. 
   *
   * Also pass in an optional `limit` (levels of ancestry to scan), default 4.
   */
  ancestorHasAttribute: function ancestorHasAttribute(element, attrName, limit) {
    limit = limit || 4;
    var current = element;
    while (limit-- && current.length) {
      if (current[0].hasAttribute && current[0].hasAttribute(attrName)) {
        return true;
      }
      current = current.parent();
    }
    return false;
  },

  /**
   * Checks to see if the element or its parents are disabled.
   * @param element DOM element to start scanning for `disabled` attribute
   * @param limit Number of parent levels that should be scanned; defaults to 4
   * @returns {*} Boolean
   */
  isParentDisabled: function isParentDisabled(element, limit) {
    return Util.ancestorHasAttribute(element, 'disabled', limit);
  },

  /**
   * Checks if two elements have the same parent
   */
  elementIsSibling: function elementIsSibling(element, otherElement) {
    return element.parent().length && 
      (element.parent()[0] === otherElement.parent()[0]);
  },

  /**
   * Converts snake_case to camelCase.
   * @param name Name to normalize
   */
  camelCase: function camelCase(name) {
    return name
      .replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
        return offset ? letter.toUpperCase() : letter;
      });
  },

  /**
   * Selects 'n' words from a string
   * for use in an HTML attribute
   */
  stringFromTextBody: function stringFromTextBody(textBody, numWords) {
    var string = textBody.trim();

    if(string.split(/\s+/).length > numWords){
      string = textBody.split(/\s+/).slice(1, (numWords + 1)).join(" ") + '...';
    }
    return string;
  },

  /**
   * Publish the iterator facade to easily support iteration and accessors
   * @see iterator.js
   */
  iterator: iterator,

  // Returns a function, that, as long as it continues to be invoked, will not
  // be triggered. The function will be called after it stops being called for
  // N milliseconds. If `immediate` is passed, trigger the function on the
  // leading edge, instead of the trailing.
  debounce: function debounce(func, wait, immediate) {
    var timeout;
    return function debounced() {
      var context = this, args = arguments;
      clearTimeout(timeout);
      timeout = setTimeout(function() {
        timeout = null;
        if (!immediate) func.apply(context, args);
      }, wait);
      if (immediate && !timeout) func.apply(context, args);
    };
  },

  // Returns a function that can only be triggered every `delay` milliseconds.
  // In other words, the function will not be called unless it has been more
  // than `delay` milliseconds since the last call.
  throttle: function throttle(func, delay) {
    var recent;
    return function throttled() {
      var context = this;
      var args = arguments;
      var now = Util.now();

      if (!recent || recent - now > delay) {
        func.apply(context, args);
        recent = now;
      }
    };
  },

  /**
   * Wraps an element with a tag
   *
   * @param el element to wrap
   * @param tag tag to wrap it with
   * @param [className] optional class to apply to the wrapper
   * @returns new element
   *
   */
  wrap: function(el, tag, className) {
    if(el.hasOwnProperty(0)) { el = el[0]; }
    var wrapper = document.createElement(tag);
    wrapper.className += className;
    wrapper.appendChild(el.parentNode.replaceChild(wrapper, el));
    return angular.element(wrapper);
  },

  /**
   * nextUid, from angular.js.
   * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric
   * characters such as '012ABC'. The reason why we are not using simply a number counter is that
   * the number string gets longer over time, and it can also overflow, where as the nextId
   * will grow much slower, it is a string, and it will never overflow.
   *
   * @returns an unique alpha-numeric string
   */
  nextUid: function() {
    var index = uid.length;
    var digit;

    while(index) {
      index--;
      digit = uid[index].charCodeAt(0);
      if (digit == 57 /*'9'*/) {
        uid[index] = 'A';
        return uid.join('');
      }
      if (digit == 90  /*'Z'*/) {
        uid[index] = '0';
      } else {
        uid[index] = String.fromCharCode(digit + 1);
        return uid.join('');
      }
    }
    uid.unshift('0');
    return uid.join('');
  },

  // Stop watchers and events from firing on a scope without destroying it,
  // by disconnecting it from its parent and its siblings' linked lists.
  disconnectScope: function disconnectScope(scope) {
    if (!scope) return;

    // we can't destroy the root scope or a scope that has been already destroyed
    if (scope.$root === scope) return;
    if (scope.$$destroyed ) return;

    var parent = scope.$parent;
    scope.$$disconnected = true;

    // See Scope.$destroy
    if (parent.$$childHead === scope) parent.$$childHead = scope.$$nextSibling;
    if (parent.$$childTail === scope) parent.$$childTail = scope.$$prevSibling;
    if (scope.$$prevSibling) scope.$$prevSibling.$$nextSibling = scope.$$nextSibling;
    if (scope.$$nextSibling) scope.$$nextSibling.$$prevSibling = scope.$$prevSibling;

    scope.$$nextSibling = scope.$$prevSibling = null;

  },

  // Undo the effects of disconnectScope above.
  reconnectScope: function reconnectScope(scope) {
    if (!scope) return;

    // we can't disconnect the root node or scope already disconnected
    if (scope.$root === scope) return;
    if (!scope.$$disconnected) return;

    var child = scope;

    var parent = child.$parent;
    child.$$disconnected = false;
    // See Scope.$new for this logic...
    child.$$prevSibling = parent.$$childTail;
    if (parent.$$childHead) {
      parent.$$childTail.$$nextSibling = child;
      parent.$$childTail = child;
    } else {
      parent.$$childHead = parent.$$childTail = child;
    }
  }

};

/* 
 * Since removing jQuery from the demos, some code that uses `element.focus()` is broken.
 *
 * We need to add `element.focus()`, because it's testable unlike `element[0].focus`.
 *
 * TODO(ajoslin): This should be added in a better place later.
 */
angular.element.prototype.focus = angular.element.prototype.focus || function() {
  if (this.length) {
    this[0].focus();
  }
  return this;
};
angular.element.prototype.blur = angular.element.prototype.blur || function() {
  if (this.length) {
    this[0].blur();
  }
  return this;
};

/**
 * @ngdoc module
 * @name material.components.animate
 * @description
 *
 * Ink and Popup Effects
 */
angular.module('material.animations', [])
  .service('$materialEffects', [ 
    '$rootElement', 
    '$$rAF', 
    '$sniffer',
    '$q',
    MaterialEffects
  ]);

/**
 * @ngdoc service
 * @name $materialEffects
 * @module material.components.animate
 *
 * @description
 * The `$materialEffects` service provides a simple API for various
 * Material Design effects.
 *
 * @returns A `$materialEffects` object with the following properties:
 * - `{function(element,styles,duration)}` `inkBar` - starts ink bar
 * animation on specified DOM element
 * - `{function(element,parentElement,clickElement)}` `popIn` - animated show of element overlayed on parent element
 * - `{function(element,parentElement)}` `popOut` - animated close of popup overlay
 *
 */
function MaterialEffects($rootElement, $$rAF, $sniffer, $q) {

  var webkit = /webkit/i.test($sniffer.vendorPrefix);
  function vendorProperty(name) {
    return webkit ? 
      ('webkit' + name.charAt(0).toUpperCase() + name.substring(1)) :
      name;
  }

  var self;
  // Publish API for effects...
  return self = {
    popIn: popIn,

    /* Constants */
    TRANSITIONEND_EVENT: 'transitionend' + (webkit ? ' webkitTransitionEnd' : ''),
    ANIMATIONEND_EVENT: 'animationend' + (webkit ? ' webkitAnimationEnd' : ''),

    TRANSFORM: vendorProperty('transform'),
    TRANSITION: vendorProperty('transition'),
    TRANSITION_DURATION: vendorProperty('transitionDuration'),
    ANIMATION_PLAY_STATE: vendorProperty('animationPlayState'),
    ANIMATION_DURATION: vendorProperty('animationDuration'),
    ANIMATION_NAME: vendorProperty('animationName'),
    ANIMATION_TIMING: vendorProperty('animationTimingFunction'),
    ANIMATION_DIRECTION: vendorProperty('animationDirection')
  };

  // **********************************************************
  // API Methods
  // **********************************************************
  function popIn(element, parentElement, clickElement) {
    var deferred = $q.defer();
    parentElement.append(element);

    var startPos;
    if (clickElement) {
      var clickRect = clickElement[0].getBoundingClientRect();
      startPos = translateString(
        clickRect.left - element[0].offsetWidth,
        clickRect.top - element[0].offsetHeight, 
        0
      ) + ' scale(0.2)';
    } else {
      startPos = 'translate3d(0,100%,0) scale(0.5)';
    }

    element
      .css(self.TRANSFORM, startPos)
      .css('opacity', 0);
    
    $$rAF(function() {
      $$rAF(function() {
        element
          .addClass('active')
          .css(self.TRANSFORM, '')
          .css('opacity', '')
          .on(self.TRANSITIONEND_EVENT, finished);
      });
    });

    function finished(ev) {
      //Make sure this transitionend didn't bubble up from a child
      if (ev.target === element[0]) {
        element.off(self.TRANSITIONEND_EVENT, finished);
        deferred.resolve();
      }
    }

    return deferred.promise;
  }

  // **********************************************************
  // Utility Methods
  // **********************************************************


  function translateString(x, y, z) {
    return 'translate3d(' + Math.floor(x) + 'px,' + Math.floor(y) + 'px,' + Math.floor(z) + 'px)';
  }

}


(function() {

angular.module('material.animations')

/**
 * noink/nobar/nostretch directive: make any element that has one of
 * these attributes be given a controller, so that other directives can 
 * `require:` these and see if there is a `no<xxx>` parent attribute.
 *
 * @usage
 * <hljs lang="html">
 * <parent noink>
 *   <child detect-no>
 *   </child>
 * </parent>
 * </hljs>
 *
 * <hljs lang="js">
 * myApp.directive('detectNo', function() {
 *   return {
 *     require: ['^?noink', ^?nobar'],
 *     link: function(scope, element, attr, ctrls) {
 *       var noinkCtrl = ctrls[0];
 *       var nobarCtrl = ctrls[1];
 *       if (noInkCtrl) {
 *         alert("the noink flag has been specified on an ancestor!");
 *       }
 *       if (nobarCtrl) {
 *         alert("the nobar flag has been specified on an ancestor!");
 *       }
 *     }
 *   };
 * });
 * </hljs>
 */
.directive({
  noink: attrNoDirective(),
  nobar: attrNoDirective(),
  nostretch: attrNoDirective()
});

function attrNoDirective() {
  return function() {
    return {
      controller: angular.noop
    };
  };
}

})();


angular.module('material.animations')

.directive('inkRipple', [
  '$materialInkRipple',
  InkRippleDirective
])

.factory('$materialInkRipple', [
  '$window',
  '$$rAF',
  '$materialEffects',
  '$timeout',
  InkRippleService
]);

function InkRippleDirective($materialInkRipple) {
  return function(scope, element, attr) {
    if (attr.inkRipple == 'checkbox') {
      $materialInkRipple.attachCheckboxBehavior(element);
    } else {
      $materialInkRipple.attachButtonBehavior(element);
    }
  };
}

function InkRippleService($window, $$rAF, $materialEffects, $timeout) {

  // TODO fix this. doesn't support touch AND click devices (eg chrome pixel)
  var hasTouch = !!('ontouchend' in document);
  var POINTERDOWN_EVENT = hasTouch ? 'touchstart' : 'mousedown';
  var POINTERUP_EVENT = hasTouch ? 'touchend touchcancel' : 'mouseup mouseleave';

  return {
    attachButtonBehavior: attachButtonBehavior,
    attachCheckboxBehavior: attachCheckboxBehavior,
    attach: attach
  };

  function attachButtonBehavior(element) {
    return attach(element, {
      mousedown: true,
      center: false,
      animationDuration: 350,
      mousedownPauseTime: 175,
      animationName: 'inkRippleButton',
      animationTimingFunction: 'linear'
    });
  }

  function attachCheckboxBehavior(element) {
    return attach(element, {
      mousedown: true,
      center: true,
      animationDuration: 300,
      mousedownPauseTime: 180,
      animationName: 'inkRippleCheckbox',
      animationTimingFunction: 'linear'
    });
  }

  function attach(element, options) {
    // Parent element with noink attr? Abort.
    if (element.controller('noink')) return angular.noop;

    options = angular.extend({
      mousedown: true,
      hover: true,
      focus: true,
      center: false,
      animationDuration: 300,
      mousedownPauseTime: 150,
      animationName: '',
      animationTimingFunction: 'linear'
    }, options || {});

    var rippleContainer;
    var node = element[0];

    if (options.mousedown) {
      listenPointerDown(true);
    }

    // Publish self-detach method if desired...
    return function detach() {
      listenPointerDown(false);
      if (rippleContainer) {
        rippleContainer.remove();
      }
    };

    function listenPointerDown(shouldListen) {
      element[shouldListen ? 'on' : 'off'](POINTERDOWN_EVENT, onPointerDown);
    }

    function rippleIsAllowed() {
      return !Util.isParentDisabled(element);
    }

    function createRipple(left, top, positionsAreAbsolute) {

      var rippleEl = angular.element('<div class="material-ripple">')
            .css($materialEffects.ANIMATION_DURATION, options.animationDuration + 'ms')
            .css($materialEffects.ANIMATION_NAME, options.animationName)
            .css($materialEffects.ANIMATION_TIMING, options.animationTimingFunction)
            .on($materialEffects.ANIMATIONEND_EVENT, function() {
              rippleEl.remove();
            });

      if (!rippleContainer) {
        rippleContainer = angular.element('<div class="material-ripple-container">');
        element.append(rippleContainer);
      }
      rippleContainer.append(rippleEl);

      var containerWidth = rippleContainer.prop('offsetWidth');

      if (options.center) {
        left = containerWidth / 2;
        top = rippleContainer.prop('offsetHeight') / 2;
      } else if (positionsAreAbsolute) {
        var elementRect = node.getBoundingClientRect();
        left -= elementRect.left;
        top -= elementRect.top;
      }

      var css = {
        'background-color': $window.getComputedStyle(rippleEl[0]).color || 
          $window.getComputedStyle(node).color,
        'border-radius': (containerWidth / 2) + 'px',

        left: (left - containerWidth / 2) + 'px',
        width: containerWidth + 'px',

        top: (top - containerWidth / 2) + 'px',
        height: containerWidth + 'px'
      };
      css[$materialEffects.ANIMATION_DURATION] = options.fadeoutDuration + 'ms';
      rippleEl.css(css);

      return rippleEl;
    }

    function onPointerDown(ev) {
      if (!rippleIsAllowed()) return;

      var rippleEl = createRippleFromEvent(ev);
      var ripplePauseTimeout = $timeout(pauseRipple, options.mousedownPauseTime, false);
      rippleEl.on('$destroy', cancelRipplePause);

      // Stop listening to pointer down for now, until the user lifts their finger/mouse
      listenPointerDown(false);
      element.on(POINTERUP_EVENT, onPointerUp);

      function onPointerUp() {
        cancelRipplePause();
        rippleEl.css($materialEffects.ANIMATION_PLAY_STATE, 'running');
        element.off(POINTERUP_EVENT, onPointerUp);
        listenPointerDown(true);
      }
      function pauseRipple() {
        rippleEl.css($materialEffects.ANIMATION_PLAY_STATE, 'paused');
      }
      function cancelRipplePause() {
        $timeout.cancel(ripplePauseTimeout);
      }

      function createRippleFromEvent(ev) {
        ev = ev.touches ? ev.touches[0] : ev;
        return createRipple(ev.pageX, ev.pageY, true);
      }
    }
  }

}

/**
 * @ngdoc module
 * @name material.components.sticky
 * @description
 *
 * Sticky effects for material
 */

angular.module('material.components.sticky', [
  'material.components.content',
  'material.decorators',
  'material.animations'
])
.factory('$materialSticky', [
  '$document',
  '$materialEffects',
  '$compile',
  '$$rAF',
  MaterialSticky
]);

/**
 * @ngdoc factory
 * @name $materialSticky
 * @module material.components.sticky
 *
 * @description
 * The `$materialSticky`service provides a mixin to make elements sticky.
 *
 * @returns A `$materialSticky` function that takes three arguments:
 *   - `scope`
 *   - `element`: The element that will be 'sticky'
 *   - `{optional}` `clone`: A clone of the element, that will be shown
 *     when the user starts scrolling past the original element.
 *     If not provided, it will use the result of `element.clone()`.
 */

function MaterialSticky($document, $materialEffects, $compile, $$rAF) {

  var browserStickySupport = checkStickySupport();

  /**
   * Registers an element as sticky, used internally by directives to register themselves
   */
  return function registerStickyElement(scope, element, stickyClone) {
    var contentCtrl = element.controller('materialContent');
    if (!contentCtrl) return;

    if (browserStickySupport) {
      element.css({
        position: browserStickySupport,
        top: 0,
        'z-index': 2
      });
    } else {
      var $$sticky = contentCtrl.$element.data('$$sticky');
      if (!$$sticky) {
        $$sticky = setupSticky(contentCtrl);
        contentCtrl.$element.data('$$sticky', $$sticky);
      }

      var deregister = $$sticky.add(element, stickyClone || element.clone());
      scope.$on('$destroy', deregister);
    }
  };

  function setupSticky(contentCtrl) {
    var contentEl = contentCtrl.$element;

    // Refresh elements is very expensive, so we use the debounced
    // version when possible.
    var debouncedRefreshElements = $$rAF.debounce(refreshElements);

    // setupAugmentedScrollEvents gives us `$scrollstart` and `$scroll`,
    // more reliable than `scroll` on android.
    setupAugmentedScrollEvents(contentEl);
    contentEl.on('$scrollstart', debouncedRefreshElements);
    contentEl.on('$scroll', onScroll);

    var self;
    return self = {
      prev: null,
      current: null, //the currently stickied item
      next: null,
      items: [],
      add: add,
      refreshElements: refreshElements
    };

    /***************
     * Public
     ***************/
    // Add an element and its sticky clone to this content's sticky collection
    function add(element, stickyClone) {
      stickyClone.addClass('material-sticky-clone');

      var item = {
        element: element,
        clone: stickyClone
      };
      self.items.push(item);

      contentEl.parent().prepend(item.clone);

      debouncedRefreshElements();

      return function remove() {
        self.items.forEach(function(item, index) {
          if (item.element[0] === element[0]) {
            self.items.splice(index, 1);
            item.clone.remove();
          }
        });
        debouncedRefreshElements();
      };
    }

    function refreshElements() {
      var contentRect = contentEl[0].getBoundingClientRect();


      // Sort our collection of elements by their current position in the DOM.
      // We need to do this because our elements' order of being added may not
      // be the same as their order of display.
      self.items.forEach(refreshPosition);
      self.items = self.items.sort(function(a, b) {
        return a.top > b.top;
      });

      // Find which item in the list should be active, 
      // based upon the content's current scroll position
      var item;
      var currentScrollTop = contentEl.prop('scrollTop');
      for (var i = self.items.length - 1; i >= 0; i--) {
        if (currentScrollTop > self.items[i].top) {
          item = self.items[i];
          break;
        }
      }
      setCurrentItem(item);
    }


    /***************
     * Private
     ***************/

    // Find the `top` of an item relative to the content element,
    // and also the height.
    function refreshPosition(item) {
      // Find the top of an item by adding to the offsetHeight until we reach the 
      // content element.
      var current = item.element[0];
      item.top = 0;
      item.left = 0;
      while (current && current !== contentEl[0]) {
        item.top += current.offsetTop;
        item.left += current.offsetLeft;
        current = current.offsetParent;
      }
      item.height = item.element.prop('offsetHeight');

      item.clone.css('margin-left', item.left + 'px');
    }


    // As we scroll, push in and select the correct sticky element.
    function onScroll() {
      var scrollTop = contentEl.prop('scrollTop');
      var isScrollingDown = scrollTop > (onScroll.prevScrollTop || 0);
      onScroll.prevScrollTop = scrollTop;

      // At the top?
      if (scrollTop === 0) {
        setCurrentItem(null);

      // Going to next item?
      } else if (isScrollingDown && self.next) {
        if (self.next.top - scrollTop <= 0) {
          // Sticky the next item if we've scrolled past its position.
          setCurrentItem(self.next);
        } else if (self.current) {
          // Push the current item up when we're almost at the next item.
          if (self.next.top - scrollTop <= self.next.height) {
            translate(self.current, self.next.top - self.next.height - scrollTop);
          } else {
            translate(self.current, null);
          }
        }
        
      // Scrolling up with a current sticky item?
      } else if (!isScrollingDown && self.current) {
        if (scrollTop < self.current.top) {
          // Sticky the previous item if we've scrolled up past
          // the original position of the currently stickied item.
          setCurrentItem(self.prev);
        }
        // Scrolling up, and just bumping into the item above (just set to current)?
        // If we have a next item bumping into the current item, translate
        // the current item up from the top as it scrolls into view.
        if (self.current && self.next) {
          if (scrollTop >= self.next.top - self.current.height) {
            translate(self.current, self.next.top - scrollTop - self.current.height);
          } else {
            translate(self.current, null);
          }
        }
      }
    }
     
   function setCurrentItem(item) {
     if (self.current === item) return;
     // Deactivate currently active item
     if (self.current) {
       translate(self.current, null);
       setStickyState(self.current, null);
     }

     // Activate new item if given
     if (item) {
       setStickyState(item, 'active');
     }

     self.current = item;
     var index = self.items.indexOf(item);
     // If index === -1, index + 1 = 0. It works out.
     self.next = self.items[index + 1];
     self.prev = self.items[index - 1];
     setStickyState(self.next, 'next');
     setStickyState(self.prev, 'prev');
   }

   function setStickyState(item, state) {
     if (!item || item.state === state) return;
     if (item.state) {
       item.clone.attr('sticky-prev-state', item.state);
       item.element.attr('sticky-prev-state', item.state);
     }
     item.clone.attr('sticky-state', state);
     item.element.attr('sticky-state', state);
     item.state = state;
   }

   function translate(item, amount) {
     if (!item) return;
     if (amount === null || amount === undefined) {
       if (item.translateY) {
         item.translateY = null;
         item.clone.css($materialEffects.TRANSFORM, '');
       }
     } else {
       item.translateY = amount;
       item.clone.css(
         $materialEffects.TRANSFORM, 
         'translate3d(' + item.left + 'px,' + amount + 'px,0)'
       );
     }
   }
  }

  // Function to check for browser sticky support
  function checkStickySupport($el) {
    var stickyProp;
    var testEl = angular.element('<div>');
    $document[0].body.appendChild(testEl[0]);

    var stickyProps = ['sticky', '-webkit-sticky'];
    for (var i = 0; i < stickyProps.length; ++i) {
      testEl.css({position: stickyProps[i], top: 0, 'z-index': 2});
      if (testEl.css('position') == stickyProps[i]) {
        stickyProp = stickyProps[i];
        break;
      }
    }
    testEl.remove();
    return stickyProp;
  }

  // Android 4.4 don't accurately give scroll events.
  // To fix this problem, we setup a fake scroll event. We say:
  // > If a scroll or touchmove event has happened in the last DELAY milliseconds, 
  //   then send a `$scroll` event every animationFrame.
  // Additionally, we add $scrollstart and $scrollend events.
  function setupAugmentedScrollEvents(element) {
    var SCROLL_END_DELAY = 200;
    var isScrolling;
    var lastScrollTime;
    element.on('scroll touchmove', function() {
      if (!isScrolling) {
        isScrolling = true;
        $$rAF(loopScrollEvent);
        element.triggerHandler('$scrollstart');
      }
      element.triggerHandler('$scroll');
      lastScrollTime = +Util.now();
    });

    function loopScrollEvent() {
      if (+Util.now() - lastScrollTime > SCROLL_END_DELAY) {
        isScrolling = false;
        element.triggerHandler('$scrollend');
      } else {
        element.triggerHandler('$scroll');
        $$rAF(loopScrollEvent);
      }
    }
  }

}

/**
 * @ngdoc module
 * @name material.components.bottomSheet
 * @description
 * BottomSheet
 */
angular.module('material.components.bottomSheet', [
  'material.services.interimElement'
])
.directive('materialBottomSheet', [
  MaterialBottomSheetDirective
])
.factory('$materialBottomSheet', [
  '$$interimElement',
  '$animate',
  '$materialEffects',
  '$timeout',
  '$$rAF',
  MaterialBottomSheet
]);

function MaterialBottomSheetDirective() {
  return {
    restrict: 'E'
  };
}

/**
 * @ngdoc service
 * @name $materialBottomSheet
 * @module material.components.bottomSheet
 *
 * @description

 * Used to open a bottom sheet on the screen, `$materialBottomSheet` is a service
 * created by `$$interimElement` and provides a simple promise-based, behavior API:
 *
 *  - `$materialBottomSheet.show()`
 *  - `$materialBottomSheet.hide()`
 *  - `$materialBottomSheet.cancel()`
 *
 * #### Notes:
 *
 * Only one bottom sheet may ever be active at any time. If a new sheet is
 * shown while a different one is active, the previous sheet will be automatically
 * hidden.

 * The bottom sheet's template must have an outer `<material-bottom-sheet>` element.
 *
 * @usage
 * <hljs lang="html">
 * <div ng-controller="MyController">
 *   <material-button ng-click="openBottomSheet()">
 *     Open a Bottom Sheet!
 *   </material-button>
 * </div>
 * </hljs>
 * <hljs lang="js">
 * var app = angular.module('app', ['ngMaterial']);
 * app.controller('MyController', function($scope, $materialBottomSheet) {
 *   $scope.openBottomSheet = function() {
 *     $materialBottomSheet.show({
 *       template: '<material-bottom-sheet>Hello!</material-bottom-sheet>'
 *     });
 *   };
 * });
 * </hljs>
 */

 /**
 * @ngdoc method
 * @name $materialBottomSheet#show
 *
 * @description
 * Show a bottom sheet with the specified options.
 *
 * @paramType Options
 * @param {string=} templateUrl The url of an html template file that will
 * be used as the content of the bottom sheet. Restrictions: the template must
 * have an outer `material-bottom-sheet` element.
 * @param {string=} template Same as templateUrl, except this is an actual
 * template string.
 * @param {string=} controller The controller to associate with this bottom sheet.
 * @param {string=} locals An object containing key/value pairs. The keys will
 * be used as names of values to inject into the controller. For example, 
 * `locals: {three: 3}` would inject `three` into the controller with the value
 * of 3.
 * @param {element=} parent The element to append the bottomSheet to. Defaults to appending
 * to the root element of the application.
 * @param {DOMClickEvent=} targetEvent A click's event object. When passed in as an option, 
 * the location of the click will be used as the starting point for the opening animation
 * of the the dialog.
 * @param {object=} resolve Similar to locals, except it takes promises as values
 * and the bottom sheet will not open until the promises resolve.
 * @param {string=} controllerAs An alias to assign the controller to on the scope.
 *
 * @returns {Promise} Returns a promise that will be resolved or rejected when
 *  `$materialBottomSheet.hide()` or `$materialBottomSheet.cancel()` is called respectively.
 */

/**
 * @ngdoc method
 * @name $materialBottomSheet#hide
 *
 * @description
 * Hide the existing bottom sheet and `resolve` the promise returned from 
 * `$materialBottomSheet.show()`.
 *
 * @param {*} arg An argument to resolve the promise with.
 *
 */

/**
 * @ngdoc method
 * @name $materialBottomSheet#cancel
 *
 * @description
 * Hide the existing bottom sheet and `reject` the promise returned from 
 * `$materialBottomSheet.show()`.
 *
 * @param {*} arg An argument to reject the promise with.
 *
 */

function MaterialBottomSheet($$interimElement, $animate, $materialEffects, $timeout, $$rAF) {
  var backdrop;

  var $materialBottomSheet = $$interimElement({
    targetEvent: null,
    onShow: onShow,
    onRemove: onRemove,
  });

  return $materialBottomSheet;

  function onShow(scope, element, options) {
    // Add a backdrop that will close on click
    backdrop = angular.element('<material-backdrop class="opaque ng-enter">');
    backdrop.on('click touchstart', function() {
      $timeout($materialBottomSheet.cancel);
    });

    $animate.enter(backdrop, options.parent, null);

    var bottomSheet = new BottomSheet(element);
    options.bottomSheet = bottomSheet;

    // Give up focus on calling item
    options.targetEvent && angular.element(options.targetEvent.target).blur();

    return $animate.enter(bottomSheet.element, options.parent);

  }

  function onRemove(scope, element, options) {
    var bottomSheet = options.bottomSheet;
    $animate.leave(backdrop);
    return $animate.leave(bottomSheet.element).then(function() {
      bottomSheet.cleanup();

      // Restore focus
      options.targetEvent && angular.element(options.targetEvent.target).focus();
    });
  }

  /**
   * BottomSheet class to apply bottom-sheet behavior to an element
   */
  function BottomSheet(element) {
    var MAX_OFFSET = 80; // amount past the bottom of the element that we can drag down, this is same as in _bottomSheet.scss
    var WIGGLE_AMOUNT = 20; // point where it starts to get "harder" to drag
    var CLOSING_VELOCITY = 10; // how fast we need to flick down to close the sheet
    var startY, lastY, velocity, transitionDelay, startTarget;

    // coercion incase $materialCompiler returns multiple elements
    element = element.eq(0);

    element.on('touchstart', onTouchStart);
    element.on('touchmove', onTouchMove);
    element.on('touchend', onTouchEnd);

    return {
      element: element,
      cleanup: function cleanup() {
        element.off('touchstart', onTouchStart);
        element.off('touchmove', onTouchMove);
        element.off('touchend', onTouchEnd);
      }
    };

    function onTouchStart(e) {
      e.preventDefault();
      startTarget = e.target;
      startY = getY(e);
      
      // Disable transitions on transform so that it feels fast
      transitionDelay = element.css($materialEffects.TRANSITION_DURATION);
      element.css($materialEffects.TRANSITION_DURATION, '0s');
    }

    function onTouchEnd(e) {
      // Re-enable the transitions on transforms
      element.css($materialEffects.TRANSITION_DURATION, transitionDelay);

      var currentY = getY(e);
      // If we didn't scroll much, and we didn't change targets, assume its a click
      if ( Math.abs(currentY - startY) < 5  && e.target == startTarget) {
        angular.element(e.target).triggerHandler('click');
      } else {
        // If they went fast enough, trigger a close.
        if (velocity > CLOSING_VELOCITY) {
          $timeout($materialBottomSheet.cancel);

        // Otherwise, untransform so that we go back to our normal position
        } else {
          setTransformY(undefined);
        }
      }
    }

    function onTouchMove(e) {
      var currentY = getY(e);
      var delta = currentY - startY;

      velocity = currentY - lastY;
      lastY = currentY;
      
      // Do some conversion on delta to get a friction-like effect
      delta = adjustedDelta(delta);
      setTransformY(delta + MAX_OFFSET);
    }

    /**
     * Helper function to find the Y aspect of various touch events.
     **/
    function getY(e) {
      var touch = e.touches && e.touches.length ? e.touches[0] : e.changedTouches[0];
      return touch.clientY;
    }

    /**
     * Transform the element along the y-axis
     **/
    function setTransformY(amt) {
      if (amt === null || amt === undefined) {
        element.css($materialEffects.TRANSFORM, '');
      } else {
        element.css($materialEffects.TRANSFORM, 'translate3d(0, ' + amt + 'px, 0)');
      }
    }

    // Returns a new value for delta that will never exceed MAX_OFFSET_AMOUNT
    // Will get harder to exceed it as you get closer to it
    function adjustedDelta(delta) {
      if ( delta < 0  && delta < -MAX_OFFSET + WIGGLE_AMOUNT) {
        delta = -delta;
        var base = MAX_OFFSET - WIGGLE_AMOUNT;
        delta = Math.max(-MAX_OFFSET, -Math.min(MAX_OFFSET - 5, base + ( WIGGLE_AMOUNT * (delta - base)) / MAX_OFFSET) - delta / 50);
      }

      return delta;
    }
  }

}

/**
 * @ngdoc module
 * @name material.components.buttons
 * @description
 *
 * Button
 */
angular.module('material.components.button', [
  'material.animations',
  'material.services.aria'
])
  .directive('materialButton', [
    'ngHrefDirective',
    '$materialInkRipple',
    '$materialAria',
    MaterialButtonDirective
  ]);

/**
 * @ngdoc directive
 * @name materialButton
 * @order 0
 *
 * @restrict E
 *
 * @description
 * `<material-button>` is a button directive with optional ink ripples (default enabled).
 *
 * @param {boolean=} noink If present, disable ripple ink effects.
 * @param {boolean=} disabled If present, disable tab selection.
 * @param {string=} type Optional attribute to specific button types (useful for forms); such as 'submit', etc.
 * @param {string=} ng-href Optional attribute to support both ARIA and link navigation
 * @param {string=} href Optional attribute to support both ARIA and link navigation
 * @param {string=} ariaLabel Publish the button label used by screen-readers for accessibility. Defaults to the button's text.
 *
 * @usage
 * <hljs lang="html">
 *  <material-button>Button</material-button>
 *  <br/>
 *  <material-button noink class="material-button-colored">
 *    Button (noInk)
 *  </material-button>
 *  <br/>
 *  <material-button disabled class="material-button-colored">
 *    Colored (disabled)
 *  </material-button>
 * </hljs>
 */
function MaterialButtonDirective(ngHrefDirectives, $materialInkRipple, $materialAria ) {
  var ngHrefDirective = ngHrefDirectives[0];

  return {
    restrict: 'E',
    compile: function(element, attr) {
      var innerElement;
      var attributesToCopy;

      // Add an inner anchor if the element has a `href` or `ngHref` attribute,
      // so this element can be clicked like a normal `<a>`.
      if (attr.ngHref || attr.href) {
        innerElement = angular.element('<a>');
        attributesToCopy = ['ng-href', 'href', 'rel', 'target'];
      // Otherwise, just add an inner button element (for form submission etc)
      } else {
        innerElement = angular.element('<button>');
        attributesToCopy = ['type', 'disabled', 'ng-disabled', 'form'];
      }

      angular.forEach(attributesToCopy, function(name) {
        var camelCaseName = Util.camelCase(name);
        if (attr.hasOwnProperty(camelCaseName)) {
          innerElement.attr(name, attr[camelCaseName]);
        }
      });

      innerElement
        .addClass('material-button-inner')
        .append(element.contents())
        // Since we're always passing focus to the inner element,
        // add a focus class to the outer element so we can still style
        // it with focus.
        .on('focus', function() {
          element.addClass('focus');
        })
        .on('blur', function() {
          element.removeClass('focus');
        });

      element.
        append(innerElement)
        .attr('tabIndex', -1)
        //Always pass focus to innerElement
        .on('focus', function() {
          innerElement.focus();
        });

      return function postLink(scope, element, attr) {
        $materialAria.expect(element, 'aria-label', element.text());
        $materialInkRipple.attachButtonBehavior(element);
      };
    }
  };

}

/**
 * @ngdoc module
 * @name material.components.card
 *
 * @description
 * Card components.
 */
angular.module('material.components.card', [
])
  .directive('materialCard', [
    materialCardDirective 
  ]);



/**
 * @ngdoc directive
 * @name materialCard
 * @module material.components.card
 *
 * @restrict E
 *
 * @description
 * The `<material-card>` directive is a container element used within `<material-content>` containers.
 *
 * Cards have constant width and variable heights; where the maximum height is limited to what can
 * fit within a single view on a platform, but it can temporarily expand as needed
 *
 * @usage
 * <hljs lang="html">
 * <material-card>
 *  <img src="/img/washedout.png" class="material-card-image">
 *  <h2>Paracosm</h2>
 *  <p>
 *    The titles of Washed Out's breakthrough song and the first single from Paracosm share the * two most important words in Ernest Greene's musical language: feel it. It's a simple request, as well...
 *  </p>
 * </material-card>
 * </hljs>
 *
 */
function materialCardDirective() {
  return {
    restrict: 'E',
    link: function($scope, $element, $attr) {
    }
  };
}

/**
 * @ngdoc module
 * @name material.components.checkbox
 * @description Checkbox module!
 */
angular.module('material.components.checkbox', [
  'material.animations',
  'material.services.aria'
])
  .directive('materialCheckbox', [ 
    'inputDirective',
    '$materialInkRipple',
    '$materialAria',
    MaterialCheckboxDirective
  ]);

/**
 * @ngdoc directive
 * @name materialCheckbox
 * @module material.components.checkbox
 * @restrict E
 *
 * @description
 * The checkbox directive is used like the normal [angular checkbox](https://docs.angularjs.org/api/ng/input/input%5Bcheckbox%5D).
 *
 * @param {string} ngModel Assignable angular expression to data-bind to.
 * @param {string=} name Property name of the form under which the control is published.
 * @param {expression=} ngTrueValue The value to which the expression should be set when selected.
 * @param {expression=} ngFalseValue The value to which the expression should be set when not selected.
 * @param {string=} ngChange Angular expression to be executed when input changes due to user interaction with the input element.
 * @param {boolean=} noink Use of attribute indicates use of ripple ink effects
 * @param {boolean=} disabled Use of attribute indicates the switch is disabled: no ink effects and not selectable
 * @param {string=} ariaLabel Publish the button label used by screen-readers for accessibility. Defaults to the checkbox's text.
 *
 * @usage
 * <hljs lang="html">
 * <material-checkbox ng-model="isChecked" aria-label="Finished?">
 *   Finished ?
 * </material-checkbox>
 *
 * <material-checkbox noink ng-model="hasInk" aria-label="No Ink Effects">
 *   No Ink Effects
 * </material-checkbox>
 *
 * <material-checkbox disabled ng-model="isDisabled" aria-label="Disabled">
 *   Disabled
 * </material-checkbox>
 *
 * </hljs>
 *
 */
function MaterialCheckboxDirective(inputDirectives, $materialInkRipple, $materialAria) {
  var inputDirective = inputDirectives[0];

  var CHECKED_CSS = 'material-checked';

  return {
    restrict: 'E',
    transclude: true,
    require: '?ngModel',
    template: 
      '<div class="material-container" ink-ripple="checkbox">' +
        '<div class="material-icon"></div>' +
      '</div>' +
      '<div ng-transclude class="material-label"></div>',
    compile: compile
  };

  // **********************************************************
  // Private Methods
  // **********************************************************

  function compile (tElement, tAttrs) {

    tAttrs.type = 'checkbox';
    tAttrs.tabIndex = 0;
    tElement.attr('role', tAttrs.type);

    $materialAria.expect(tElement, 'aria-label', tElement.text());

    return function postLink(scope, element, attr, ngModelCtrl) {
      var checked = false;

      // Create a mock ngModel if the user doesn't provide one
      ngModelCtrl = ngModelCtrl || {
        $setViewValue: function(value) {
          this.$viewValue = value;
        },
        $parsers: [],
        $formatters: []
      };

      // Reuse the original input[type=checkbox] directive from Angular core.
      // This is a bit hacky as we need our own event listener and own render
      // function.
      inputDirective.link.pre(scope, {
        on: angular.noop,
        0: {}
      }, attr, [ngModelCtrl]);

      element.on('click', listener);
      element.on('keypress', keypressHandler);
      ngModelCtrl.$render = render;

      function keypressHandler(ev) {
        if(ev.which === Constant.KEY_CODE.SPACE) {
          ev.preventDefault();
          listener(ev);
        }
      }
      function listener(ev) {
        if (element[0].hasAttribute('disabled')) return;

        scope.$apply(function() {
          checked = !checked;
          ngModelCtrl.$setViewValue(checked, ev && ev.type);
          ngModelCtrl.$render();
        });
      }

      function render() {
        checked = ngModelCtrl.$viewValue;
        // element.attr('aria-checked', checked);
        if(checked) {
          element.addClass(CHECKED_CSS);
        } else {
          element.removeClass(CHECKED_CSS);
        }
      }
    }
  }
}



/**
 * @ngdoc module
 * @name material.components.content
 *
 * @description
 * Scrollable content
 */
angular.module('material.components.content', [
  'material.services.registry'
])
  .directive('materialContent', [
    materialContentDirective
  ]);

/**
 * @ngdoc directive
 * @name materialContent
 * @module material.components.content
 *
 * @restrict E
 *
 * @description
 * The `<material-content>` directive is a container element useful for scrollable content
 *
 * @usage
 * <hljs lang="html">
 *  <material-content class="material-content-padding">
 *      Lorem ipsum dolor sit amet, ne quod novum mei.
 *  </material-content>
 * </hljs>
 *
 */
function materialContentDirective() {
  return {
    restrict: 'E',
    controller: ['$scope', '$element', ContentController],
    link: function($scope, $element, $attr) {
      $scope.$broadcast('$materialContentLoaded', $element);
    }
  };

  function ContentController($scope, $element) {
    this.$scope = $scope;
    this.$element = $element;
  }
}

/**
 * @ngdoc module
 * @name material.components.dialog
 */
angular.module('material.components.dialog', [
  'material.animations',
  'material.services.compiler',
  'material.services.aria',
  'material.services.interimElement',
])
  .directive('materialDialog', [
    '$$rAF',
    MaterialDialogDirective
  ])
  .factory('$materialDialog', [
    '$timeout',
    '$rootElement',
    '$materialEffects',
    '$animate',
    '$materialAria',
    '$$interimElement',
    MaterialDialogService
  ]);

function MaterialDialogDirective($$rAF) {
  return {
    restrict: 'E',
    link: function(scope, element, attr) {
      $$rAF(function() {
        var content = element[0].querySelector('.dialog-content');
        if (content && content.scrollHeight > content.clientHeight) {
          element.addClass('dialog-content-overflow');
        }
      });
    }
  };
}

/**
 * @ngdoc service
 * @name $materialDialog
 * @module material.components.dialog
 *
 * @description
 *
 * Used to open a dialog over top of the app, `$materialDialog` is a service created
 * by `$$interimElement` and provides a simple promise-based, behavior API:
 *
 *  - `$materialDialog.show()`
 *  - `$materialDialog.hide()`
 *  - `$materialDialog.cancel()`
 *
 * #### Notes:
 *
 * The dialog is always given an isolate scope.
 *
 * The dialog's template must have an outer `<material-dialog>` element.
 * Inside, use an element with class `dialog-content` for the dialog's content, and use
 * an element with class `dialog-actions` for the dialog's actions.  
 *
 * When opened, the `dialog-actions` area will attempt to focus the first button found with 
 * class `dialog-close`. If no button with `dialog-close` class is found, it will focus the
 * last button in the `dialog-actions` area.
 *
 * @usage
 * <hljs lang="html">
 * <div ng-controller="MyController">
 *   <material-button ng-click="openDialog($event)">
 *     Open a Dialog from this button!
 *   </material-button>
 * </div>
 * </hljs>
 * <hljs lang="js">
 * var app = angular.module('app', ['ngMaterial']);
 * app.controller('MyController', function($scope, $materialDialog) {
 *   $scope.openDialog = function($event) {
 *     $materialDialog.show({
 *       template: '<material-dialog>Hello!</material-dialog>',
 *       targetEvent: $event
 *     });
 *   };
 * });
 * </hljs>
 *
 */

/**
 *
 * @ngdoc method
 * @name $materialDialog#show
 *
 * @description
 * Show a dialog with the specified options
 *
 * @paramType Options
 * @param {string=} templateUrl The url of a template that will be used as the content
 * of the dialog. 
 * @param {string=} template Same as templateUrl, except this is an actual template string.
 * @param {DOMClickEvent=} targetEvent A click's event object. When passed in as an option, 
 * the location of the click will be used as the starting point for the opening animation
 * of the the dialog.
 * @param {boolean=} hasBackdrop Whether there should be an opaque backdrop behind the dialog.
 *   Default true.
 * @param {boolean=} clickOutsideToClose Whether the user can click outside the dialog to
 *   close it. Default true.
 * @param {boolean=} escapeToClose Whether the user can press escape to close the dialog.
 *   Default true.
 * @param {string=} controller The controller to associate with the dialog.
 * @param {object=} locals An object containing key/value pairs. The keys will be used as names
 * of values to inject into the controller. For example, `locals: {three: 3}` would inject
 * `three` into the controller, with the value 3.
 * @param {object=} resolve Similar to locals, except it takes promises as values, and the
 * toast will not open until all of the promises resolve.
 * @param {string=} controllerAs An alias to assign the controller to on the scope.
 * @param {element=} parent The element to append the dialog to. Defaults to appending
 *   to the root element of the application.
 *
 * @returns {Promise} Returns a promise that will be resolved or rejected when
 *  `$materialDialog.hide()` or `$materialDialog.cancel()` is called respectively.
 */

/**
 * @ngdoc method
 * @name $materialDialog#hide
 *
 * @description
 * Hide an existing dialog and `resolve` the promise returned from `$materialDialog.show()`.
 *
 * @param {*} arg An argument to resolve the promise with.
 *
 */

/**
 * @ngdoc method
 * @name $materialDialog#cancel
 *
 * @description
 * Hide an existing dialog and `reject` the promise returned from `$materialDialog.show()`.
 *
 * @param {*} arg An argument to reject the promise with.
 *
 */

function MaterialDialogService($timeout, $rootElement, $materialEffects, $animate, $materialAria, $$interimElement) {

  var $dialogService;
  return $dialogService = $$interimElement({
    hasBackdrop: true,
    isolateScope: true,
    onShow: onShow,
    onRemove: onRemove,
    clickOutsideToClose: true,
    escapeToClose: true,
    targetEvent: null,
    transformTemplate: function(template) {
      return '<div class="material-dialog-container">' + template + '</div>';
    }
  });

  function onShow(scope, element, options) {
    // Incase the user provides a raw dom element, always wrap it in jqLite
    options.parent = angular.element(options.parent);

    options.popInTarget = angular.element((options.targetEvent || {}).target); 
    var closeButton = findCloseButton();

    configureAria(element.find('material-dialog'));

    if (options.hasBackdrop) {
      var backdrop = angular.element('<material-backdrop class="opaque ng-enter">');
      $animate.enter(backdrop, options.parent, null);
      options.backdrop = backdrop;
    }

    return $materialEffects.popIn(
      element, 
      options.parent, 
      options.popInTarget.length && options.popInTarget
    )
    .then(function() {
      if (options.escapeToClose) {
        options.rootElementKeyupCallback = function(e) {
          if (e.keyCode === Constant.KEY_CODE.ESCAPE) {
            $timeout($dialogService.cancel);
          }
        };

        $rootElement.on('keyup', options.rootElementKeyupCallback);
      }

      if (options.clickOutsideToClose) {
        options.dialogClickOutsideCallback = function(e) {
          // Only close if we click the flex container outside the backdrop
          if (e.target === element[0]) {
            $timeout($dialogService.cancel);
          }
        };

        element.on('click', options.dialogClickOutsideCallback);
      }
      closeButton.focus();
    });


    function findCloseButton() {
      //If no element with class dialog-close, try to find the last
      //button child in dialog-actions and assume it is a close button
      var closeButton = element[0].querySelector('.dialog-close');
      if (!closeButton) {
        var actionButtons = element[0].querySelectorAll('.dialog-actions button');
        closeButton = actionButtons[ actionButtons.length - 1 ];
      }
      return angular.element(closeButton);
    }

  }

  function onRemove(scope, element, options) {

    if (options.backdrop) {
      $animate.leave(options.backdrop);
      element.data('backdrop', undefined);
    }
    if (options.escapeToClose) {
      $rootElement.off('keyup', options.rootElementKeyupCallback);
    }
    if (options.clickOutsideToClose) {
      element.off('click', options.dialogClickOutsideCallback);
    }
    return $animate.leave(element).then(function() {
      element.remove();
      options.popInTarget && options.popInTarget.focus();
    });

  }

  /**
   * Inject ARIA-specific attributes appropriate for Dialogs
   */
  function configureAria(element) {
    element.attr({
      'role': 'dialog'
    });

    var dialogContent = element.find('.dialog-content');
    if (dialogContent.length === 0){
      dialogContent = element;
    }
    var defaultText = Util.stringFromTextBody(dialogContent.text(), 3);
    $materialAria.expect(element, 'aria-label', defaultText);
  }
}

/**
 * @ngdoc module
 * @name material.components.textField
 * @description
 * Form
 */
angular.module('material.components.textField', [])
  .directive('materialInputGroup', [
    materialInputGroupDirective
  ])
  .directive('materialInput', [
    materialInputDirective
  ]);

/**
 * @ngdoc directive
 * @name materialInputGroup
 * @module material.components.textField
 * @restrict E
 * @description
 * Use the `<material-input-group>` directive as the grouping parent of a `<material-input>` element.
 *
 * @usage 
 * <hljs lang="html">
 * <material-input-group ng-disabled="isDisabled">
 *   <label for="{{fid}}">{{someLabel}}</label>
 *   <material-input id="{{fid}}" type="text" ng-model="someText"></material-input>
 * </material-input-group>
 * </hljs>
 */
function materialInputGroupDirective() {
  return {
    restrict: 'CE',
    controller: ['$element', function($element) {
      this.setFocused = function(isFocused) {
        $element.toggleClass('material-input-focused', !!isFocused);
      };
      this.setHasValue = function(hasValue) {
        $element.toggleClass('material-input-has-value', !!hasValue);
      };
    }]
  };
}

/**
 * @ngdoc directive
 * @name materialInput
 * @module material.components.textField
 *
 * @restrict E
 *
 * @description
 * Use the `<material-input>` directive as elements within a `<material-input-group>` container
 *
 * @usage
 * <hljs lang="html">
 * <material-input-group ng-disabled="user.isLocked">
 *   <label for="i1">FirstName</label>
 *   <material-input id="i1" ng-model="user.firstName"></material-input>
 * </material-input-group>
 * </hljs>
 */
function materialInputDirective() {
  return {
    restrict: 'E',
    replace: true,
    template: '<input >',
    require: ['^?materialInputGroup', '?ngModel'],
    link: function(scope, element, attr, ctrls) {
      var inputGroupCtrl = ctrls[0];
      var ngModelCtrl = ctrls[1];
      if (!inputGroupCtrl) {
        return;
      }

      // scan for disabled and transpose the `type` value to the <input> element
      var isDisabled = Util.isParentDisabled(element);

      element.attr('tabindex', isDisabled ? -1 : 0 );
      element.attr('type', attr.type || element.parent().attr('type') || "text" );

      // When the input value changes, check if it "has" a value, and
      // set the appropriate class on the input group
      if (ngModelCtrl) {
        //Add a $formatter so we don't use up the render function
        ngModelCtrl.$formatters.push(function(value) {
          inputGroupCtrl.setHasValue(!!value);
          return value;
        });
      }

      element.on('input', function() {
        inputGroupCtrl.setHasValue(!!element.val());
      });

      // When the input focuses, add the focused class to the group
      element.on('focus', function(e) {
        inputGroupCtrl.setFocused(true);
      });
      // When the input blurs, remove the focused class from the group
      element.on('blur', function(e) {
        inputGroupCtrl.setFocused(false);
      });

      scope.$on('$destroy', function() {
        inputGroupCtrl.setFocused(false);
        inputGroupCtrl.setHasValue(false);
      });
    }
  };
}

/**
 * @ngdoc module
 * @name material.components.icon
 * @description
 * Icon
 */
angular.module('material.components.icon', [])
  .directive('materialIcon', [
    materialIconDirective
  ]);

/**
 * @ngdoc directive
 * @name materialIcon
 * @module material.components.icon
 *
 * @restrict E
 *
 * @description
 * The `<material-icon>` directive is an element useful for SVG icons
 *
 * @usage
 * <hljs lang="html">
 *  <material-icon icon="/img/icons/ic_access_time_24px.svg">
 *  </material-icon>
 * </hljs>
 *
 */
function materialIconDirective() {
  return {
    restrict: 'E',
    template: '<object class="material-icon"></object>',
    compile: function(element, attr) {
      var object = angular.element(element[0].children[0]);
      if(angular.isDefined(attr.icon)) {
        object.attr('data', attr.icon);
      }
    }
  };
}

/**
 * @ngdoc module
 * @name material.components.list
 * @description
 * List module
 */
angular.module('material.components.list', [])

.directive('materialList', [
  materialListDirective
])
.directive('materialItem', [
  materialItemDirective
]);

/**
 * @ngdoc directive
 * @name materialList
 * @module material.components.list
 *
 * @restrict E
 *
 * @description
 * The `<material-list>` directive is a list container for 1..n `<material-item>` tags.
 *
 * @usage
 * <hljs lang="html">
 * <material-list>
 *  <material-item ng-repeat="item in todos">
 *    <div class="material-tile-left">
 *      <img ng-src="{{item.face}}" class="face" alt="{{item.who}}">
 *    </div>
 *    <div class="material-tile-content">
 *      <h3>{{item.what}}</h3>
 *      <h4>{{item.who}}</h4>
 *      <p>
 *        {{item.notes}}
 *      </p>
 *    </div>
 *
 *  </material-item>
 * </material-list>
 * </hljs>
 *
 */
function materialListDirective() {
  return {
    restrict: 'E',
    link: function($scope, $element, $attr) {
      $element.attr({
        'role' : 'list'
      });
    }
  };
}

/**
 * @ngdoc directive
 * @name materialItem
 * @module material.components.list
 *
 * @restrict E
 *
 * @description
 * The `<material-item>` directive is a container intended for row items in a `<material-list>` container.
 *
 * @usage
 * <hljs lang="html">
 *  <material-list>
 *    <material-item>
 *            Item content in list
 *    </material-item>
 *  </material-list>
 * </hljs>
 *
 */
function materialItemDirective() {
  return {
    restrict: 'E',
    link: function($scope, $element, $attr) {
      $element.attr({
        'role' : 'listitem'
      });
    }
  };
}


/**
 * @ngdoc module
 * @name material.components.radioButton
 * @description radioButton module!
 */
angular.module('material.components.radioButton', [
  'material.animations',
  'material.services.aria'
])
  .directive('materialRadioGroup', [
    materialRadioGroupDirective
  ])
  .directive('materialRadioButton', [
    '$materialAria',
    materialRadioButtonDirective
  ]);

/**
 * @ngdoc directive
 * @module material.components.radioButton
 * @name materialRadioGroup
 *
 * @order 0
 * @restrict E
 *
 * @description
 * The `<material-radio-group>` directive identifies a grouping
 * container for the 1..n grouped material radio buttons; specified using nested
 * `<material-radio-button>` tags.
 *
 * @param {string} ngModel Assignable angular expression to data-bind to.
 * @param {boolean=} noink Use of attribute indicates flag to disable ink ripple effects.
 *
 * @usage
 * <hljs lang="html">
 * <material-radio-group ng-model="selected">
 *
 *   <material-radio-button
 *        ng-repeat="d in colorOptions"
 *        ng-value="d.value" aria-label="{{ d.label }}">
 *
 *          {{ d.label }}
 *
 *   </material-radio-button>
 *
 * </material-radio-group>
 * </hljs>
 *
 */
function materialRadioGroupDirective() {
  RadioGroupController.prototype = createRadioGroupControllerProto();

  return {
    restrict: 'E',
    controller: ['$element', RadioGroupController],
    require: ['materialRadioGroup', '?ngModel'],
    link: link
  };

  function link(scope, element, attr, ctrls) {
    var rgCtrl = ctrls[0],
      ngModelCtrl = ctrls[1] || {
        $setViewValue: angular.noop
      };

    function keydownListener(ev) {
      if (ev.which === Constant.KEY_CODE.LEFT_ARROW || ev.which === Constant.KEY_CODE.UP_ARROW) {
        ev.preventDefault();
        rgCtrl.selectPrevious();
      }
      else if (ev.which === Constant.KEY_CODE.RIGHT_ARROW || ev.which === Constant.KEY_CODE.DOWN_ARROW) {
        ev.preventDefault();
        rgCtrl.selectNext();
      }
    }

    rgCtrl.init(ngModelCtrl);

    element.attr({
      'role': 'radiogroup',
      'tabIndex': '0'
    })
    .on('keydown', keydownListener);
  }

  function RadioGroupController($element) {
    this._radioButtonRenderFns = [];
    this.$element = $element;
  }

  function createRadioGroupControllerProto() {
    return {
      init: function(ngModelCtrl) {
        this._ngModelCtrl = ngModelCtrl;
        this._ngModelCtrl.$render = angular.bind(this, this.render);
      },
      add: function(rbRender) {
        this._radioButtonRenderFns.push(rbRender);
      },
      remove: function(rbRender) {
        var index = this._radioButtonRenderFns.indexOf(rbRender);
        if (index !== -1) {
          this._radioButtonRenderFns.splice(index, 1);
        }
      },
      render: function() {
        this._radioButtonRenderFns.forEach(function(rbRender) {
          rbRender();
        });
      },
      setViewValue: function(value, eventType) {
        this._ngModelCtrl.$setViewValue(value, eventType);
        // update the other radio buttons as well
        this.render();
      },
      getViewValue: function() {
        return this._ngModelCtrl.$viewValue;
      },
      selectNext: function() {
        return changeSelectedButton(this.$element, 1);
      },
      selectPrevious : function() {
        return changeSelectedButton(this.$element, -1);
      },
      setActiveDescendant: function (radioId) {
        this.$element.attr('aria-activedescendant', radioId);
      }
    };
  }
  /**
   * Change the radio group's selected button by a given increment.
   * If no button is selected, select the first button.
   */
  function changeSelectedButton(parent, increment) {
    // Coerce all child radio buttons into an array, then wrap then in an iterator
    var buttons = Util.iterator(
      Array.prototype.slice.call(parent[0].querySelectorAll('material-radio-button')),
      true
    );

    if (buttons.count()) {
      var selected = parent[0].querySelector('material-radio-button.material-checked');
      var target = buttons[increment < 0 ? 'previous' : 'next'](selected) || 
        buttons.first();
      // Activate radioButton's click listener (triggerHandler won't create a real click event)
      angular.element(target).triggerHandler('click');
    }
  }

}

/**
 * @ngdoc directive
 * @module material.components.radioButton
 * @name materialRadioButton
 *
 * @order 1
 * @restrict E
 *
 * @description
 * The `<material-radio-button>`directive is the child directive required to be used within `<material-radioo-group>` elements.
 *
 * While similar to the `<input type="radio" ng-model="" value="">` directive,
 * the `<material-radio-button>` directive provides material ink effects, ARIA support, and
 * supports use within named radio groups.
 *
 * @param {string} ngModel Assignable angular expression to data-bind to.
 * @param {string=} ngChange Angular expression to be executed when input changes due to user
 *    interaction with the input element.
 * @param {string} ngValue Angular expression which sets the value to which the expression should
 *    be set when selected.*
 * @param {string} value The value to which the expression should be set when selected.
 * @param {string=} name Property name of the form under which the control is published.
 * @param {string=} ariaLabel Publish the button label used by screen-readers for accessibility. Defaults to the radio button's text.
 *
 * @usage
 * <hljs lang="html">
 *
 * <material-radio-button value="1" aria-label="Label 1">
 *   Label 1
 * </material-radio-button>
 *
 * <material-radio-button ng-model="color" ng-value="specialValue" aria-label="Green">
 *   Green
 * </material-radio-button>
 *
 * </hljs>
 *
 */
function materialRadioButtonDirective($materialAria) {

  var CHECKED_CSS = 'material-checked';

  return {
    restrict: 'E',
    require: '^materialRadioGroup',
    transclude: true,
    template: '<div class="material-container" ink-ripple="checkbox">' +
                '<div class="material-off"></div>' +
                '<div class="material-on"></div>' +
              '</div>' +
              '<div ng-transclude class="material-label"></div>',
    link: link
  };

  function link(scope, element, attr, rgCtrl) {
    var lastChecked;

    configureAria(element, scope);

    rgCtrl.add(render);
    attr.$observe('value', render);

    element
      .on('click', listener)
      .on('$destroy', function() {
        rgCtrl.remove(render);
      });

    function listener(ev) {
      if (element[0].hasAttribute('disabled')) return;

      scope.$apply(function() {
        rgCtrl.setViewValue(attr.value, ev && ev.type);
      });
    }

    function render() {
      var checked = (rgCtrl.getViewValue() === attr.value);
      if (checked === lastChecked) {
        return;
      }
      lastChecked = checked;
      element.attr('aria-checked', checked);
      if (checked) {
        element.addClass(CHECKED_CSS);
        rgCtrl.setActiveDescendant(element.attr('id'));
      } else {
        element.removeClass(CHECKED_CSS);
      }
    }
    /**
     * Inject ARIA-specific attributes appropriate for each radio button
     */
    function configureAria( element, scope ){
      scope.ariaId = buildAriaID();

      element.attr({
        'id' :  scope.ariaId,
        'role' : 'radio',
        'aria-checked' : 'false'
      });

      $materialAria.expect(element, 'aria-label', element.text());

      /**
       * Build a unique ID for each radio button that will be used with aria-activedescendant.
       * Preserve existing ID if already specified.
       * @returns {*|string}
       */
      function buildAriaID() {
        return attr.id || ( 'radio' + "_" + Util.nextUid() );
      }
    }
  }
}



/**
 * @ngdoc module
 * @name material.components.sidenav
 *
 * @description
 * A Sidenav QP component.
 */
angular.module('material.components.sidenav', [
  'material.services.registry',
  'material.animations'
])
  .factory('$materialSidenav', [
    '$materialComponentRegistry', 
    materialSidenavService 
  ])
  .directive('materialSidenav', [
    '$timeout',
    '$materialEffects',
    '$$rAF',
    materialSidenavDirective 
  ])
  .controller('$materialSidenavController', [
    '$scope',
    '$element',
    '$attrs',
    '$timeout',
    '$materialSidenav',
    '$materialComponentRegistry',
    materialSidenavController 
  ]);
  
/**
 * @private
 * @ngdoc object
 * @name materialSidenavController
 * @module material.components.sidenav
 *
 * @description
 * The controller for materialSidenav components.
 */
function materialSidenavController($scope, $element, $attrs, $timeout, $materialSidenav, $materialComponentRegistry) {

  var self = this;

  $materialComponentRegistry.register(this, $attrs.componentId);

  this.isOpen = function() {
    return !!$scope.isOpen;
  };

  /**
   * Toggle the side menu to open or close depending on its current state.
   */
  this.toggle = function() {
    $scope.isOpen = !$scope.isOpen;
  };

  /**
   * Open the side menu
   */
  this.open = function() {
    $scope.isOpen = true;
  };

  /**
   * Close the side menu
   */
  this.close = function() {
    $scope.isOpen = false;
  };
}

/**
 * @private
 * @ngdoc service
 * @name $materialSidenav
 * @module material.components.sidenav
 *
 * @description
 * $materialSidenav makes it easy to interact with multiple sidenavs
 * in an app.
 *
 * @usage
 *
 * ```javascript
 * // Toggle the given sidenav
 * $materialSidenav(componentId).toggle();
 *
 * // Open the given sidenav
 * $materialSidenav(componentId).open();
 *
 * // Close the given sidenav
 * $materialSidenav(componentId).close();
 * ```
 */
function materialSidenavService($materialComponentRegistry) {
  return function(handle) {
    var instance = $materialComponentRegistry.get(handle);
    if(!instance) {
      $materialComponentRegistry.notFoundError(handle);
    }

    return {
      isOpen: function() {
        if (!instance) { return; }
        return instance.isOpen();
      },
      /**
       * Toggle the given sidenav
       * @param handle the specific sidenav to toggle
       */
      toggle: function() {
        if(!instance) { return; }
        instance.toggle();
      },
      /**
       * Open the given sidenav
       * @param handle the specific sidenav to open
       */
      open: function(handle) {
        if(!instance) { return; }
        instance.open();
      },
      /**
       * Close the given sidenav
       * @param handle the specific sidenav to close
       */
      close: function(handle) {
        if(!instance) { return; }
        instance.close();
      }
    };
  };
}

/**
 * @ngdoc directive
 * @name materialSidenav
 * @module material.components.sidenav
 * @restrict E
 *
 * @description
 *
 * A Sidenav component that can be opened and closed programatically.
 *
 * When used properly with a layout, it will seamleslly stay open on medium
 * and larger screens, while being hidden by default on mobile devices.
 *
 * @usage
 * <hljs lang="html">
 * <div layout="horizontal" ng-controller="MyController">
 *   <material-sidenav component-id="left" class="material-sidenav-left">
 *     Left Nav!
 *   </material-sidenav>
 *
 *   <material-content>
 *     Center Content
 *     <material-button ng-click="openLeftMenu()">
 *       Open Left Menu
 *     </material-button>
 *   </material-content>
 *
 *   <material-sidenav component-id="right" class="material-sidenav-right">
 *     Right Nav!
 *   </material-sidenav>
 * </div>
 * </hljs>
 *
 * <hljs lang="js">
 * var app = angular.module('myApp', ['ngMaterial']);
 * app.controller('MainController', function($scope, $materialSidenav) {
 *   $scope.openLeftMenu = function() {
 *     $materialSidenav('left').toggle();
 *   };
 * });
 * </hljs>
 */
function materialSidenavDirective($timeout, $materialEffects, $$rAF) {
  return {
    restrict: 'E',
    scope: {},
    controller: '$materialSidenavController',
    compile: compile
  };

  function compile(element, attr) {
    element.addClass('closed');

    return postLink;
  }
  function postLink(scope, element, attr, sidenavCtrl) {
    var backdrop = angular.element('<material-backdrop class="material-sidenav-backdrop">');

    scope.$watch('isOpen', onShowHideSide);
    element.on($materialEffects.TRANSITIONEND_EVENT, onTransitionEnd);

    /**
     * Toggle the SideNav view and attach/detach listeners
     * @param isOpen
     */
    function onShowHideSide(isOpen) {
      var parent = element.parent();

      if (isOpen) {
        element.removeClass('closed');

        parent.append(backdrop);
        backdrop.on('click', close);
        parent.on('keydown', onKeyDown);

      } else {
        backdrop.remove();
        backdrop.off('click', close);
        parent.off('keydown', onKeyDown);
      }

      // Wait until the next frame, so that if the `closed` class was just removed the 
      // element has a chance to 're-initialize' from being display: none.
      $$rAF(function() {
        element.toggleClass('open', !!scope.isOpen);
      });
    }

    function onTransitionEnd(ev) {
      if (ev.target === element[0] && !scope.isOpen) {
        element.addClass('closed');
      }
    }

    /**
     * Auto-close sideNav when the `escape` key is pressed.
     * @param evt
     */
    function onKeyDown(evt) {
      if(evt.which === Constant.KEY_CODE.ESCAPE){
        close();

        evt.preventDefault();
        evt.stopPropagation();
      }
    }

    /**
     * With backdrop `clicks` or `escape` key-press, immediately
     * apply the CSS close transition... Then notify the controller
     * to close() and perform its own actions.
     */
    function close() {

      onShowHideSide( false );

      $timeout(function(){
        sidenavCtrl.close();
      });
    }

  }

}

/**
 * @ngdoc module
 * @name material.components.slider
 */
angular.module('material.components.slider', [
  'material.animations',
  'material.services.aria'
])
.directive('materialSlider', [
  SliderDirective
]);

/**
 * @ngdoc directive
 * @name materialSlider
 * @module material.components.slider
 * @restrict E
 * @description
 * The `<material-slider>` component allows the user to choose from a range of
 * values.
 *
 * It has two modes: 'normal' mode, where the user slides between a wide range
 * of values, and 'discrete' mode, where the user slides between only a few
 * select values.
 *
 * To enable discrete mode, add the `discrete` attribute to a slider,
 * and use the `step` attribute to change the distance between
 * values the user is allowed to pick.
 *
 * @usage
 * <h4>Normal Mode</h4>
 * <hljs lang="html">
 * <material-slider ng-model="myValue" min="5" max="500">
 * </material-slider>
 * </hljs>
 * <h4>Discrete Mode</h4>
 * <hljs lang="html">
 * <material-slider discrete ng-model="myDiscreteValue" step="10" min="10" max="130">
 * </material-slider>
 * </hljs>
 *
 * @param {boolean=} discrete Whether to enable discrete mode.
 * @param {number=} step The distance between values the user is allowed to pick. Default 1.
 * @param {number=} min The minimum value the user is allowed to pick. Default 0.
 * @param {number=} max The maximum value the user is allowed to pick. Default 100.
 */
function SliderDirective() {
  return {
    scope: {},
    require: ['?ngModel', 'materialSlider'],
    controller: [
      '$scope',
      '$element',
      '$attrs',
      '$$rAF',
      '$window',
      '$materialEffects',
      '$materialAria',
      SliderController
    ],
    template:
      '<div class="slider-track-container">' +
        '<div class="slider-track"></div>' +
        '<div class="slider-track slider-track-fill"></div>' +
        '<div class="slider-track-ticks"></div>' +
      '</div>' +
      '<div class="slider-thumb-container">' +
        '<div class="slider-thumb"></div>' +
        '<div class="slider-focus-thumb"></div>' +
        '<div class="slider-focus-ring"></div>' +
        '<div class="slider-sign">' +
          '<span class="slider-thumb-text" ng-bind="modelValue"></span>' +
        '</div>' +
        '<div class="slider-disabled-thumb"></div>' +
      '</div>',
    link: postLink
  };

  function postLink(scope, element, attr, ctrls) {
    var ngModelCtrl = ctrls[0] || {
      // Mock ngModelController if it doesn't exist to give us
      // the minimum functionality needed
      $setViewValue: function(val) {
        this.$viewValue = val;
        this.$viewChangeListeners.forEach(function(cb) { cb(); });
      },
      $parsers: [],
      $formatters: [],
      $viewChangeListeners: []
    };

    var sliderCtrl = ctrls[1];
    sliderCtrl.init(ngModelCtrl);
  }
}

/**
 * We use a controller for all the logic so that we can expose a few
 * things to unit tests
 */
function SliderController(scope, element, attr, $$rAF, $window, $materialEffects, $materialAria) {

  this.init = function init(ngModelCtrl) {
    var thumb = angular.element(element[0].querySelector('.slider-thumb'));
    var thumbContainer = thumb.parent();
    var trackContainer = angular.element(element[0].querySelector('.slider-track-container'));
    var activeTrack = angular.element(element[0].querySelector('.slider-track-fill'));
    var tickContainer = angular.element(element[0].querySelector('.slider-track-ticks'));

    // Default values, overridable by attrs
    attr.min ? attr.$observe('min', updateMin) : updateMin(0);
    attr.max ? attr.$observe('max', updateMax) : updateMax(100);
    attr.step ? attr.$observe('step', updateStep) : updateStep(1);

    // We have to manually stop the $watch on ngDisabled because it exists
    // on the parent scope, and won't be automatically destroyed when
    // the component is destroyed.
    var stopDisabledWatch = angular.noop;
    if (attr.ngDisabled) {
      stopDisabledWatch = scope.$parent.$watch(attr.ngDisabled, updateAriaDisabled);
    } else {
      updateAriaDisabled(!!attr.disabled);
    }

    $materialAria.expect(element, 'aria-label');
    element.attr('tabIndex', 0);
    element.attr('role', 'slider');
    element.on('keydown', keydownListener);

    var hammertime = new Hammer(element[0], {
      recognizers: [
        [Hammer.Pan, { direction: Hammer.DIRECTION_HORIZONTAL }]
      ]
    });
    hammertime.on('hammer.input', onInput);
    hammertime.on('panstart', onPanStart);
    hammertime.on('pan', onPan);
    hammertime.on('panend', onPanEnd);

    // On resize, recalculate the slider's dimensions and re-render
    var updateAll = $$rAF.debounce(function() {
      refreshSliderDimensions();
      ngModelRender();
      redrawTicks();
    });
    updateAll();
    angular.element($window).on('resize', updateAll);

    scope.$on('$destroy', function() {
      angular.element($window).off('resize', updateAll);
      hammertime.destroy();
      stopDisabledWatch();
    });

    ngModelCtrl.$render = ngModelRender;
    ngModelCtrl.$viewChangeListeners.push(ngModelRender);
    ngModelCtrl.$formatters.push(minMaxValidator);
    ngModelCtrl.$formatters.push(stepValidator);

    /**
     * Attributes
     */
    var min;
    var max;
    var step;
    function updateMin(value) {
      min = parseFloat(value);
      element.attr('aria-valuemin', value);
    }
    function updateMax(value) {
      max = parseFloat(value);
      element.attr('aria-valuemax', value);
    }
    function updateStep(value) {
      step = parseFloat(value);
      redrawTicks();
    }
    function updateAriaDisabled(isDisabled) {
      element.attr('aria-disabled', !!isDisabled);
    }

    // Draw the ticks with canvas.
    // The alternative to drawing ticks with canvas is to draw one element for each tick,
    // which could quickly become a performance bottleneck.
    var tickCanvas, tickCtx;
    function redrawTicks() {
      if (!angular.isDefined(attr.discrete)) return;

      var numSteps = Math.floor( (max - min) / step );
      if (!tickCanvas) {
        tickCanvas = angular.element('<canvas style="position:absolute;">');
        tickCtx = tickCanvas[0].getContext('2d');
        tickCtx.fillStyle = 'black';
        tickContainer.append(tickCanvas);
      }
      var dimensions = getSliderDimensions();
      tickCanvas[0].width = dimensions.width;
      tickCanvas[0].height = dimensions.height;

      var distance;
      for (var i = 0; i <= numSteps; i++) {
        distance = Math.floor(dimensions.width * (i / numSteps));
        tickCtx.fillRect(distance - 1, 0, 2, dimensions.height);
      }
    }


    /**
     * Refreshing Dimensions
     */
    var sliderDimensions = {};
    var throttledRefreshDimensions = Util.throttle(refreshSliderDimensions, 5000);
    refreshSliderDimensions();
    function refreshSliderDimensions() {
      sliderDimensions = trackContainer[0].getBoundingClientRect();
    }
    function getSliderDimensions() {
      throttledRefreshDimensions();
      return sliderDimensions;
    }

    /**
     * left/right arrow listener
     */
    function keydownListener(ev) {
      var changeAmount;
      if (ev.which === Constant.KEY_CODE.LEFT_ARROW) {
        changeAmount = -step;
      } else if (ev.which === Constant.KEY_CODE.RIGHT_ARROW) {
        changeAmount = step;
      }
      if (changeAmount) {
        if (ev.metaKey || ev.ctrlKey || ev.altKey) {
          changeAmount *= 4;
        }
        ev.preventDefault();
        ev.stopPropagation();
        scope.$evalAsync(function() {
          setModelValue(ngModelCtrl.$viewValue + changeAmount);
        });
      }
    }

    /**
     * ngModel setters and validators
     */
    function setModelValue(value) {
      ngModelCtrl.$setViewValue( minMaxValidator(stepValidator(value)) );
    }
    function ngModelRender() {
      var percent = (ngModelCtrl.$viewValue - min) / (max - min);
      scope.modelValue = ngModelCtrl.$viewValue;
      element.attr('aria-valuenow', ngModelCtrl.$viewValue);
      setSliderPercent(percent);
    }

    function minMaxValidator(value) {
      if (angular.isNumber(value)) {
        return Math.max(min, Math.min(max, value));
      }
    }
    function stepValidator(value) {
      if (angular.isNumber(value)) {
        return Math.round(value / step) * step;
      }
    }

    /**
     * @param percent 0-1
     */
    function setSliderPercent(percent) {
      activeTrack.css('width', (percent * 100) + '%');
      thumbContainer.css(
        $materialEffects.TRANSFORM,
        'translate3d(' + getSliderDimensions().width * percent + 'px,0,0)'
      );
      element.toggleClass('slider-min', percent === 0);
    }


    /**
     * Slide listeners
     */
    var isSliding = false;
    var isDiscrete = angular.isDefined(attr.discrete);

    function onInput(ev) {
      if (!isSliding && ev.eventType === Hammer.INPUT_START &&
          !element[0].hasAttribute('disabled')) {

        isSliding = true;

        element.addClass('active');
        element[0].focus();
        refreshSliderDimensions();

        onPan(ev);

        ev.srcEvent.stopPropagation();

      } else if (isSliding && ev.eventType === Hammer.INPUT_END) {

        if ( isDiscrete ) onPanEnd(ev);
        isSliding = false;

        element.removeClass('panning active');
      }
    }
    function onPanStart() {
      if (!isSliding) return;
      element.addClass('panning');
    }
    function onPan(ev) {
      if (!isSliding) return;

      // While panning discrete, update only the
      // visual positioning but not the model value.

      if ( isDiscrete ) adjustThumbPosition( ev.center.x );
      else              doSlide( ev.center.x );

      ev.preventDefault();
      ev.srcEvent.stopPropagation();
    }

    function onPanEnd(ev) {
      if ( isDiscrete ) {
        // Convert exact to closest discrete value.
        // Slide animate the thumb... and then update the model value.

        var exactVal = percentToValue( positionToPercent( ev.center.x ));
        var closestVal = minMaxValidator( stepValidator(exactVal) );

        setSliderPercent( valueToPercent(closestVal));
        $$rAF(function(){
          setModelValue( closestVal );
        });

        ev.preventDefault();
        ev.srcEvent.stopPropagation();
      }
    }

    /**
     * Expose for testing
     */
    this._onInput = onInput;
    this._onPanStart = onPanStart;
    this._onPan = onPan;

    /**
     * Slide the UI by changing the model value
     * @param x
     */
    function doSlide( x ) {
      scope.$evalAsync( function() {
        setModelValue( percentToValue( positionToPercent(x) ));
      });
    }

    /**
     * Slide the UI without changing the model (while dragging/panning)
     * @param x
     */
    function adjustThumbPosition( x ) {
      setSliderPercent( positionToPercent(x) );
    }

    /**
     * Convert horizontal position on slider to percentage value of offset from beginning...
     * @param x
     * @returns {number}
     */
    function positionToPercent( x ) {
      return (x - sliderDimensions.left) / (sliderDimensions.width);
    }

    /**
     * Convert percentage offset on slide to equivalent model value
     * @param percent
     * @returns {*}
     */
    function percentToValue( percent ) {
      return (min + percent * (max - min));
    }

    function valueToPercent( val ) {
      return (val - min)/(max - min);
    }

  };
}

/**
 * @private
 * @ngdoc module
 * @name material.components.switch
 */

angular.module('material.components.switch', [
  'material.components.checkbox',
  'material.components.radioButton'
])

.directive('materialSwitch', [
  'materialCheckboxDirective',
  'materialRadioButtonDirective',
  MaterialSwitch
]);

/**
 * @private
 * @ngdoc directive
 * @module material.components.switch
 * @name materialSwitch
 * @restrict E
 *
 * The switch directive is used very much like the normal [angular checkbox](https://docs.angularjs.org/api/ng/input/input%5Bcheckbox%5D).
 *
 * @param {string} ngModel Assignable angular expression to data-bind to.
 * @param {string=} name Property name of the form under which the control is published.
 * @param {expression=} ngTrueValue The value to which the expression should be set when selected.
 * @param {expression=} ngFalseValue The value to which the expression should be set when not selected.
 * @param {string=} ngChange Angular expression to be executed when input changes due to user interaction with the input element.
 * @param {boolean=} noink Use of attribute indicates use of ripple ink effects.
 * @param {boolean=} disabled Use of attribute indicates the switch is disabled: no ink effects and not selectable
 * @param {string=} ariaLabel Publish the button label used by screen-readers for accessibility. Defaults to the switch's text.
 *
 * @usage
 * <hljs lang="html">
 * <material-switch ng-model="isActive" aria-label="Finished?">
 *   Finished ?
 * </material-switch>
 *
 * <material-switch noink ng-model="hasInk" aria-label="No Ink Effects">
 *   No Ink Effects
 * </material-switch>
 *
 * <material-switch disabled ng-model="isDisabled" aria-label="Disabled">
 *   Disabled
 * </material-switch>
 *
 * </hljs>
 */
function MaterialSwitch(checkboxDirectives, radioButtonDirectives) {
  var checkboxDirective = checkboxDirectives[0];
  var radioButtonDirective = radioButtonDirectives[0];

  return {
    restrict: 'E',
    transclude: true,
    template:
      '<div class="material-switch-bar"></div>' +
      '<div class="material-switch-thumb">' +
        radioButtonDirective.template +
      '</div>',
    require: '?ngModel',
    compile: compile
  };

  function compile(element, attr) {
    
    var thumb = angular.element(element[0].querySelector('.material-switch-thumb'));
    //Copy down disabled attributes for checkboxDirective to use
    thumb.attr('disabled', attr.disabled);
    thumb.attr('ngDisabled', attr.ngDisabled);

    var link = checkboxDirective.compile(thumb, attr);

    return function (scope, element, attr, ngModelCtrl) {
      var thumb = angular.element(element[0].querySelector('.material-switch-thumb'));
      return link(scope, thumb, attr, ngModelCtrl)
    };
  }
}

/**
 * @ngdoc module
 * @name material.components.subheader
 * @description
 * SubHeader module
 */
angular.module('material.components.subheader', [
  'material.components.sticky'
])
.directive('materialSubheader', [
  '$materialSticky',
  '$compile',
  MaterialSubheaderDirective
]);

/**
 * @ngdoc directive
 * @name materialSubheader
 * @module material.components.subheader
 *
 * @restrict E
 *
 * @description
 * The `<material-subheader>` directive is a subheader for a section
 *
 * @usage
 * <hljs lang="html">
 * <material-subheader>Online Friends</material-subheader>
 * </hljs>
 */

function MaterialSubheaderDirective($materialSticky, $compile) {
  return {
    restrict: 'E',
    replace: true,
    transclude: true,
    template: 
      '<h2 class="material-subheader">' +
        '<span class="material-subheader-content"></span>' +
      '</h2>',
    compile: function(element, attr, transclude) {
      var outerHTML = element[0].outerHTML;
      return function postLink(scope, element, attr) {
        function getContent(el) {
          return angular.element(el[0].querySelector('.material-subheader-content'));
        }

        // Transclude the user-given contents of the subheader
        // the conventional way.
        transclude(scope, function(clone) {
          getContent(element).append(clone);
        });

        // Create another clone, that uses the outer and inner contents
        // of the element, that will be 'stickied' as the user scrolls.
        transclude(scope, function(clone) {
          var stickyClone = $compile(angular.element(outerHTML))(scope);
          getContent(stickyClone).append(clone);
          $materialSticky(scope, element, stickyClone);
        });
      };
    }
  };
}

/**
 * @ngdoc module
 * @name material.components.tabs
 * @description
 *
 * Tabs
 */
angular.module('material.components.tabs', [
  'material.animations',
  'material.components.swipe'
]);


/**
 * Conditionally configure ink bar animations when the
 * tab selection changes. If `nobar` then do not show the
 * bar nor animate.
 */
angular.module('material.components.tabs')

.directive('materialTabsInkBar', [
  '$materialEffects',
  '$window',
  '$$rAF',
  '$timeout',
  MaterialTabInkDirective
]);

function MaterialTabInkDirective($materialEffects, $window, $$rAF, $timeout) {

  return {
    restrict: 'E',
    require: ['^?nobar', '^materialTabs'],
    link: postLink
  };

  function postLink(scope, element, attr, ctrls) {
    var nobar = ctrls[0];
    var tabsCtrl = ctrls[1];

    if (nobar) return;

    var debouncedUpdateBar = $$rAF.debounce(updateBar);

    scope.$watch(tabsCtrl.selected, updateBar);
    scope.$on('$materialTabsChanged', debouncedUpdateBar);
    scope.$on('$materialTabsPaginationChanged', debouncedUpdateBar);
    angular.element($window).on('resize', onWindowResize);

    function onWindowResize() {
      debouncedUpdateBar();
      $timeout(debouncedUpdateBar, 100, false);
    }

    scope.$on('$destroy', function() {
      angular.element($window).off('resize', onWindowResize);
    });

    function updateBar() {
      var selectedElement = tabsCtrl.selected() && tabsCtrl.selected().element;

      if (!selectedElement || tabsCtrl.count() < 2) {
        element.css({
          display : 'none',
          width : '0px'
        });
      } else {
        var width = selectedElement.prop('offsetWidth');
        var left = selectedElement.prop('offsetLeft') + (tabsCtrl.$$pagingOffset || 0);

        element.css({
          display : width > 0 ? 'block' : 'none',
          width: width + 'px'
        });
        element.css($materialEffects.TRANSFORM, 'translate3d(' + left + 'px,0,0)');
      }
    }

  }

}


angular.module('material.components.tabs')

.directive('materialTabsPagination', [
  '$materialEffects',
  '$window',
  '$$rAF',
  '$$q',
  '$timeout',
  TabPaginationDirective
]);

function TabPaginationDirective($materialEffects, $window, $$rAF, $$q, $timeout) {

  // TODO allow configuration of TAB_MIN_WIDTH
  // Must match tab min-width rule in _tabs.scss
  var TAB_MIN_WIDTH = 8 * 12; 
  // Must match (2 * width of paginators) in scss
  var PAGINATORS_WIDTH = (8 * 4) * 2;

  return {
    restrict: 'A',
    require: '^materialTabs',
    link: postLink
  };

  function postLink(scope, element, attr, tabsCtrl) {

    var tabsParent = element.children();
    var state = scope.pagination = {
      page: -1,
      active: false,
      clickNext: function() { userChangePage(+1); },
      clickPrevious: function() { userChangePage(-1); }
    };

    var debouncedUpdatePagination = $$rAF.debounce(updatePagination);

    scope.$on('$materialTabsChanged', debouncedUpdatePagination);
    angular.element($window).on('resize', debouncedUpdatePagination);

    // Listen to focus events bubbling up from material-tab elements
    tabsParent.on('focusin', onTabsFocusIn);

    scope.$on('$destroy', function() {
      angular.element($window).off('resize', debouncedUpdatePagination);
      tabsParent.off('focusin', onTabsFocusIn);
    });

    scope.$watch(tabsCtrl.selected, onSelectedTabChange);

    // Allows pagination through focus change.
    function onTabsFocusIn(ev) {
      if (!state.active) return;

      var tab = angular.element(ev.target).controller('materialTab');
      var pageIndex = getPageForTab(tab);
      if (pageIndex !== state.page) {
        // If the focused element is on a new page, don't focus yet.
        tab.element.blur();
        // Go to the new page, wait for the page transition to end, then focus.
        setPage(pageIndex).then(function() {
          tab.element.focus();
        });
      }
    }

    function onSelectedTabChange(selectedTab) {
      if (!selectedTab) return;

      if (state.active) {
        var selectedTabPage = getPageForTab(selectedTab);
        setPage(selectedTabPage);
      } else {
        debouncedUpdatePagination();
      }
    }

    // Called when page is changed by a user action (click)
    function userChangePage(increment) {
      var newPage = state.page + increment;
      var newTab;
      if (!tabsCtrl.selected() || getPageForTab(tabsCtrl.selected()) !== newPage) {
        var startIndex;
        if (increment < 0) {
          // If going backward, select the previous available tab, starting from
          // the first item on the page after newPage.
          startIndex = (newPage + 1) * state.itemsPerPage;
          newTab = tabsCtrl.previous( tabsCtrl.itemAt(startIndex) );
        } else {
          // If going forward, select the next available tab, starting with the
          // last item before newPage.
          startIndex = (newPage * state.itemsPerPage) - 1;
          newTab = tabsCtrl.next( tabsCtrl.itemAt(startIndex) );
        }
      }
      setPage(newPage).then(function() {
        newTab && newTab.element.focus();
      });
      newTab && tabsCtrl.select(newTab);
    }

    function updatePagination() {
      var tabs = element.find('material-tab');
      var tabsWidth = element.parent().prop('clientWidth') - PAGINATORS_WIDTH;

      var needPagination = tabsWidth && TAB_MIN_WIDTH * tabsCtrl.count() > tabsWidth;
      var paginationToggled = needPagination !== state.active;

      state.active = needPagination;

      if (needPagination) {

        state.pagesCount = Math.ceil((TAB_MIN_WIDTH * tabsCtrl.count()) / tabsWidth);
        state.itemsPerPage = Math.max(1, Math.floor(tabsCtrl.count() / state.pagesCount));
        state.tabWidth = tabsWidth / state.itemsPerPage;
        
        tabsParent.css('width', state.tabWidth * tabsCtrl.count() + 'px');
        tabs.css('width', state.tabWidth + 'px');

        var selectedTabPage = getPageForTab(tabsCtrl.selected());
        setPage(selectedTabPage);

      } else {

        if (paginationToggled) {
          $timeout(function() {
            tabsParent.css('width', '');
            tabs.css('width', '');
            slideTabButtons(0);
            state.page = -1;
          });
        }

      }
    }

    function slideTabButtons(x) {
      if (tabsCtrl.pagingOffset === x) {
        // Resolve instantly if no change
        return $$q.when();
      }

      var deferred = $$q.defer();

      tabsCtrl.$$pagingOffset = x;
      tabsParent.css($materialEffects.TRANSFORM, 'translate3d(' + x + 'px,0,0)');
      tabsParent.on($materialEffects.TRANSITIONEND_EVENT, onTabsParentTransitionEnd);

      return deferred.promise;

      function onTabsParentTransitionEnd(ev) {
        // Make sure this event didn't bubble up from an animation in a child element.
        if (ev.target === tabsParent[0]) {
          tabsParent.off($materialEffects.TRANSITIONEND_EVENT, onTabsParentTransitionEnd);
          deferred.resolve();
        }
      }
    }

    function getPageForTab(tab) {
      var tabIndex = tabsCtrl.indexOf(tab);
      if (tabIndex === -1) return 0;

      return Math.floor(tabIndex / state.itemsPerPage);
    }

    function setPage(page) {
      if (page === state.page) return;

      var lastPage = state.pagesCount;

      if (page < 0) page = 0;
      if (page > lastPage) page = lastPage;

      state.hasPrev = page > 0;
      state.hasNext = ((page + 1) * state.itemsPerPage) < tabsCtrl.count();

      state.page = page;

      $timeout(function() {
        scope.$broadcast('$materialTabsPaginationChanged');
      });

      return slideTabButtons(-page * state.itemsPerPage * state.tabWidth);
    }
  }

}


angular.module('material.components.tabs')

.controller('$materialTab', [
  '$scope',
  '$element',
  '$compile',
  '$animate',
  '$materialSwipe',
  TabItemController
]);

function TabItemController(scope, element, $compile, $animate, $materialSwipe) {
  var self = this;

  var detachSwipe = angular.noop;
  var attachSwipe = function() { return detachSwipe };
  var eventTypes = "swipeleft swiperight" ;
  var configureSwipe = $materialSwipe( scope, eventTypes );

  // special callback assigned by TabsController
  self.$$onSwipe = angular.noop;

  // Properties
  self.contentContainer = angular.element('<div class="tab-content ng-hide">');
  self.element = element;

  // Methods
  self.isDisabled = isDisabled;
  self.onAdd = onAdd;
  self.onRemove = onRemove;
  self.onSelect = onSelect;
  self.onDeselect = onDeselect;


  function isDisabled() {
    return element[0].hasAttribute('disabled');
  }
  
  /**
   * Add the tab's content to the DOM container area in the tabs,
   * @param contentArea the contentArea to add the content of the tab to
   */
  function onAdd(contentArea) {
    if (self.content.length) {

      self.contentContainer.append(self.content);
      self.contentScope = scope.$parent.$new();
      contentArea.append(self.contentContainer);

      $compile(self.contentContainer)(self.contentScope);

      Util.disconnectScope(self.contentScope);

      // For internal tab views we only use the `$materialSwipe`
      // so we can easily attach()/detach() when the tab view is active/inactive

      attachSwipe = configureSwipe( self.contentContainer, function(ev) {
        self.$$onSwipe(ev.type);
      }, true );
    }
  }


  /**
   * Usually called when a Tab is programmatically removed; such
   * as in an ng-repeat
   */
  function onRemove() {
    $animate.leave(self.contentContainer).then(function()
    {
      self.contentScope && self.contentScope.$destroy();
      self.contentScope = null;
    });
  }

  function onSelect() {
    // Resume watchers and events firing when tab is selected
    Util.reconnectScope(self.contentScope);
    detachSwipe = attachSwipe();

    element.addClass('active');
    element.attr('aria-selected', true);
    element.attr('tabIndex', 0);
    $animate.removeClass(self.contentContainer, 'ng-hide');

    scope.onSelect();
  }

  function onDeselect() {
    // Stop watchers & events from firing while tab is deselected
    Util.disconnectScope(self.contentScope);
    detachSwipe();

    element.removeClass('active');
    element.attr('aria-selected', false);
    // Only allow tabbing to the active tab
    element.attr('tabIndex', -1);
    $animate.addClass(self.contentContainer, 'ng-hide');

    scope.onDeselect();
  }

}


angular.module('material.components.tabs')

.directive('materialTab', [
  '$materialInkRipple', 
  '$compile',
  '$materialAria',
  MaterialTabDirective
]);

/**
 * @ngdoc directive
 * @name materialTab
 * @module material.components.tabs
 * @order 1
 *
 * @restrict E
 *
 * @description
 * `<material-tab>` is the nested directive used [within `<material-tabs>`] to specify each tab with a **label** and optional *view content*.
 *
 * If the `label` attribute is not specified, then an optional `<material-tab-label>` tag can be used to specified more
 * complex tab header markup. If neither the **label** nor the **material-tab-label** are specified, then the nested
 * markup of the `<material-tab>` is used as the tab header markup.
 *
 * If a tab **label** has been identified, then any **non-**`<material-tab-label>` markup
 * will be considered tab content and will be transcluded to the internal `<div class="tabs-content">` container.
 *
 * This container is used by the TabsController to show/hide the active tab's content view. This synchronization is
 * automatically managed by the internal TabsController whenever the tab selection changes. Selection changes can
 * be initiated via data binding changes, programmatic invocation, or user gestures.
 *
 * @param {string=} label Optional attribute to specify a simple string as the tab label
 * @param {boolean=} active When evaluteing to true, selects the tab.
 * @param {boolean=} disabled If present, disabled tab selection.
 * @param {expression=} deselected Expression to be evaluated after the tab has been de-selected.
 * @param {expression=} selected Expression to be evaluated after the tab has been selected.
 *
 *
 * @usage
 *
 * <hljs lang="html">
 * <material-tab label="" disabled="" selected="" deselected="" >
 *   <h3>My Tab content</h3>
 * </material-tab>
 *
 * <material-tab >
 *   <material-tab-label>
 *     <h3>My Tab content</h3>
 *   </material-tab-label>
 *   <p>
 *     Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium,
 *     totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae
 *     dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit,
 *     sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.
 *   </p>
 * </material-tab>
 * </hljs>
 *
 */
function MaterialTabDirective($materialInkRipple, $compile, $materialAria) {
  return {
    restrict: 'E',
    require: ['materialTab', '^materialTabs'],
    controller: '$materialTab',
    scope: {
      onSelect: '&',
      onDeselect: '&',
      label: '@'
    },
    compile: compile
  };

  function compile(element, attr) {
    var tabLabel = element.find('material-tab-label');

    // If a tab label element is found, remove it for later re-use.
    if (tabLabel.length) {
      tabLabel.remove();
    // Otherwise, try to use attr.label as the label
    } else if (angular.isDefined(attr.label)) {
      tabLabel = angular.element('<material-tab-label>').html(attr.label);
    // If nothing is found, use the tab's content as the label
    } else {
      tabLabel = angular.element('<material-tab-label>')
        .append(element.contents().remove());
    }

    // Everything that's left as a child is the tab's content.
    var tabContent = element.contents().remove();

    return function postLink(scope, element, attr, ctrls) {

      var tabItemCtrl = ctrls[0]; // Controller for THIS tabItemCtrl
      var tabsCtrl = ctrls[1]; // Controller for ALL tabs

      transcludeTabContent();

      var detachRippleFn = $materialInkRipple.attachButtonBehavior(element);
      tabsCtrl.add(tabItemCtrl);
      scope.$on('$destroy', function() {
        detachRippleFn();
        tabsCtrl.remove(tabItemCtrl);
      });

      if (!angular.isDefined(attr.ngClick)) element.on('click', defaultClickListener);
      element.on('keydown', keydownListener);

      if (angular.isNumber(scope.$parent.$index)) watchNgRepeatIndex();
      if (angular.isDefined(attr.active)) watchActiveAttribute();
      watchDisabled();

      configureAria();

      function transcludeTabContent() {
        // Clone the label we found earlier, and $compile and append it
        var label = tabLabel.clone();
        element.append(label);
        $compile(label)(scope.$parent);

        // Clone the content we found earlier, and mark it for later placement into
        // the proper content area.
        tabItemCtrl.content = tabContent.clone();
      }

      //defaultClickListener isn't applied if the user provides an ngClick expression.
      function defaultClickListener() {
        scope.$apply(function() {
          tabsCtrl.select(tabItemCtrl);
          tabItemCtrl.element.focus();
        });
      }
      function keydownListener(ev) {
        if (ev.which == Constant.KEY_CODE.SPACE ) {
          // Fire the click handler to do normal selection if space is pressed
          element.triggerHandler('click');
          ev.preventDefault();

        } else if (ev.which === Constant.KEY_CODE.LEFT_ARROW) {
          var previous = tabsCtrl.previous(tabItemCtrl);
          previous && previous.element.focus();

        } else if (ev.which === Constant.KEY_CODE.RIGHT_ARROW) {
          var next = tabsCtrl.next(tabItemCtrl);
          next && next.element.focus();
        }
      }

      // If tabItemCtrl is part of an ngRepeat, move the tabItemCtrl in our internal array
      // when its $index changes
      function watchNgRepeatIndex() {
        // The tabItemCtrl has an isolate scope, so we watch the $index on the parent.
        scope.$watch('$parent.$index', function $indexWatchAction(newIndex) {
          tabsCtrl.move(tabItemCtrl, newIndex);
        });
      }

      function watchActiveAttribute() {
        var unwatch = scope.$parent.$watch('!!(' + attr.active + ')', activeWatchAction);
        scope.$on('$destroy', unwatch);
        
        function activeWatchAction(isActive) {
          var isSelected = tabsCtrl.selected() === tabItemCtrl;

          if (isActive && !isSelected) {
            tabsCtrl.select(tabItemCtrl);
          } else if (!isActive && isSelected) {
            tabsCtrl.deselect(tabItemCtrl);
          }
        }
      }

      function watchDisabled() {
        scope.$watch(tabItemCtrl.isDisabled, disabledWatchAction);
        
        function disabledWatchAction(isDisabled) {
          element.attr('aria-disabled', isDisabled);

          // Auto select `next` tab when disabled
          var isSelected = (tabsCtrl.selected() === tabItemCtrl);
          if (isSelected && isDisabled) {
            tabsCtrl.select(tabsCtrl.next() || tabsCtrl.previous());
          }

        }
      }

      function configureAria() {
        // Link together the content area and tabItemCtrl with an id
        var tabId = attr.id || Util.nextUid();
        var tabContentId = 'content_' + tabId;
        element.attr({
          id: tabId,
          role: 'tabItemCtrl',
          tabIndex: '-1', //this is also set on select/deselect in tabItemCtrl
          'aria-controls': tabContentId
        });
        tabItemCtrl.contentContainer.attr({
          id: tabContentId,
          role: 'tabpanel',
          'aria-labelledby': tabId
        });

        $materialAria.expect(element, 'aria-label', element.text());
      }

    };

  }

}


angular.module('material.components.tabs')

.controller('$materialTabs', [
  '$scope', 
  '$element',
  MaterialTabsController
]);

function MaterialTabsController(scope, element) {

  var tabsList = Util.iterator([], false);
  var self = this;

  // Properties
  self.element = element;
  // The section containing the tab content elements
  self.contentArea = angular.element(element[0].querySelector('.tabs-content'));

  // Methods from iterator
  self.inRange = tabsList.inRange;
  self.indexOf = tabsList.indexOf;
  self.itemAt = tabsList.itemAt;
  self.count = tabsList.count;
  
  self.selected = selected;
  self.add = add;
  self.remove = remove;
  self.move = move;
  self.select = select;
  self.deselect = deselect;

  self.next = next;
  self.previous = previous;

  self.swipe = swipe;

  // Get the selected tab
  function selected() {
    return self.itemAt(scope.selectedIndex);
  }

  // Add a new tab.
  // Returns a method to remove the tab from the list.
  function add(tab, index) {

    tabsList.add(tab, index);
    tab.onAdd(self.contentArea);

    // Register swipe feature
    tab.$$onSwipe = swipe;

    // Select the new tab if we don't have a selectedIndex, or if the
    // selectedIndex we've been waiting for is this tab
    if (scope.selectedIndex === -1 || scope.selectedIndex === self.indexOf(tab)) {
      self.select(tab);
    }
    scope.$broadcast('$materialTabsChanged');
  }

  function remove(tab) {
    if (!tabsList.contains(tab)) return;

    if (self.selected() === tab) {
      if (tabsList.count() > 1) {
        self.select(self.previous() || self.next());
      } else {
        self.deselect(tab);
      }
    }

    tabsList.remove(tab);
    tab.onRemove();

    scope.$broadcast('$materialTabsChanged');
  }

  // Move a tab (used when ng-repeat order changes)
  function move(tab, toIndex) {
    var isSelected = self.selected() === tab;

    tabsList.remove(tab);
    tabsList.add(tab, toIndex);
    if (isSelected) self.select(tab);

    scope.$broadcast('$materialTabsChanged');
  }

  function select(tab) {
    if (!tab || tab.isSelected || tab.isDisabled()) return;
    if (!tabsList.contains(tab)) return;

    self.deselect(self.selected());

    scope.selectedIndex = self.indexOf(tab);
    tab.isSelected = true;
    tab.onSelect();
  }
  function deselect(tab) {
    if (!tab || !tab.isSelected) return;
    if (!tabsList.contains(tab)) return;

    scope.selectedIndex = -1;
    tab.isSelected = false;
    tab.onDeselect();
  }

  function next(tab, filterFn) {
    return tabsList.next(tab || self.selected(), filterFn || isTabEnabled);
  }
  function previous(tab, filterFn) {
    return tabsList.previous(tab || self.selected(), filterFn || isTabEnabled);
  }

  function isTabEnabled(tab) {
    return tab && !tab.isDisabled();
  }

  /*
   * attach a swipe listen
   * if it's not selected, abort
   * check the direction
   *   if it is right
   *   it pan right
   *     Now select
   */

  function swipe(direction) {
    if ( !self.selected() ) return;

    // check the direction
    switch(direction) {

      case "swiperight":  // if it is right
      case "panright"  :  // it pan right
        // Now do this...
        self.select( self.previous() );
        break;

      case "swipeleft":
      case "panleft"  :
        self.select( self.next() );
        break;
    }

  }

}

angular.module('material.components.tabs')

/**
 * @ngdoc directive
 * @name materialTabs
 * @module material.components.tabs
 * @order 0
 *
 * @restrict E
 *
 * @description
 * The `<material-tabs>` directive serves as the container for 1..n `<material-tab>` child directives to produces a Tabs components.
 * In turn, the nested `<material-tab>` directive is used to specify a tab label for the **header button** and a [optional] tab view
 * content that will be associated with each tab button.
 *
 * Below is the markup for its simplest usage:
 *
 *  <hljs lang="html">
 *  <material-tabs>
 *    <material-tab label="Tab #1"></material-tab>
 *    <material-tab label="Tab #2"></material-tab>
 *    <material-tab label="Tab #3"></material-tab>
 *  <material-tabs>
 *  </hljs>
 *
 * Tabs supports three (3) usage scenarios:
 *
 *  1. Tabs (buttons only)
 *  2. Tabs with internal view content
 *  3. Tabs with external view content
 *
 * **Tab-only** support is useful when tab buttons are used for custom navigation regardless of any other components, content, or views.
 * **Tabs with internal views** are the traditional usages where each tab has associated view content and the view switching is managed internally by the Tabs component.
 * **Tabs with external view content** is often useful when content associated with each tab is independently managed and data-binding notifications announce tab selection changes.
 *
 * > As a performance bonus, if the tab content is managed internally then the non-active (non-visible) tab contents are temporarily disconnected from the `$scope.$digest()` processes; which restricts and optimizes DOM updates to only the currently active tab.
 *
 * Additional features also include:
 *
 * *  Content can include any markup.
 * *  If a tab is disabled while active/selected, then the next tab will be auto-selected.
 * *  If the currently active tab is the last tab, then next() action will select the first tab.
 * *  Any markup (other than **`<material-tab>`** tags) will be transcluded into the tab header area BEFORE the tab buttons.
 *
 * @param {integer=} selected Index of the active/selected tab
 * @param {boolean=} noink If present, disables ink ripple effects.
 * @param {boolean=} nobar If present, disables the selection ink bar.
 * @param {string=}  align-tabs Attribute to indicate position of tab buttons: bottom or top; default is `top`
 *
 * @usage
 * <hljs lang="html">
 * <material-tabs selected="selectedIndex" >
 *   <img ng-src="/img/angular.png" class="centered">
 *
 *   <material-tab
 *      ng-repeat="tab in tabs | orderBy:predicate:reversed"
 *      on-select="onTabSelected(tab)"
 *      on-deselect="announceDeselected(tab)"
 *      disabled="tab.disabled" >
 *
 *       <material-tab-label>
 *           {{tab.title}}
 *           <img src="/img/removeTab.png"
 *                ng-click="removeTab(tab)"
 *                class="delete" >
 *       </material-tab-label>
 *
 *       {{tab.content}}
 *
 *   </material-tab>
 *
 * </material-tabs>
 * </hljs>
 *
 */
.directive('materialTabs', [
  '$parse',
  TabsDirective
]);

function TabsDirective($parse) {
  return {
    restrict: 'E',
    controller: '$materialTabs',
    require: 'materialTabs',
    transclude: true,
    scope: {
      selectedIndex: '=?selected'
    },
    template: 
      '<section class="tabs-header" ' +
        'ng-class="{\'tab-paginating\': pagination.active}">' +

        '<div class="tab-paginator prev" ' +
          'ng-if="pagination.active && pagination.hasPrev" ' +
          'ng-click="pagination.clickPrevious()">' +
        '</div>' +

        // overflow: hidden container when paginating
        '<div class="tabs-header-items-container" material-tabs-pagination>' +
          // flex container for <material-tab> elements
          '<div class="tabs-header-items" ng-transclude></div>' +
          '<material-tabs-ink-bar></material-tabs-ink-bar>' +
        '</div>' +

        '<div class="tab-paginator next" ' +
          'ng-if="pagination.active && pagination.hasNext" ' +
          'ng-click="pagination.clickNext()">' +
        '</div>' +

      '</section>' +
      '<section class="tabs-content"></section>',
    link: postLink
  };

  function postLink(scope, element, attr, tabsCtrl) {

    configureAria();
    watchSelected();

    function configureAria() {
      element.attr({
        role: 'tablist'
      });
    }

    function watchSelected() {
      scope.$watch('selectedIndex', function watchSelectedIndex(newIndex, oldIndex) {
        // Note: if the user provides an invalid newIndex, all tabs will be deselected
        // and the associated view will be hidden.
        tabsCtrl.deselect( tabsCtrl.itemAt(oldIndex) );

        if (tabsCtrl.inRange(newIndex)) {
          var newTab = tabsCtrl.itemAt(newIndex);

          // If the newTab is disabled, find an enabled one to go to.
          if (newTab && newTab.isDisabled()) {
            newTab = newIndex > oldIndex ?
              tabsCtrl.next(newTab) :
              tabsCtrl.previous(newTab);
          }
          tabsCtrl.select(newTab);

        }
      });
    }

  }
}

/**
 * @ngdoc module
 * @name material.components.toast
 * @description
 * Toast
 */
angular.module('material.components.toast', [
  'material.services.interimElement',
  'material.components.swipe'
])
  .directive('materialToast', [
    MaterialToastDirective
  ])
  .factory('$materialToast', [
    '$timeout',
    '$$interimElement',
    '$animate',
    '$materialSwipe',
    MaterialToastService
  ]);

function MaterialToastDirective() {
  return {
    restrict: 'E'
  };
}

/**
 * @ngdoc service
 * @name $materialToast
 * @module material.components.toast
 *
 * @description
 *
 * Used to open a toast notification on any position on the screen [with an optional
 * duration], `$materialToast` is a service created by `$$interimElement` and provides a
 * simple promise-based, behavior API:
 *
 *  - `$materialToast.show()`
 *  - `$materialToast.hide()`
 *  - `$materialToast.cancel()`
 *
 * #### Notes:
 *
 * Only one toast notification may ever be active at any time. If a new toast is
 * shown while a different toast is active, the old toast will be automatically
 * hidden.
 *
 * @usage
 * <hljs lang="html">
 *  <script type="text/javascript">
 *  var app = angular.module('app', ['ngMaterial']);
 *    app.controller('MyController', function($scope, $materialToast) {
 *      $scope.openToast = function($event) {
 *        $materialToast.show({
 *          template: '<material-toast>Hello!</material-toast>',
 *          hideDelay: 3000
 *        });
 *      };
 *    });
 *  </script>
 *
 *  <div ng-controller="MyController">
 *    <material-button ng-click="openToast()">
 *      Open a Toast!
 *    </material-button>
 *  </div>
 * </hljs>
 */

 /**
 * @ngdoc method
 * @name $materialToast#show
 *
 * @description
 * Show a toast dialog with the specified options.
 *
 * @paramType Options
 * @param {string=} templateUrl The url of an html template file that will
 * be used as the content of the toast. Restrictions: the template must
 * have an outer `material-toast` element.
 * @param {string=} template Same as templateUrl, except this is an actual
 * template string.
 * @param {number=} hideDelay How many milliseconds the toast should stay
 * active before automatically closing.  Set to 0 to disable duration.
 * Default: 3000.
 * @param {string=} position Where to place the toast. Available: any combination
 * of 'bottom', 'left', 'top', 'right', 'fit'. Default: 'bottom left'.
 * @param {string=} controller The controller to associate with this toast.
 * @param {string=} locals An object containing key/value pairs. The keys will
 * be used as names of values to inject into the controller. For example,
 * `locals: {three: 3}` would inject `three` into the controller with the value
 * of 3.
 * @param {object=} resolve Similar to locals, except it takes promises as values
 * and the toast will not open until the promises resolve.
 * @param {string=} controllerAs An alias to assign the controller to on the scope.
 * @param {element=} parent The element to append the bottomSheet to. Defaults to appending
 * to the root element of the application.
 *
 * @returns {Promise} Returns a promise that will be resolved or rejected when
 *  `$materialToast.hide()` or `$materialToast.cancel()` is called respectively.
 */

/**
 * @ngdoc method
 * @name $materialToast#hide
 *
 * @description
 * Hide an existing toast and `resolve` the promise returned from `$materialToast.show()`.
 *
 * @param {*} arg An argument to resolve the promise with.
 *
 */

/**
 * @ngdoc method
 * @name $materialToast#cancel
 *
 * @description
 * Hide an existing toast and `reject` the promise returned from `$materialToast.show()`.
 *
 * @param {*} arg An argument to reject the promise with.
 *
 */

function MaterialToastService($timeout, $$interimElement, $animate, $materialSwipe) {

  var factoryDef = {
    onShow: onShow,
    onRemove: onRemove,
    position: 'bottom left',
    hideDelay: 3000,
  };

  var $materialToast = $$interimElement(factoryDef);
  return $materialToast;

  function onShow(scope, element, options) {
    element.addClass(options.position);
    options.parent.addClass(toastOpenClass(options.position));

    var configureSwipe = $materialSwipe(scope, 'swipeleft swiperight');
    options.detachSwipe = configureSwipe(element, function(ev) {
      //Add swipeleft/swiperight class to element so it can animate correctly
      element.addClass(ev.type);
      $timeout($materialToast.hide);
    });

    return $animate.enter(element, options.parent);
  }

  function onRemove(scope, element, options) {
    options.detachSwipe();
    options.parent.removeClass(toastOpenClass(options.position));
    return $animate.leave(element);
  }

  function toastOpenClass(position) {
    return 'material-toast-open-' +
      (position.indexOf('top') > -1 ? 'top' : 'bottom');
  }
}

/**
 * @ngdoc module
 * @name material.components.toolbar
 */
angular.module('material.components.toolbar', [
  'material.components.content',
  'material.animations'
])
  .directive('materialToolbar', [
    '$$rAF',
    '$materialEffects',
    materialToolbarDirective
  ]);

/**
 * @ngdoc directive
 * @name materialToolbar
 * @restrict E
 * @description
 * `material-toolbar` is used to place a toolbar in your app.
 *
 * Toolbars are usually used above a content area to display the title of the
 * current page, and show relevant action buttons for that page.
 *
 * You can change the height of the toolbar by adding either the
 * `material-medium-tall` or `material-tall` class to the toolbar.
 *
 * @usage
 * <hljs lang="html">
 * <div layout="vertical" layout-fill>
 *   <material-toolbar>
 *
 *     <div class="material-toolbar-tools">
 *       <span>My App's Title</span>
 *
 *       <!-- fill up the space between left and right area -->
 *       <span flex></span>
 *
 *       <material-button>
 *         Right Bar Button
 *       </material-button>
 *     </div>
 *
 *   </material-toolbar>
 *   <material-content>
 *     Hello!
 *   </material-content>
 * </div>
 * </hljs>
 *
 * @param {boolean=} scrollShrink Whether the header should shrink away as 
 * the user scrolls down, and reveal itself as the user scrolls up. 
 * Note: for scrollShrink to work, the toolbar must be a sibling of a 
 * `material-content` element, placed before it. See the scroll shrink demo.
 *
 *
 * @param {number=} shrinkSpeedFactor How much to change the speed of the toolbar's
 * shrinking by. For example, if 0.25 is given then the toolbar will shrink
 * at one fourth the rate at which the user scrolls down. Default 0.5.
 */ 
function materialToolbarDirective($$rAF, $materialEffects) {

  return {
    restrict: 'E',
    controller: angular.noop,
    link: function(scope, element, attr) {

      if (angular.isDefined(attr.scrollShrink)) {
        setupScrollShrink();
      }

      function setupScrollShrink() {
        // Current "y" position of scroll
        var y = 0;
        // Store the last scroll top position
        var prevScrollTop = 0;

        var shrinkSpeedFactor = attr.shrinkSpeedFactor || 0.5;

        var toolbarHeight;
        var contentElement;

        var debouncedContentScroll = $$rAF.debounce(onContentScroll);
        var debouncedUpdateHeight = Util.debounce(updateToolbarHeight, 5 * 1000);

        // Wait for $materialContentLoaded event from materialContent directive.
        // If the materialContent element is a sibling of our toolbar, hook it up
        // to scroll events.
        scope.$on('$materialContentLoaded', onMaterialContentLoad);

        function onMaterialContentLoad($event, newContentEl) {
          if (Util.elementIsSibling(element, newContentEl)) {
            // unhook old content event listener if exists
            if (contentElement) {
              contentElement.off('scroll', debouncedContentScroll);
            }

            newContentEl.on('scroll', debouncedContentScroll);
            newContentEl.attr('scroll-shrink', 'true');

            contentElement = newContentEl;
            $$rAF(updateToolbarHeight);
          }
        }

        function updateToolbarHeight() {
          toolbarHeight = element.prop('offsetHeight');
          // Add a negative margin-top the size of the toolbar to the content el.
          // The content will start transformed down the toolbarHeight amount,
          // so everything looks normal.
          //
          // As the user scrolls down, the content will be transformed up slowly
          // to put the content underneath where the toolbar was.
          contentElement.css(
            'margin-top', 
            (-toolbarHeight * shrinkSpeedFactor) + 'px'
          );
          onContentScroll();
        }

        function onContentScroll(e) {
          var scrollTop = e ? e.target.scrollTop : prevScrollTop;

          debouncedUpdateHeight();

          y = Math.min(
            toolbarHeight / shrinkSpeedFactor, 
            Math.max(0, y + scrollTop - prevScrollTop)
          );

          element.css(
            $materialEffects.TRANSFORM, 
            'translate3d(0,' + (-y * shrinkSpeedFactor) + 'px,0)'
          );
          contentElement.css(
            $materialEffects.TRANSFORM, 
            'translate3d(0,' + ((toolbarHeight - y) * shrinkSpeedFactor) + 'px,0)'
          );

          prevScrollTop = scrollTop;
        }

      }

    }
  };

}

/**
 * @ngdoc module
 * @name material.components.tooltip
 */
angular.module('material.components.tooltip', [])

.directive('materialTooltip', [
  '$timeout',
  '$window',
  '$$rAF',
  '$document',
  MaterialTooltipDirective
]);

/**
 * @ngdoc directive
 * @name materialTooltip
 * @module material.components.tooltip
 * @description
 * Tooltips are used to describe elements that are interactive and primarily graphical (not textual).
 *
 * Place a `<material-tooltip>` as a child of the element it describes.
 *
 * A tooltip will activate when the user focuses, hovers over, or touches the parent.
 *
 * @usage
 * <hljs lang="html">
 * <material-icon icon="/img/icons/ic_play_arrow_24px.svg">
 *   <material-tooltip>
 *     Play Music
 *   </material-tooltip>
 * </material-icon>
 * </hljs>
 *
 * @param {expression=} visible Boolean bound to whether the tooltip is 
 * currently visible.
 */
function MaterialTooltipDirective($timeout, $window, $$rAF, $document) {

  var TOOLTIP_SHOW_DELAY = 400;
  var TOOLTIP_WINDOW_EDGE_SPACE = 8;
  // We have to append tooltips to the body, because we use
  // getBoundingClientRect().
  // to find where to append the tooltip.
  var tooltipParent = angular.element(document.body);

  return {
    restrict: 'E',
    transclude: true,
    require: '^?materialContent',
    template: 
      '<div class="tooltip-background"></div>' +
      '<div class="tooltip-content" ng-transclude></div>',
    scope: {
      visible: '=?'
    },
    link: postLink
  };

  function postLink(scope, element, attr, contentCtrl) {
    var parent = element.parent();

    // We will re-attach tooltip when visible
    element.detach();
    element.attr('role', 'tooltip');
    element.attr('id', attr.id || ('tooltip_' + Util.nextUid()));

    parent.on('focus mouseenter touchstart', function() {
      setVisible(true);
    });
    parent.on('blur mouseleave touchend touchcancel', function() {
      // Don't hide the tooltip if the parent is still focused.
      if (document.activeElement === parent[0]) return;
      setVisible(false);
    });

    scope.$watch('visible', function(isVisible) {
      if (isVisible) showTooltip();
      else hideTooltip();
    });
    
    var debouncedOnResize = $$rAF.debounce(onWindowResize);
    angular.element($window).on('resize', debouncedOnResize);
    function onWindowResize() {
      // Reposition on resize
      if (scope.visible) positionTooltip();
    }

    // Be sure to completely cleanup the element on destroy
    scope.$on('$destroy', function() {
      scope.visible = false;
      element.remove();
      angular.element($window).off('resize', debouncedOnResize);
    });

    // *******
    // Methods
    // *******

    // If setting visible to true, debounce to TOOLTIP_SHOW_DELAY ms
    // If setting visible to false and no timeout is active, instantly hide the tooltip.
    function setVisible(value) {
      setVisible.value = !!value;

      if (!setVisible.queued) {
        if (value) {
          setVisible.queued = true;
          $timeout(function() {
            scope.visible = setVisible.value;
            setVisible.queued = false;
          }, TOOLTIP_SHOW_DELAY);

        } else {
          $timeout(function() { scope.visible = false; });
        }
      }
    }

    function showTooltip() {
      // Insert the element before positioning it, so we can get position
      // (tooltip is hidden by default)
      element.removeClass('tooltip-hide');
      parent.attr('aria-describedby', element.attr('id'));
      tooltipParent.append(element);

      // Wait until the element has been in the dom for two frames before 
      // fading it in.
      // Additionally, we position the tooltip twice to avoid positioning bugs
      //positionTooltip();
      $$rAF(function() {

        $$rAF(function() {
          positionTooltip();
          if (!scope.visible) return;
          element.addClass('tooltip-show');
        });

      });
    }

    function hideTooltip() {
      element.removeClass('tooltip-show').addClass('tooltip-hide');
      parent.removeAttr('aria-describedby');
      $timeout(function() {
        if (scope.visible) return;
        element.detach();
      }, 200, false);
    }

    function positionTooltip(rerun) {
      var tipRect = element[0].getBoundingClientRect();
      var parentRect = parent[0].getBoundingClientRect();

      if (contentCtrl) {
        parentRect.top += contentCtrl.$element.prop('scrollTop');
        parentRect.left += contentCtrl.$element.prop('scrollLeft');
      }

      // Default to bottom position if possible
      var tipDirection = 'bottom';
      var newPosition = {
        left: parentRect.left + parentRect.width / 2 - tipRect.width / 2,
        top: parentRect.top + parentRect.height
      };

      // If element bleeds over left/right of the window, place it on the edge of the window.
      newPosition.left = Math.min(
        newPosition.left, 
        $window.innerWidth - tipRect.width - TOOLTIP_WINDOW_EDGE_SPACE
      );
      newPosition.left = Math.max(newPosition.left, TOOLTIP_WINDOW_EDGE_SPACE);

      // If element bleeds over the bottom of the window, place it above the parent.
      if (newPosition.top + tipRect.height > $window.innerHeight) {
        newPosition.top = parentRect.top - tipRect.height;
        tipDirection = 'top';
      }

      element.css({top: newPosition.top + 'px', left: newPosition.left + 'px'});
      // Tell the CSS the size of this tooltip, as a multiple of 32.
      element.attr('width-32', Math.ceil(tipRect.width / 32));
      element.attr('tooltip-direction', tipDirection);
    }

  }

}

angular.module('material.components.whiteframe', []);

/**
 * @ngdoc module
 * @name material.components.divider
 * @description Divider module!
 */
angular.module('material.components.divider', [
  'material.animations',
  'material.services.aria'
])
  .directive('materialDivider', MaterialDividerDirective);

function MaterialDividerController(){}

/**
 * @ngdoc directive
 * @name materialDivider
 * @module material.components.divider
 * @restrict E
 *
 * @description
 * Dividers group and separate content within lists and page layouts using strong visual and spatial distinctions. This divider is a thin rule, lightweight enough to not distract the user from content.
 *
 * @param {boolean=} inset Add this attribute to activate the inset divider style.
 * @usage
 * <hljs lang="html">
 * <material-divider></material-divider>
 *
 * <material-divider inset></material-divider>
 * </hljs>
 *
 */
function MaterialDividerDirective() {
  return {
    restrict: 'E',
    controller: [MaterialDividerController]
  };
}

/**
 * @ngdoc module
 * @name material.components.linearProgress
 * @description Linear Progress module!
 */
angular.module('material.components.linearProgress', [
  'material.animations',
  'material.services.aria'
])
.directive('materialLinearProgress', [
  '$$rAF', 
  '$materialEffects',
  MaterialLinearProgressDirective
]);

/**
 * @ngdoc directive
 * @name materialLinearProgress
 * @module material.components.linearProgress
 * @restrict E
 *
 * @description
 * The linear progress directive is used to make loading content in your app as delightful and painless as possible by minimizing the amount of visual change a user sees before they can view and interact with content. Each operation should only be represented by one activity indicator—for example, one refresh operation should not display both a refresh bar and an activity circle.
 *
 * For operations where the percentage of the operation completed can be determined, use a determinate indicator. They give users a quick sense of how long an operation will take.
 *
 * For operations where the user is asked to wait a moment while something finishes up, and it’s not necessary to expose what's happening behind the scenes and how long it will take, use an indeterminate indicator.
 *
 * @param {string} mode Select from one of four modes: determinate, indeterminate, buffer or query.
 * @param {number=} value In determinate and buffer modes, this number represents the percentage of the primary progress bar. Default: 0
 * @param {number=} secondaryValue In the buffer mode, this number represents the precentage of the secondary progress bar. Default: 0
 *
 * @usage
 * <hljs lang="html">
 * <material-linear-progress mode="determinate" value="..."></material-linear-progress>
 *
 * <material-linear-progress mode="determinate" ng-value="..."></material-linear-progress>
 *
 * <material-linear-progress mode="indeterminate"></material-linear-progress>
 *
 * <material-linear-progress mode="buffer" value="..." secondaryValue="..."></material-linear-progress>
 *
 * <material-linear-progress mode="query"></material-linear-progress>
 * </hljs>
 */
function MaterialLinearProgressDirective($$rAF, $materialEffects) {

  return {
    restrict: 'E',
    template: '<div class="container">' +
      '<div class="dashed"></div>' +
      '<div class="bar bar1"></div>' +
      '<div class="bar bar2"></div>' +
      '</div>',
    compile: compile
  };
  
  function compile(tElement, tAttrs, transclude) {
    tElement.attr('aria-valuemin', 0);
    tElement.attr('aria-valuemax', 100);
    tElement.attr('role', 'progressbar');

    return postLink;
  }
  function postLink(scope, element, attr) {
    var bar1Style = element[0].querySelector('.bar1').style,
      bar2Style = element[0].querySelector('.bar2').style,
      container = angular.element(element[0].querySelector('.container'));

    attr.$observe('value', function(value) {
      if (attr.mode == 'query') {
        return;
      }

      var clamped = clamp(value);
      element.attr('aria-valuenow', clamped);
      bar2Style[$materialEffects.TRANSFORM] = linearProgressTransforms[clamped];
    });

    attr.$observe('secondaryvalue', function(value) {
      bar1Style[$materialEffects.TRANSFORM] = linearProgressTransforms[clamp(value)];
    });

    $$rAF(function() {
      container.addClass('ready');
    });
  }

  function clamp(value) {
    if (value > 100) {
      return 100;
    }

    if (value < 0) {
      return 0;
    }

    return Math.ceil(value || 0);
  }
}


// **********************************************************
// Private Methods
// **********************************************************
var linearProgressTransforms = (function() {
  var values = new Array(101);
  for(var i = 0; i < 101; i++){
    values[i] = makeTransform(i);
  }

  return values;

  function makeTransform(value){
    var scale = value/100;
    var translateX = (value-100)/2;
    return 'translateX(' + translateX.toString() + '%) scale(' + scale.toString() + ', 1)';
  }
})();

/**
 * @ngdoc module
 * @name material.components.circularProgress
 * @description Circular Progress module!
 */
angular.module('material.components.circularProgress', [
  'material.animations',
  'material.services.aria'
])
  .directive('materialCircularProgress', [
    '$$rAF',
    '$materialEffects',
    MaterialCircularProgressDirective
  ]);

/**
 * @ngdoc directive
 * @name materialCircularProgress
 * @module material.components.circularProgress
 * @restrict E
 *
* @description
 * The circular progress directive is used to make loading content in your app as delightful and painless as possible by minimizing the amount of visual change a user sees before they can view and interact with content.
 *
 * For operations where the percentage of the operation completed can be determined, use a determinate indicator. They give users a quick sense of how long an operation will take.
 *
 * For operations where the user is asked to wait a moment while something finishes up, and it’s not necessary to expose what's happening behind the scenes and how long it will take, use an indeterminate indicator.
 *
 * @param {string} mode Select from one of two modes: determinate and indeterminate.
 * @param {number=} value In determinate mode, this number represents the percentage of the circular progress. Default: 0
 * @param {number=} diameter This specifies the diamter of the circular progress. Default: 48
 *
 * @usage
 * <hljs lang="html">
 * <material-circular-progress mode="determinate" value="..."></material-circular-progress>
 *
 * <material-circular-progress mode="determinate" ng-value="..."></material-circular-progress>
 *
 * <material-circular-progress mode="determinate" value="..." diameter="100"></material-circular-progress>
 *
 * <material-circular-progress mode="indeterminate"></material-circular-progress>
 * </hljs>
 */
function MaterialCircularProgressDirective($$rAF, $materialEffects) {
  var fillRotations = new Array(101),
    fixRotations = new Array(101);

  for (var i = 0; i < 101; i++) {
    var percent = i / 100;
    var rotation = Math.floor(percent * 180);

    fillRotations[i] = 'rotate(' + rotation.toString() + 'deg)';
    fixRotations[i] = 'rotate(' + (rotation * 2).toString() + 'deg)';
  }

  return {
    restrict: 'E',
    template: 
      '<div class="wrapper1"><div class="wrapper2"><div class="circle">' +
        '<div class="mask full">' +
          '<div class="fill"></div>' +
        '</div>' +
        '<div class="mask half">' +
          '<div class="fill"></div>' +
          '<div class="fill fix"></div>' +
        '</div>' +
        '<div class="shadow"></div>' +
      '</div>' +
      '<div class="inset"></div></div></div>',
    compile: compile
  };

  function compile(tElement, tAttrs, transclude) {
    tElement.attr('aria-valuemin', 0);
    tElement.attr('aria-valuemax', 100);
    tElement.attr('role', 'progressbar');

    return postLink;
  }

  function postLink(scope, element, attr) {
    var circle = element[0],
      fill = circle.querySelectorAll('.fill, .mask.full'),
      fix = circle.querySelectorAll('.fill.fix'),
      i, clamped, fillRotation, fixRotation;

    var diameter = attr.diameter || 48;
    var scale = diameter/48;

    circle.style[$materialEffects.TRANSFORM] = 'scale(' + scale.toString() + ')';

    attr.$observe('value', function(value) {
      clamped = clamp(value);
      fillRotation = fillRotations[clamped];
      fixRotation = fixRotations[clamped];

      element.attr('aria-valuenow', clamped);

      for (i = 0; i < fill.length; i++) {
        fill[i].style[$materialEffects.TRANSFORM] = fillRotation;
      }

      for (i = 0; i < fix.length; i++) {
        fix[i].style[$materialEffects.TRANSFORM] = fixRotation;
      }
    });
  }

  function clamp(value) {
    if (value > 100) {
      return 100;
    }

    if (value < 0) {
      return 0;
    }

    return Math.ceil(value || 0);
  }
}
(function() {

  /**
   * @ngdoc module
   * @name material.components.swipe
   * @description Swipe module!
   */
  angular.module('material.components.swipe',['ng'])

    /**
     * @ngdoc directive
     * @module material.components.swipe
     * @name $materialSwipe
     *
     *  This service allows directives to easily attach swipe and pan listeners to
     *  the specified element.
     *
     * @private
     */
    .factory("$materialSwipe", function() {

      // match expected API functionality
      var attachNoop = function(){ return angular.noop; };

      /**
       * SwipeService constructor pre-captures scope and customized event types
       *
       * @param scope
       * @param eventTypes
       * @returns {*}
       * @constructor
       */
      return function SwipeService(scope, eventTypes) {
        if ( !eventTypes ) eventTypes = "swipeleft swiperight";

        // publish configureFor() method for specific element instance
        return function configureFor(element, onSwipeCallback, attachLater ) {
          var hammertime = new Hammer(element[0], {
            recognizers : addRecognizers([], eventTypes )
          });

          // Attach swipe listeners now
          if ( !attachLater ) attachSwipe();

          // auto-disconnect during destroy
          scope.$on('$destroy', function() {
            hammertime.destroy();
          });

          return attachSwipe;

          // **********************
          // Internal methods
          // **********************

          /**
           * Delegate swipe event to callback function
           * and ensure $digest is triggered.
           *
           * @param ev HammerEvent
           */
          function swipeHandler(ev) {

            // Prevent triggering parent hammer listeners
            ev.srcEvent.stopPropagation();

            if ( angular.isFunction(onSwipeCallback) ) {
              scope.$apply(function() {
                onSwipeCallback(ev);
              });
            }
          }

          /**
           * Enable listeners and return detach() fn
           */
          function attachSwipe() {
            hammertime.on(eventTypes, swipeHandler );

            return function detachSwipe() {
              hammertime.off( eventTypes );
            };
          }

          /**
           * Add optional recognizers such as panleft, panright
           */
          function addRecognizers(list, events) {
            var hasPanning = (events.indexOf("pan") > -1);
            var hasSwipe   = (events.indexOf("swipe") > -1);

            if (hasPanning) {
              list.push([ Hammer.Pan, { direction: Hammer.DIRECTION_HORIZONTAL } ]);
            }
            if (hasSwipe) {
              list.push([ Hammer.Swipe, { direction: Hammer.DIRECTION_HORIZONTAL } ]);
            }

            return list;
          }

        };
      };
    })

    /**
     * @ngdoc directive
     * @module material.components.swipe
     * @name materialSwipeLeft
     *
     * @order 0
     * @restrict A
     *
     * @description
     * The `<div  material-swipe-left="<expression" >` directive identifies an element on which
     * HammerJS horizontal swipe left and pan left support will be active. The swipe/pan action
     * can result in custom activity trigger by evaluating `<expression>`.
     *
     * @param {boolean=} noPan Use of attribute indicates flag to disable detection of `panleft` activity
     *
     * @usage
     * <hljs lang="html">
     *
     * <div class="animate-switch-container"
     *      ng-switch on="data.selectedIndex"
     *      material-swipe-left="data.selectedIndex+=1;"
     *      material-swipe-right="data.selectedIndex-=1;" >
     *
     * </div>
     * </hljs>
     *
     */
    .directive("materialSwipeLeft", ['$parse', '$materialSwipe',
      function MaterialSwipeLeft($parse, $materialSwipe) {
        return {
          restrict: 'A',
          link :  swipePostLink( $parse, $materialSwipe, "SwipeLeft" )
        };
      }])

    /**
     * @ngdoc directive
     * @module material.components.swipe
     * @name materialSwipeRight
     *
     * @order 1
     * @restrict A
     *
     * @description
     * The `<div  material-swipe-right="<expression" >` directive identifies functionality
     * that attaches HammerJS horizontal swipe right and pan right support to an element. The swipe/pan action
     * can result in activity trigger by evaluating `<expression>`
     *
     * @param {boolean=} noPan Use of attribute indicates flag to disable detection of `panright` activity
     *
     * @usage
     * <hljs lang="html">
     *
     * <div class="animate-switch-container"
     *      ng-switch on="data.selectedIndex"
     *      material-swipe-left="data.selectedIndex+=1;"
     *      material-swipe-right="data.selectedIndex-=1;" >
     *
     * </div>
     * </hljs>
     *
     */
    .directive( "materialSwipeRight", ['$parse', '$materialSwipe',
      function MaterialSwipeRight($parse, $materialSwipe) {
        return {
          restrict: 'A',
          link: swipePostLink( $parse, $materialSwipe, "SwipeRight" )
        };
      }
    ]);

    /**
     * Factory to build PostLink function specific to Swipe or Pan direction
     *
     * @param $parse
     * @param $materialSwipe
     * @param name
     * @returns {Function}
     */
    function swipePostLink($parse, $materialSwipe, name ) {

      return function(scope, element, attrs) {
        var direction = name.toLowerCase();
        var directiveName= "material" + name;

        var parentGetter = $parse(attrs[directiveName]) || angular.noop;
        var configureSwipe = $materialSwipe(scope, direction);
        var requestSwipe = function(locals) {
          // build function to request scope-specific swipe response
          parentGetter(scope, locals);
        };

        configureSwipe( element, function onHandleSwipe(ev) {
          if ( ev.type == direction ) {
            requestSwipe();
          }
        });

      }
    }

})();




angular.module('material.decorators', [])
.config(['$provide', function($provide) {
  $provide.decorator('$$rAF', ['$delegate', '$rootScope', rAFDecorator]);

  function rAFDecorator($$rAF, $rootScope) {

    /**
     * Use this to debounce events that come in often.
     * The debounced function will always use the *last* invocation before the
     * coming frame.
     *
     * For example, window resize events that fire many times a second:
     * If we set to use an raf-debounced callback on window resize, then
     * our callback will only be fired once per frame, with the last resize
     * event that happened before that frame.
     *
     * @param {function} callback function to debounce
     */
    $$rAF.debounce = function(cb) {
      var queueArgs, alreadyQueued, queueCb, context;
      return function debounced() {
        queueArgs = arguments;
        context = this;
        queueCb = cb;
        if (!alreadyQueued) {
          alreadyQueued = true;
          $$rAF(function() {
            queueCb.apply(context, queueArgs);
            alreadyQueued = false;
          });
        }
      };
    };

    return $$rAF;
  }
}]);

angular.module('material.services.aria', [])

.service('$materialAria', [
  '$log',
  AriaService
]);

function AriaService($log) {
  var messageTemplate = 'ARIA: Attribute "%s", required for accessibility, is missing on "%s"!';
  var defaultValueTemplate = 'Default value was set: %s="%s".';

  return {
    expect : expectAttribute,
  };

  /**
   * Check if expected ARIA has been specified on the target element
   * @param element
   * @param attrName
   * @param defaultValue
   */
  function expectAttribute(element, attrName, defaultValue) {

    var node = element[0];
    if (!node.hasAttribute(attrName)) {
      var hasDefault = angular.isDefined(defaultValue);

      if (hasDefault) {
        defaultValue = String(defaultValue).trim();
        // $log.warn(messageTemplate + ' ' + defaultValueTemplate,
        //           attrName, getTagString(node), attrName, defaultValue);
        element.attr(attrName, defaultValue);
      } else {
        // $log.warn(messageTemplate, attrName, getTagString(node));
      }
    }
  }


  /**
   * Gets the tag definition from a node's outerHTML
   * @example getTagString(
   *   '<material-button foo="bar">Hello</material-button>'
   * ) // => '<material-button foo="bar">'
   */
  function getTagString(node) {
    var html = node.outerHTML;
    var closingIndex = html.indexOf('>');
    return html.substring(0, closingIndex + 1);
  }
}

angular.module('material.services.attrBind', [
])
  .factory('$attrBind', [
    '$parse', 
    '$interpolate', 
    MaterialAttrBind 
  ]);

/**
 *  This service allows directives to easily databind attributes to private scope properties.
 *
 * @private
 */
function MaterialAttrBind($parse, $interpolate) {
  var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/;

  return function (scope, attrs, bindDefinition, bindDefaults) {
    angular.forEach(bindDefinition || {}, function (definition, scopeName) {
      //Adapted from angular.js $compile
      var match = definition.match(LOCAL_REGEXP) || [],
        attrName = match[3] || scopeName,
        mode = match[1], // @, =, or &
        parentGet,
        unWatchFn;

      switch (mode) {
        case '@':   // One-way binding from attribute into scope

          attrs.$observe(attrName, function (value) {
            scope[scopeName] = value;
          });
          attrs.$$observers[attrName].$$scope = scope;

          if (!bypassWithDefaults(attrName, scopeName)) {
            // we trigger an interpolation to ensure
            // the value is there for use immediately
            scope[scopeName] = $interpolate(attrs[attrName])(scope);
          }
          break;

        case '=':   // Two-way binding...

          if (!bypassWithDefaults(attrName, scopeName)) {
            // Immediate evaluation
            scope[scopeName] = (attrs[attrName] === "") ? true : scope.$eval(attrs[attrName]);

            // Data-bind attribute to scope (incoming) and
            // auto-release watcher when scope is destroyed

            unWatchFn = scope.$watch(attrs[attrName], function (value) {
              scope[scopeName] = value;
            });
            scope.$on('$destroy', unWatchFn);
          }

          break;

        case '&':   // execute an attribute-defined expression in the context of the parent scope

          if (!bypassWithDefaults(attrName, scopeName, angular.noop)) {
            /* jshint -W044 */
            if (attrs[attrName] && attrs[attrName].match(RegExp(scopeName + '\(.*?\)'))) {
              throw new Error('& expression binding "' + scopeName + '" looks like it will recursively call "' +
                attrs[attrName] + '" and cause a stack overflow! Please choose a different scopeName.');
            }

            parentGet = $parse(attrs[attrName]);
            scope[scopeName] = function (locals) {
              return parentGet(scope, locals);
            };
          }

          break;
      }
    });

    /**
     * Optional fallback value if attribute is not specified on element
     * @param scopeName
     */
    function bypassWithDefaults(attrName, scopeName, defaultVal) {
      if (!angular.isDefined(attrs[attrName])) {
        var hasDefault = bindDefaults && bindDefaults.hasOwnProperty(scopeName);
        scope[scopeName] = hasDefault ? bindDefaults[scopeName] : defaultVal;
        return true;
      }
      return false;
    }

  };
}

angular.module('material.services.compiler', [
])
  .service('$materialCompiler', [
    '$q',
    '$http',
    '$injector',
    '$compile',
    '$controller',
    '$templateCache',
    materialCompilerService
  ]);

function materialCompilerService($q, $http, $injector, $compile, $controller, $templateCache) {

  /**
   * @ngdoc service
   * @name $materialCompiler
   * @module material.services.compiler
   *
   * @description
   * The $materialCompiler service is an abstraction of angular's compiler, that allows the developer
   * to easily compile an element with a templateUrl, controller, and locals.
   */

   /**
    * @ngdoc method
    * @name $materialCompiler#compile
    * @param {object} options An options object, with the following properties:
    *
    *    - `controller` – `{(string=|function()=}` – Controller fn that should be associated with
    *      newly created scope or the name of a {@link angular.Module#controller registered
    *      controller} if passed as a string.
    *    - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be
    *      published to scope under the `controllerAs` name.
    *    - `template` – `{string=}` – html template as a string or a function that
    *      returns an html template as a string which should be used by {@link
    *      ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
    *      This property takes precedence over `templateUrl`.
    *
    *    - `templateUrl` – `{string=}` – path or function that returns a path to an html
    *      template that should be used by {@link ngRoute.directive:ngView ngView}.
    *
    *    - `transformTemplate` – `{function=} – a function which can be used to transform
    *      the templateUrl or template provided after it is fetched.  It will be given one
    *      parameter, the template, and should return a transformed template.
    *
    *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
    *      be injected into the controller. If any of these dependencies are promises, the compiler
    *      will wait for them all to be resolved or one to be rejected before the controller is
    *      instantiated.
    *
    *      - `key` – `{string}`: a name of a dependency to be injected into the controller.
    *      - `factory` - `{string|function}`: If `string` then it is an alias for a service.
    *        Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}
    *        and the return value is treated as the dependency. If the result is a promise, it is
    *        resolved before its value is injected into the controller.
    *
    * @returns {object=} promise A promsie which will be resolved with a `compileData` object,
    * with the following properties:
    *
    *   - `{element}` – `element` – an uncompiled angular element compiled using the provided template.
    *   
    *   - `{function(scope)}`  – `link` – A link function, which, when called, will compile
    *     the elmeent and instantiate options.controller.
    *
    *   - `{object}` – `locals` – The locals which will be passed into the controller once `link` is
    *     called.
    *
    * @usage
    * $materialCompiler.compile({
    *   templateUrl: 'modal.html',
    *   controller: 'ModalCtrl',
    *   locals: {
    *     modal: myModalInstance;
    *   }
    * }).then(function(compileData) {
    *   compileData.element; // modal.html's template in an element
    *   compileData.link(myScope); //attach controller & scope to element
    * });
    */
  this.compile = function(options) {
    var templateUrl = options.templateUrl;
    var template = options.template || '';
    var controller = options.controller;
    var controllerAs = options.controllerAs;
    var resolve = options.resolve || {};
    var locals = options.locals || {};
    var transformTemplate = options.transformTemplate || angular.identity;

    // Take resolve values and invoke them.  
    // Resolves can either be a string (value: 'MyRegisteredAngularConst'),
    // or an invokable 'factory' of sorts: (value: function ValueGetter($dependency) {})
    angular.forEach(resolve, function(value, key) {
      if (angular.isString(value)) {
        resolve[key] = $injector.get(value);
      } else {
        resolve[key] = $injector.invoke(value);
      }
    });
    //Add the locals, which are just straight values to inject
    //eg locals: { three: 3 }, will inject three into the controller
    angular.extend(resolve, locals);

    if (templateUrl) {
      resolve.$template = $http.get(templateUrl, {cache: $templateCache})
        .then(function(response) {
          return response.data;
        });
    } else {
      resolve.$template = $q.when(template);
    }

    // Wait for all the resolves to finish if they are promises
    return $q.all(resolve).then(function(locals) {

      var template = transformTemplate(locals.$template);
      var element = angular.element('<div>').html(template).contents();
      var linkFn = $compile(element);

      //Return a linking function that can be used later when the element is ready
      return {
        locals: locals,
        element: element,
        link: function link(scope) {
          locals.$scope = scope;

          //Instantiate controller if it exists, because we have scope
          if (controller) {
            var ctrl = $controller(controller, locals);
            //See angular-route source for this logic
            element.data('$ngControllerController', ctrl);
            element.children().data('$ngControllerController', ctrl);

            if (controllerAs) {
              scope[controllerAs] = ctrl;
            }
          }

          return linkFn(scope);
        }
      };
    });
  };
}

/**
 * @ngdoc module
 * @name material.services.interimElement
 * @description InterimElement
 */

angular.module('material.services.interimElement', [
  'material.services.compiler'
])
.factory('$$interimElement', [
  '$q',
  '$rootScope',
  '$timeout',
  '$rootElement',
  '$animate',
  '$materialCompiler',
  InterimElementFactory
]);

/**
 * @ngdoc service
 * @name $$interimElement
 *
 * @description
 *
 * Factory that contructs `$$interimElement.$service` services. 
 * Used internally in material for elements that appear on screen temporarily.
 * The service provides a promise-like API for interacting with the temporary
 * elements.
 *
 * ```js
 * app.service('$materialToast', function($$interimElement) {
 *   var $materialToast = $$interimElement(toastDefaultOptions);
 *   return $materialToast;
 * });
 * ```
 * @param {object=} defaultOptions Options used by default for the `show` method on the service.
 *
 * @returns {$$interimElement.$service}
 *
 */

function InterimElementFactory($q, $rootScope, $timeout, $rootElement, $animate, $materialCompiler) {

  return function createInterimElementService(defaults) {

    /**
     * @ngdoc service
     * @name $$interimElement.$service
     *
     * @description
     * A service used to control inserting and removing an element into the DOM.
     *
     */


    var stack = [];

    var parent = $rootElement.find('body');
    if (!parent.length) parent = $rootElement;

    defaults = angular.extend({
      parent: parent,
      onShow: function(scope, $el, options) {
        return $animate.enter($el, options.parent);
      },
      onRemove: function(scope, $el, options) {
        return $animate.leave($el);
      },
    }, defaults || {});

    var service;
    return service = {
      show: show,
      hide: hide,
      cancel: cancel
    };

    /**
     * @ngdoc method
     * @name $$interimElement.$service#show
     * @kind function
     *
     * @description
     * Compiles and inserts an element into the DOM.
     *
     * @param {Object} options Options object to compile with.
     *
     * @returns {Promise} Promise that will resolve when the service
     * has `#close()` or `#cancel()` called.
     *
     */
    function show(options) {
      if (stack.length) {
        service.hide();
      }

      var interimElement = new InterimElement(options);
      stack.push(interimElement);
      return interimElement.show().then(function() {
        return interimElement.deferred.promise;
      });
    }

    /**
     * @ngdoc method
     * @name $$interimElement.$service#hide
     * @kind function
     *
     * @description
     * Removes the `$interimElement` from the DOM and resolves the promise returned from `show`
     *
     * @param {*} resolveParam Data to resolve the promise with
     *
     * @returns undefined data that resolves after the element has been removed.
     *
     */
    function hide(success) {
      var interimElement = stack.shift();
      interimElement && interimElement.remove().then(function() {
        interimElement.deferred.resolve(success);
      });
    }

    /**
     * @ngdoc method
     * @name $$interimElement.$service#cancel
     * @kind function
     *
     * @description
     * Removes the `$interimElement` from the DOM and rejects the promise returned from `show`
     *
     * @param {*} reason Data to reject the promise with
     *
     * @returns undefined
     *
     */
    function cancel(reason) {
      var interimElement = stack.shift();
      interimElement && interimElement.remove().then(function() {
        interimElement.deferred.reject(reason);
      });
    }


    /*
     * Internal Interim Element Object
     * Used internally to manage the DOM element and related data
     */
    function InterimElement(options) {
      var self;
      var hideTimeout, element;

      options = options || {};

      options = angular.extend({
        scope: options.scope || $rootScope.$new(options.isolateScope)
      }, defaults, options);

      self = {
        options: options,
        deferred: $q.defer(),
        show: function() {
          return $materialCompiler.compile(options).then(function(compiledData) {
            element = compiledData.link(options.scope);
            var ret = options.onShow(options.scope, element, options);
            return $q.when(ret)
              .then(startHideTimeout);

            function startHideTimeout() {
              if (options.hideDelay) {
                hideTimeout = $timeout(service.hide, options.hideDelay) ;
              }
            }
          });
        },
        cancelTimeout: function() {
          if (hideTimeout) {
            $timeout.cancel(hideTimeout);
            hideTimeout = undefined;
          }
        },
        remove: function() {
          self.cancelTimeout();
          var ret = options.onRemove(options.scope, element, options);
          return $q.when(ret).then(function() {
            options.scope.$destroy();
          });
        }
      };
      return self;
    }
  };
}


/**
 * @ngdoc overview
 * @name material.services.registry
 *
 * @description
 * A component registry system for accessing various component instances in an app.
 */
angular.module('material.services.registry', [
])
  .factory('$materialComponentRegistry', [
    '$log', 
    materialComponentRegistry 
  ]);

/**
 * @ngdoc service
 * @name material.services.registry.service:$materialComponentRegistry
 *
 * @description
 * $materialComponentRegistry enables the user to interact with multiple instances of
 * certain complex components in a running app.
 */
function materialComponentRegistry($log) {
  var instances = [];

  return {
    /**
     * Used to print an error when an instance for a handle isn't found.
     */
    notFoundError: function(handle) {
      $log.error('No instance found for handle', handle);
    },
    /**
     * Return all registered instances as an array.
     */
    getInstances: function() {
      return instances;
    },

    /**
     * Get a registered instance.
     * @param handle the String handle to look up for a registered instance.
     */
    get: function(handle) {
      var i, j, instance;
      for(i = 0, j = instances.length; i < j; i++) {
        instance = instances[i];
        if(instance.$$materialHandle === handle) {
          return instance;
        }
      }
      return null;
    },

    /**
     * Register an instance.
     * @param instance the instance to register
     * @param handle the handle to identify the instance under.
     */
    register: function(instance, handle) {
      instance.$$materialHandle = handle;
      instances.push(instance);

      return function deregister() {
        var index = instances.indexOf(instance);
        if (index !== -1) {
          instances.splice(index, 1);
        }
      };
    }
  }
}


})();
/*!
 * Angular Material Design
 * https://github.com/angular/material
 * @license MIT
 * v0.4.0
 */
@font-face {
  font-family: 'RobotoDraft';
  font-style: normal;
  font-weight: 100;
  src: local('RobotoDraft Thin'), local('RobotoDraft-Thin'), url(//fonts.gstatic.com/s/robotodraft/v1/hope9NW9iJ5hh8P5PM_EAyeJLMOzE6CCkidNEpZOseY.woff) format('woff'); }

@font-face {
  font-family: 'RobotoDraft';
  font-style: normal;
  font-weight: 300;
  src: local('RobotoDraft Light'), local('RobotoDraft-Light'), url(//fonts.gstatic.com/s/robotodraft/v1/u0_CMoUf3y3-4Ss4ci-VwR_xHqYgAV9Bl_ZQbYUxnQU.woff) format('woff'); }

@font-face {
  font-family: 'RobotoDraft';
  font-style: normal;
  font-weight: 400;
  src: local('RobotoDraft'), local('RobotoDraft-Regular'), url(//fonts.gstatic.com/s/robotodraft/v1/0xES5Sl_v6oyT7dAKuoni4bN6UDyHWBl620a-IRfuBk.woff) format('woff'); }

@font-face {
  font-family: 'RobotoDraft';
  font-style: normal;
  font-weight: 500;
  src: local('RobotoDraft Medium'), local('RobotoDraft-Medium'), url(//fonts.gstatic.com/s/robotodraft/v1/u0_CMoUf3y3-4Ss4ci-VwSqHEX2q--o2so14pIEl08w.woff) format('woff'); }

@font-face {
  font-family: 'RobotoDraft';
  font-style: normal;
  font-weight: 700;
  src: local('RobotoDraft Bold'), local('RobotoDraft-Bold'), url(//fonts.gstatic.com/s/robotodraft/v1/u0_CMoUf3y3-4Ss4ci-VwTqR_3kx9_hJXbbyU8S6IN0.woff) format('woff'); }

@font-face {
  font-family: 'RobotoDraft';
  font-style: normal;
  font-weight: 900;
  src: local('RobotoDraft Black'), local('RobotoDraft-Black'), url(//fonts.gstatic.com/s/robotodraft/v1/u0_CMoUf3y3-4Ss4ci-VwUExzZ44ka2Lr5i-x5aWr0E.woff) format('woff'); }

@font-face {
  font-family: 'RobotoDraft';
  font-style: italic;
  font-weight: 400;
  src: local('RobotoDraft Italic'), local('RobotoDraft-Italic'), url(//fonts.gstatic.com/s/robotodraft/v1/er-TIW55l9KWsTS1x9bTftkZXW4sYc4BjuAIFc1SXII.woff) format('woff'); }

@font-face {
  font-family: 'RobotoDraft';
  font-style: italic;
  font-weight: 700;
  src: local('RobotoDraft Bold Italic'), local('RobotoDraft-BoldItalic'), url(//fonts.gstatic.com/s/robotodraft/v1/5SAvdU0uYYlH8OURAykt5wRV2F9RPTaqyJ4QibDfkzM.woff) format('woff'); }

/*
@mixin material-theme($name, $t100, $t300, $t500, $t700, $t900) {
}

@include material-theme('google-red', #f3c6C2, #e57b72, #da4336, #c43828, #a42613);
@include material-theme('pink', #f7bacf, #ef6191, #e81d62, #c1175a, #870d4e);
@include material-theme('indigo', #c4c9e8, #7885ca, #3e50b4, #2f3e9e, #19227d);
@include material-theme('google-blue', #c5d9fb, #7aa9f6, #4184f3, #3266d5, #1b39ab);
@include material-theme('light-blue', #b2e4fb, #4ec2f6, #02a8f3, #0187d0, #00569A);
@include material-theme('teal', #b1deda, #4cb5ab, #009587, #00786a, #004c3f);
@include material-theme('google-green', #b6e0cc, #56ba89, #0E9C57, #0a7f42, #045423);
@include material-theme('yellow', #fff8c3, #fff075, #ffea3a, #fabf2c, #f47e16);
@include material-theme('google-yellow', #fbe7b1, #f6ca4c, #f3b300, #ef9200, #e96000);
@include material-theme('orange', #ffdfb1, #ffb64c, #ff9700, #f47b00, #e55000);
@include material-theme('deep-orange', #ffcbbb, #ff8964, #ff5621, #e54918, #be350b);
@include material-theme('grey', #f0f0f0, #e0e0e0, #a2a2a2, #636363, #252525);
*/
.material-theme-dark {
  background-color: #3f51b5 !important;
  color: #f1f1f1 !important; }

.material-theme-light {
  background-color: #4285f4 !important;
  color: #f1f1f1 !important; }

.material-theme-light-blue {
  background-color: #03a9f4 !important;
  color: #f1f1f1 !important; }

.material-theme-indigo {
  background-color: #3e50b4 !important;
  color: #f1f1f1 !important; }

.material-theme-green {
  background-color: #0f9d58 !important;
  color: #f1f1f1 !important; }

.material-theme-yellow {
  background-color: #ffeb3b !important;
  color: #111111 !important; }

.material-theme-orange {
  background-color: #ff5722 !important;
  color: #f1f1f1 !important; }

.material-theme-purple {
  background-color: #9c27b0 !important;
  color: #f1f1f1 !important; }

.material-theme-red {
  background-color: #db4437 !important;
  color: #f1f1f1 !important; }

.material-input-group-theme-light.material-input-has-value input, .material-input-group-theme-light.material-input-focused input {
  border-color: #4285f4; }
.material-input-group-theme-light.material-input-has-value label, .material-input-group-theme-light.material-input-focused label {
  color: #4285f4; }

.material-input-group-theme-light-blue.material-input-has-value input, .material-input-group-theme-light-blue.material-input-focused input {
  border-color: #03a9f4; }
.material-input-group-theme-light-blue.material-input-has-value label, .material-input-group-theme-light-blue.material-input-focused label {
  color: #03a9f4; }

.material-input-group-theme-dark.material-input-has-value input, .material-input-group-theme-dark.material-input-focused input {
  border-color: #3f51b5; }
.material-input-group-theme-dark.material-input-has-value label, .material-input-group-theme-dark.material-input-focused label {
  color: #3f51b5; }

.material-input-group-theme-green.material-input-has-value input, .material-input-group-theme-green.material-input-focused input {
  border-color: #0f9d58; }
.material-input-group-theme-green.material-input-has-value label, .material-input-group-theme-green.material-input-focused label {
  color: #0f9d58; }

.material-input-group-theme-yellow.material-input-has-value input, .material-input-group-theme-yellow.material-input-focused input {
  border-color: #ffeb3b; }
.material-input-group-theme-yellow.material-input-has-value label, .material-input-group-theme-yellow.material-input-focused label {
  color: #ffeb3b; }

.material-input-group-theme-orange.material-input-has-value input, .material-input-group-theme-orange.material-input-focused input {
  border-color: #ff5722; }
.material-input-group-theme-orange.material-input-has-value label, .material-input-group-theme-orange.material-input-focused label {
  color: #ff5722; }

.material-input-group-theme-purple.material-input-has-value input, .material-input-group-theme-purple.material-input-focused input {
  border-color: #9c27b0; }
.material-input-group-theme-purple.material-input-has-value label, .material-input-group-theme-purple.material-input-focused label {
  color: #9c27b0; }

.material-input-group-theme-red.material-input-has-value input, .material-input-group-theme-red.material-input-focused input {
  border-color: #db4437; }
.material-input-group-theme-red.material-input-has-value label, .material-input-group-theme-red.material-input-focused label {
  color: #db4437; }

.material-shadow {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  border-radius: inherit;
  pointer-events: none; }

.material-shadow-bottom-z-1, material-button.material-button-raised:not([disabled]), material-button.material-button-fab {
  box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26); }

.material-shadow-bottom-z-2, material-button:not([disabled]).material-button-raised.focus, material-button:not([disabled]).material-button-raised:hover, material-button:not([disabled]).material-button-fab.focus, material-button:not([disabled]).material-button-fab:hover {
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.4); }

.material-shadow-animated.material-shadow {
  transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1); }

*, *:before, *:after {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box; }

html, body {
  height: 100%;
  color: #444;
  background: #fff;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  -webkit-touch-callout: none;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility; }
  html h3, body h3 {
    display: block;
    -webkit-margin-before: 1em;
    -webkit-margin-after: 1em;
    -webkit-margin-start: 0px;
    -webkit-margin-end: 0px;
    font-size: 1.17em;
    font-weight: bold; }

button, select, html, textarea, input {
  font-family: 'RobotoDraft', 'Helvetica Neue', Helvetica, Arial; }

body {
  margin: 0;
  padding: 0;
  outline: none; }

.inset {
  padding: 10px; }

button {
  font-family: 'RobotoDraft', 'Helvetica Neue', Helvetica, Arial; }

a {
  background: transparent;
  outline: none; }

h1 {
  font-size: 2em;
  margin: 0.67em 0; }

h2 {
  font-size: 1.5em;
  margin: 0.83em 0; }

h3 {
  font-size: 1.17em;
  margin: 1em 0; }

h4 {
  font-size: 1em;
  margin: 1.33em 0; }

h5 {
  font-size: 0.83em;
  margin: 1.67em 0; }

h6 {
  font-size: 0.75em;
  margin: 2.33em 0; }

select, button, textarea, input {
  margin: 0;
  font-size: 100%;
  font-family: inherit;
  vertical-align: baseline; }

input[type="reset"], input[type="submit"], html input[type="button"], button {
  cursor: pointer;
  -webkit-appearance: button; }
  input[type="reset"][disabled], input[type="submit"][disabled], html input[type="button"][disabled], button[disabled] {
    cursor: default; }

textarea {
  vertical-align: top;
  overflow: auto; }

input[type="radio"], input[type="checkbox"] {
  padding: 0;
  box-sizing: border-box; }
input[type="search"] {
  -webkit-appearance: textfield;
  box-sizing: content-box;
  -webkit-box-sizing: content-box; }
  input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button {
    -webkit-appearance: none; }

table {
  margin-bottom: 20px;
  max-width: 100%;
  width: 100%;
  border-spacing: 0;
  border-collapse: collapse;
  background-color: transparent; }

td, th {
  padding: 8px 16px;
  border-top: 1px solid #ddd;
  vertical-align: top; }

th {
  border-bottom: 2px solid #ddd;
  vertical-align: bottom; }

[layout] {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -moz-flex;
  display: -ms-flexbox;
  display: flex; }

[layout=vertical] {
  -webkit-box-direction: normal;
  -webkit-box-orient: vertical;
  -webkit-flex-direction: column;
  -moz-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column; }

[layout-padding], [layout][layout-padding] > [flex] {
  padding: 8px; }

[layout-padding] + [layout-padding] {
  margin-top: -8px;
  padding-top: 0; }

[layout-fill] {
  margin: 0;
  height: 100%;
  width: 100%; }

[layout-align="center"], [layout-align="center center"], [layout-align="center start"], [layout-align="center end"] {
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  -webkit-justify-content: center;
  -moz-justify-content: center;
  justify-content: center; }

[layout-align="end"], [layout-align="end center"], [layout-align="end start"], [layout-align="end end"] {
  -webkit-box-pack: end;
  -ms-flex-pack: end;
  -webkit-justify-content: flex-end;
  -moz-justify-content: flex-end;
  justify-content: flex-end; }

[layout-align="space-around"], [layout-align="space-around center"], [layout-align="space-around start"], [layout-align="space-around end"] {
  -webkit-box-pack: space-around;
  -ms-flex-pack: space-around;
  -webkit-justify-content: space-around;
  -moz-justify-content: space-around;
  justify-content: space-around; }

[layout-align="space-between"], [layout-align="space-between center"], [layout-align="space-between start"], [layout-align="space-between end"] {
  -webkit-box-pack: justify;
  -ms-flex-pack: justify;
  -webkit-justify-content: space-between;
  -moz-justify-content: space-between;
  justify-content: space-between; }

[layout-align="center center"], [layout-align="start center"], [layout-align="end center"], [layout-align="space-between center"], [layout-align="space-around center"] {
  -webkit-box-align: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  -moz-align-items: center;
  align-items: center; }

[layout-align="center start"], [layout-align="start start"], [layout-align="end start"], [layout-align="space-between start"], [layout-align="space-around start"] {
  -webkit-box-align: start;
  -ms-flex-align: start;
  -webkit-align-items: flex-start;
  -moz-align-items: flex-start;
  align-items: flex-start; }

[layout-align="center end"], [layout-align="start end"], [layout-align="end end"], [layout-align="space-between end"], [layout-align="space-around end"] {
  -webkit-box-align: end;
  -ms-flex-align: end;
  -webkit-align-items: flex-end;
  -moz-align-items: flex-end;
  align-items: flex-end; }

[block] {
  display: block; }

[inline-block] {
  display: inline-block; }

[hide] {
  display: none; }

[show] {
  display: inherit; }

[flex] {
  -webkit-box-flex: 1;
  -webkit-flex: 1;
  -moz-box-flex: 1;
  -moz-flex: 1;
  -ms-flex: 1;
  flex: 1; }

[flex="5"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 5%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 5%;
  -ms-flex: 0 0 5%;
  flex: 0 0 5%;
  max-width: 5%; }

[flex="10"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 10%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 10%;
  -ms-flex: 0 0 10%;
  flex: 0 0 10%;
  max-width: 10%; }

[flex="15"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 15%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 15%;
  -ms-flex: 0 0 15%;
  flex: 0 0 15%;
  max-width: 15%; }

[flex="20"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 20%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 20%;
  -ms-flex: 0 0 20%;
  flex: 0 0 20%;
  max-width: 20%; }

[flex="25"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 25%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 25%;
  -ms-flex: 0 0 25%;
  flex: 0 0 25%;
  max-width: 25%; }

[flex="30"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 30%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 30%;
  -ms-flex: 0 0 30%;
  flex: 0 0 30%;
  max-width: 30%; }

[flex="35"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 35%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 35%;
  -ms-flex: 0 0 35%;
  flex: 0 0 35%;
  max-width: 35%; }

[flex="40"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 40%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 40%;
  -ms-flex: 0 0 40%;
  flex: 0 0 40%;
  max-width: 40%; }

[flex="45"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 45%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 45%;
  -ms-flex: 0 0 45%;
  flex: 0 0 45%;
  max-width: 45%; }

[flex="50"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 50%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 50%;
  -ms-flex: 0 0 50%;
  flex: 0 0 50%;
  max-width: 50%; }

[flex="55"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 55%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 55%;
  -ms-flex: 0 0 55%;
  flex: 0 0 55%;
  max-width: 55%; }

[flex="60"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 60%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 60%;
  -ms-flex: 0 0 60%;
  flex: 0 0 60%;
  max-width: 60%; }

[flex="65"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 65%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 65%;
  -ms-flex: 0 0 65%;
  flex: 0 0 65%;
  max-width: 65%; }

[flex="70"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 70%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 70%;
  -ms-flex: 0 0 70%;
  flex: 0 0 70%;
  max-width: 70%; }

[flex="75"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 75%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 75%;
  -ms-flex: 0 0 75%;
  flex: 0 0 75%;
  max-width: 75%; }

[flex="80"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 80%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 80%;
  -ms-flex: 0 0 80%;
  flex: 0 0 80%;
  max-width: 80%; }

[flex="85"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 85%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 85%;
  -ms-flex: 0 0 85%;
  flex: 0 0 85%;
  max-width: 85%; }

[flex="90"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 90%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 90%;
  -ms-flex: 0 0 90%;
  flex: 0 0 90%;
  max-width: 90%; }

[flex="95"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 95%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 95%;
  -ms-flex: 0 0 95%;
  flex: 0 0 95%;
  max-width: 95%; }

[flex="33"], [flex="34"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 33.33%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 33.33%;
  -ms-flex: 0 0 33.33%;
  flex: 0 0 33.33%;
  max-width: 33.33%; }

[flex="66"], [flex="67"] {
  -webkit-box-flex: 0;
  -webkit-flex: 0 0 66.66%;
  -moz-box-flex: 0;
  -moz-flex: 0 0 66.66%;
  -ms-flex: 0 0 66.66%;
  flex: 0 0 66.66%;
  max-width: 66.66%; }

[offset="5"] {
  margin-left: 5%; }

[offset="10"] {
  margin-left: 10%; }

[offset="15"] {
  margin-left: 15%; }

[offset="20"] {
  margin-left: 20%; }

[offset="25"] {
  margin-left: 25%; }

[offset="30"] {
  margin-left: 30%; }

[offset="35"] {
  margin-left: 35%; }

[offset="40"] {
  margin-left: 40%; }

[offset="45"] {
  margin-left: 45%; }

[offset="50"] {
  margin-left: 50%; }

[offset="55"] {
  margin-left: 55%; }

[offset="60"] {
  margin-left: 60%; }

[offset="65"] {
  margin-left: 65%; }

[offset="70"] {
  margin-left: 70%; }

[offset="75"] {
  margin-left: 75%; }

[offset="80"] {
  margin-left: 80%; }

[offset="85"] {
  margin-left: 85%; }

[offset="90"] {
  margin-left: 90%; }

[offset="95"] {
  margin-left: 95%; }

[offset="33"], [offset="34"] {
  margin-left: 33.33%; }

[offset="66"], [offset="67"] {
  margin-left: 66.66%; }

[layout-order="1"] {
  -webkit-order: 1;
  -ms-flex-order: 1;
  order: 1; }

[layout-order="2"] {
  -webkit-order: 2;
  -ms-flex-order: 2;
  order: 2; }

[layout-order="3"] {
  -webkit-order: 3;
  -ms-flex-order: 3;
  order: 3; }

[layout-order="4"] {
  -webkit-order: 4;
  -ms-flex-order: 4;
  order: 4; }

[layout-order="5"] {
  -webkit-order: 5;
  -ms-flex-order: 5;
  order: 5; }

[layout-order="6"] {
  -webkit-order: 6;
  -ms-flex-order: 6;
  order: 6; }

@media (min-width: 600px) {
  [flex-sm] {
    -webkit-box-flex: 1;
    -webkit-flex: 1;
    -moz-box-flex: 1;
    -moz-flex: 1;
    -ms-flex: 1;
    flex: 1; }
  [flex-sm="5"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 5%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 5%;
    -ms-flex: 0 0 5%;
    flex: 0 0 5%;
    max-width: 5%; }
  [flex-sm="10"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 10%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 10%;
    -ms-flex: 0 0 10%;
    flex: 0 0 10%;
    max-width: 10%; }
  [flex-sm="15"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 15%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 15%;
    -ms-flex: 0 0 15%;
    flex: 0 0 15%;
    max-width: 15%; }
  [flex-sm="20"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 20%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 20%;
    -ms-flex: 0 0 20%;
    flex: 0 0 20%;
    max-width: 20%; }
  [flex-sm="25"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 25%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 25%;
    -ms-flex: 0 0 25%;
    flex: 0 0 25%;
    max-width: 25%; }
  [flex-sm="30"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 30%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 30%;
    -ms-flex: 0 0 30%;
    flex: 0 0 30%;
    max-width: 30%; }
  [flex-sm="35"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 35%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 35%;
    -ms-flex: 0 0 35%;
    flex: 0 0 35%;
    max-width: 35%; }
  [flex-sm="40"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 40%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 40%;
    -ms-flex: 0 0 40%;
    flex: 0 0 40%;
    max-width: 40%; }
  [flex-sm="45"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 45%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 45%;
    -ms-flex: 0 0 45%;
    flex: 0 0 45%;
    max-width: 45%; }
  [flex-sm="50"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 50%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 50%;
    -ms-flex: 0 0 50%;
    flex: 0 0 50%;
    max-width: 50%; }
  [flex-sm="55"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 55%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 55%;
    -ms-flex: 0 0 55%;
    flex: 0 0 55%;
    max-width: 55%; }
  [flex-sm="60"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 60%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 60%;
    -ms-flex: 0 0 60%;
    flex: 0 0 60%;
    max-width: 60%; }
  [flex-sm="65"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 65%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 65%;
    -ms-flex: 0 0 65%;
    flex: 0 0 65%;
    max-width: 65%; }
  [flex-sm="70"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 70%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 70%;
    -ms-flex: 0 0 70%;
    flex: 0 0 70%;
    max-width: 70%; }
  [flex-sm="75"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 75%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 75%;
    -ms-flex: 0 0 75%;
    flex: 0 0 75%;
    max-width: 75%; }
  [flex-sm="80"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 80%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 80%;
    -ms-flex: 0 0 80%;
    flex: 0 0 80%;
    max-width: 80%; }
  [flex-sm="85"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 85%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 85%;
    -ms-flex: 0 0 85%;
    flex: 0 0 85%;
    max-width: 85%; }
  [flex-sm="90"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 90%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 90%;
    -ms-flex: 0 0 90%;
    flex: 0 0 90%;
    max-width: 90%; }
  [flex-sm="95"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 95%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 95%;
    -ms-flex: 0 0 95%;
    flex: 0 0 95%;
    max-width: 95%; }
  [flex-sm="33"], [flex-sm="34"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 33.33%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 33.33%;
    -ms-flex: 0 0 33.33%;
    flex: 0 0 33.33%;
    max-width: 33.33%; }
  [flex-sm="66"], [flex-sm="67"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 66.66%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 66.66%;
    -ms-flex: 0 0 66.66%;
    flex: 0 0 66.66%;
    max-width: 66.66%; }
  [offset-sm="5"] {
    margin-left: 5%; }
  [offset-sm="10"] {
    margin-left: 10%; }
  [offset-sm="15"] {
    margin-left: 15%; }
  [offset-sm="20"] {
    margin-left: 20%; }
  [offset-sm="25"] {
    margin-left: 25%; }
  [offset-sm="30"] {
    margin-left: 30%; }
  [offset-sm="35"] {
    margin-left: 35%; }
  [offset-sm="40"] {
    margin-left: 40%; }
  [offset-sm="45"] {
    margin-left: 45%; }
  [offset-sm="50"] {
    margin-left: 50%; }
  [offset-sm="55"] {
    margin-left: 55%; }
  [offset-sm="60"] {
    margin-left: 60%; }
  [offset-sm="65"] {
    margin-left: 65%; }
  [offset-sm="70"] {
    margin-left: 70%; }
  [offset-sm="75"] {
    margin-left: 75%; }
  [offset-sm="80"] {
    margin-left: 80%; }
  [offset-sm="85"] {
    margin-left: 85%; }
  [offset-sm="90"] {
    margin-left: 90%; }
  [offset-sm="95"] {
    margin-left: 95%; }
  [offset-sm="33"], [offset-sm="34"] {
    margin-left: 33.33%; }
  [offset-sm="66"], [offset-sm="67"] {
    margin-left: 66.66%; }
  [layout-order-sm="1"] {
    -webkit-order: 1;
    -ms-flex-order: 1;
    order: 1; }
  [layout-order-sm="2"] {
    -webkit-order: 2;
    -ms-flex-order: 2;
    order: 2; }
  [layout-order-sm="3"] {
    -webkit-order: 3;
    -ms-flex-order: 3;
    order: 3; }
  [layout-order-sm="4"] {
    -webkit-order: 4;
    -ms-flex-order: 4;
    order: 4; }
  [layout-order-sm="5"] {
    -webkit-order: 5;
    -ms-flex-order: 5;
    order: 5; }
  [layout-order-sm="6"] {
    -webkit-order: 6;
    -ms-flex-order: 6;
    order: 6; }
  [layout-sm] {
    -webkit-box-direction: normal;
    -webkit-box-orient: horizontal;
    -webkit-flex-direction: row;
    -moz-flex-direction: row;
    -ms-flex-direction: row;
    flex-direction: row; }
  [layout-sm=vertical] {
    -webkit-box-direction: normal;
    -webkit-box-orient: vertical;
    -webkit-flex-direction: column;
    -moz-flex-direction: column;
    -ms-flex-direction: column;
    flex-direction: column; }
  [block-sm] {
    display: block; }
  [inline-block-sm] {
    display: inline-block; }
  [show-sm] {
    display: inherit; }
  [hide-sm] {
    display: none; } }

@media (min-width: 960px) {
  [flex-md] {
    -webkit-box-flex: 1;
    -webkit-flex: 1;
    -moz-box-flex: 1;
    -moz-flex: 1;
    -ms-flex: 1;
    flex: 1; }
  [flex-md="5"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 5%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 5%;
    -ms-flex: 0 0 5%;
    flex: 0 0 5%;
    max-width: 5%; }
  [flex-md="10"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 10%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 10%;
    -ms-flex: 0 0 10%;
    flex: 0 0 10%;
    max-width: 10%; }
  [flex-md="15"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 15%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 15%;
    -ms-flex: 0 0 15%;
    flex: 0 0 15%;
    max-width: 15%; }
  [flex-md="20"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 20%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 20%;
    -ms-flex: 0 0 20%;
    flex: 0 0 20%;
    max-width: 20%; }
  [flex-md="25"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 25%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 25%;
    -ms-flex: 0 0 25%;
    flex: 0 0 25%;
    max-width: 25%; }
  [flex-md="30"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 30%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 30%;
    -ms-flex: 0 0 30%;
    flex: 0 0 30%;
    max-width: 30%; }
  [flex-md="35"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 35%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 35%;
    -ms-flex: 0 0 35%;
    flex: 0 0 35%;
    max-width: 35%; }
  [flex-md="40"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 40%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 40%;
    -ms-flex: 0 0 40%;
    flex: 0 0 40%;
    max-width: 40%; }
  [flex-md="45"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 45%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 45%;
    -ms-flex: 0 0 45%;
    flex: 0 0 45%;
    max-width: 45%; }
  [flex-md="50"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 50%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 50%;
    -ms-flex: 0 0 50%;
    flex: 0 0 50%;
    max-width: 50%; }
  [flex-md="55"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 55%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 55%;
    -ms-flex: 0 0 55%;
    flex: 0 0 55%;
    max-width: 55%; }
  [flex-md="60"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 60%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 60%;
    -ms-flex: 0 0 60%;
    flex: 0 0 60%;
    max-width: 60%; }
  [flex-md="65"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 65%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 65%;
    -ms-flex: 0 0 65%;
    flex: 0 0 65%;
    max-width: 65%; }
  [flex-md="70"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 70%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 70%;
    -ms-flex: 0 0 70%;
    flex: 0 0 70%;
    max-width: 70%; }
  [flex-md="75"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 75%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 75%;
    -ms-flex: 0 0 75%;
    flex: 0 0 75%;
    max-width: 75%; }
  [flex-md="80"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 80%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 80%;
    -ms-flex: 0 0 80%;
    flex: 0 0 80%;
    max-width: 80%; }
  [flex-md="85"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 85%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 85%;
    -ms-flex: 0 0 85%;
    flex: 0 0 85%;
    max-width: 85%; }
  [flex-md="90"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 90%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 90%;
    -ms-flex: 0 0 90%;
    flex: 0 0 90%;
    max-width: 90%; }
  [flex-md="95"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 95%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 95%;
    -ms-flex: 0 0 95%;
    flex: 0 0 95%;
    max-width: 95%; }
  [flex-md="33"], [flex-md="34"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 33.33%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 33.33%;
    -ms-flex: 0 0 33.33%;
    flex: 0 0 33.33%;
    max-width: 33.33%; }
  [flex-md="66"], [flex-md="67"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 66.66%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 66.66%;
    -ms-flex: 0 0 66.66%;
    flex: 0 0 66.66%;
    max-width: 66.66%; }
  [offset-md="5"] {
    margin-left: 5%; }
  [offset-md="10"] {
    margin-left: 10%; }
  [offset-md="15"] {
    margin-left: 15%; }
  [offset-md="20"] {
    margin-left: 20%; }
  [offset-md="25"] {
    margin-left: 25%; }
  [offset-md="30"] {
    margin-left: 30%; }
  [offset-md="35"] {
    margin-left: 35%; }
  [offset-md="40"] {
    margin-left: 40%; }
  [offset-md="45"] {
    margin-left: 45%; }
  [offset-md="50"] {
    margin-left: 50%; }
  [offset-md="55"] {
    margin-left: 55%; }
  [offset-md="60"] {
    margin-left: 60%; }
  [offset-md="65"] {
    margin-left: 65%; }
  [offset-md="70"] {
    margin-left: 70%; }
  [offset-md="75"] {
    margin-left: 75%; }
  [offset-md="80"] {
    margin-left: 80%; }
  [offset-md="85"] {
    margin-left: 85%; }
  [offset-md="90"] {
    margin-left: 90%; }
  [offset-md="95"] {
    margin-left: 95%; }
  [offset-md="33"], [offset-md="34"] {
    margin-left: 33.33%; }
  [offset-md="66"], [offset-md="67"] {
    margin-left: 66.66%; }
  [layout-order-md="1"] {
    -webkit-order: 1;
    -ms-flex-order: 1;
    order: 1; }
  [layout-order-md="2"] {
    -webkit-order: 2;
    -ms-flex-order: 2;
    order: 2; }
  [layout-order-md="3"] {
    -webkit-order: 3;
    -ms-flex-order: 3;
    order: 3; }
  [layout-order-md="4"] {
    -webkit-order: 4;
    -ms-flex-order: 4;
    order: 4; }
  [layout-order-md="5"] {
    -webkit-order: 5;
    -ms-flex-order: 5;
    order: 5; }
  [layout-order-md="6"] {
    -webkit-order: 6;
    -ms-flex-order: 6;
    order: 6; }
  [layout-md] {
    -webkit-box-direction: normal;
    -webkit-box-orient: horizontal;
    -webkit-flex-direction: row;
    -moz-flex-direction: row;
    -ms-flex-direction: row;
    flex-direction: row; }
  [layout-md=vertical] {
    -webkit-box-direction: normal;
    -webkit-box-orient: vertical;
    -webkit-flex-direction: column;
    -moz-flex-direction: column;
    -ms-flex-direction: column;
    flex-direction: column; }
  [block-md] {
    display: block; }
  [inline-block-md] {
    display: inline-block; }
  [show-md] {
    display: inherit; }
  [hide-md] {
    display: none; } }

@media (min-width: 1200px) {
  [flex-lg] {
    -webkit-box-flex: 1;
    -webkit-flex: 1;
    -moz-box-flex: 1;
    -moz-flex: 1;
    -ms-flex: 1;
    flex: 1; }
  [flex-lg="5"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 5%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 5%;
    -ms-flex: 0 0 5%;
    flex: 0 0 5%;
    max-width: 5%; }
  [flex-lg="10"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 10%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 10%;
    -ms-flex: 0 0 10%;
    flex: 0 0 10%;
    max-width: 10%; }
  [flex-lg="15"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 15%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 15%;
    -ms-flex: 0 0 15%;
    flex: 0 0 15%;
    max-width: 15%; }
  [flex-lg="20"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 20%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 20%;
    -ms-flex: 0 0 20%;
    flex: 0 0 20%;
    max-width: 20%; }
  [flex-lg="25"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 25%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 25%;
    -ms-flex: 0 0 25%;
    flex: 0 0 25%;
    max-width: 25%; }
  [flex-lg="30"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 30%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 30%;
    -ms-flex: 0 0 30%;
    flex: 0 0 30%;
    max-width: 30%; }
  [flex-lg="35"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 35%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 35%;
    -ms-flex: 0 0 35%;
    flex: 0 0 35%;
    max-width: 35%; }
  [flex-lg="40"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 40%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 40%;
    -ms-flex: 0 0 40%;
    flex: 0 0 40%;
    max-width: 40%; }
  [flex-lg="45"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 45%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 45%;
    -ms-flex: 0 0 45%;
    flex: 0 0 45%;
    max-width: 45%; }
  [flex-lg="50"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 50%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 50%;
    -ms-flex: 0 0 50%;
    flex: 0 0 50%;
    max-width: 50%; }
  [flex-lg="55"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 55%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 55%;
    -ms-flex: 0 0 55%;
    flex: 0 0 55%;
    max-width: 55%; }
  [flex-lg="60"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 60%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 60%;
    -ms-flex: 0 0 60%;
    flex: 0 0 60%;
    max-width: 60%; }
  [flex-lg="65"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 65%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 65%;
    -ms-flex: 0 0 65%;
    flex: 0 0 65%;
    max-width: 65%; }
  [flex-lg="70"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 70%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 70%;
    -ms-flex: 0 0 70%;
    flex: 0 0 70%;
    max-width: 70%; }
  [flex-lg="75"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 75%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 75%;
    -ms-flex: 0 0 75%;
    flex: 0 0 75%;
    max-width: 75%; }
  [flex-lg="80"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 80%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 80%;
    -ms-flex: 0 0 80%;
    flex: 0 0 80%;
    max-width: 80%; }
  [flex-lg="85"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 85%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 85%;
    -ms-flex: 0 0 85%;
    flex: 0 0 85%;
    max-width: 85%; }
  [flex-lg="90"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 90%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 90%;
    -ms-flex: 0 0 90%;
    flex: 0 0 90%;
    max-width: 90%; }
  [flex-lg="95"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 95%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 95%;
    -ms-flex: 0 0 95%;
    flex: 0 0 95%;
    max-width: 95%; }
  [flex-lg="33"], [flex-lg="34"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 33.33%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 33.33%;
    -ms-flex: 0 0 33.33%;
    flex: 0 0 33.33%;
    max-width: 33.33%; }
  [flex-lg="66"], [flex-lg="67"] {
    -webkit-box-flex: 0;
    -webkit-flex: 0 0 66.66%;
    -moz-box-flex: 0;
    -moz-flex: 0 0 66.66%;
    -ms-flex: 0 0 66.66%;
    flex: 0 0 66.66%;
    max-width: 66.66%; }
  [offset-lg="5"] {
    margin-left: 5%; }
  [offset-lg="10"] {
    margin-left: 10%; }
  [offset-lg="15"] {
    margin-left: 15%; }
  [offset-lg="20"] {
    margin-left: 20%; }
  [offset-lg="25"] {
    margin-left: 25%; }
  [offset-lg="30"] {
    margin-left: 30%; }
  [offset-lg="35"] {
    margin-left: 35%; }
  [offset-lg="40"] {
    margin-left: 40%; }
  [offset-lg="45"] {
    margin-left: 45%; }
  [offset-lg="50"] {
    margin-left: 50%; }
  [offset-lg="55"] {
    margin-left: 55%; }
  [offset-lg="60"] {
    margin-left: 60%; }
  [offset-lg="65"] {
    margin-left: 65%; }
  [offset-lg="70"] {
    margin-left: 70%; }
  [offset-lg="75"] {
    margin-left: 75%; }
  [offset-lg="80"] {
    margin-left: 80%; }
  [offset-lg="85"] {
    margin-left: 85%; }
  [offset-lg="90"] {
    margin-left: 90%; }
  [offset-lg="95"] {
    margin-left: 95%; }
  [offset-lg="33"], [offset-lg="34"] {
    margin-left: 33.33%; }
  [offset-lg="66"], [offset-lg="67"] {
    margin-left: 66.66%; }
  [layout-order-lg="1"] {
    -webkit-order: 1;
    -ms-flex-order: 1;
    order: 1; }
  [layout-order-lg="2"] {
    -webkit-order: 2;
    -ms-flex-order: 2;
    order: 2; }
  [layout-order-lg="3"] {
    -webkit-order: 3;
    -ms-flex-order: 3;
    order: 3; }
  [layout-order-lg="4"] {
    -webkit-order: 4;
    -ms-flex-order: 4;
    order: 4; }
  [layout-order-lg="5"] {
    -webkit-order: 5;
    -ms-flex-order: 5;
    order: 5; }
  [layout-order-lg="6"] {
    -webkit-order: 6;
    -ms-flex-order: 6;
    order: 6; }
  [layout-lg] {
    -webkit-box-direction: normal;
    -webkit-box-orient: horizontal;
    -webkit-flex-direction: row;
    -moz-flex-direction: row;
    -ms-flex-direction: row;
    flex-direction: row; }
  [layout-lg=vertical] {
    -webkit-box-direction: normal;
    -webkit-box-orient: vertical;
    -webkit-flex-direction: column;
    -moz-flex-direction: column;
    -ms-flex-direction: column;
    flex-direction: column; }
  [block-lg] {
    display: block; }
  [inline-block-lg] {
    display: inline-block; }
  [show-lg] {
    display: inherit; }
  [hide-lg] {
    display: none; } }

material-tabs-ink-bar {
  height: 2px;
  background: #ffff85;
  position: absolute;
  margin-top: -2px; }

@-webkit-keyframes inkRippleButton {
  0% {
    -webkit-transform: scale(0);
    transform: scale(0);
    opacity: 0.15; }

  50% {
    -webkit-transform: scale(0.75);
    transform: scale(0.75);
    opacity: 0.15; }

  100% {
    -webkit-transform: scale(2);
    transform: scale(2);
    opacity: 0; } }

@keyframes inkRippleButton {
  0% {
    -webkit-transform: scale(0);
    transform: scale(0);
    opacity: 0.15; }

  50% {
    -webkit-transform: scale(0.75);
    transform: scale(0.75);
    opacity: 0.15; }

  100% {
    -webkit-transform: scale(2);
    transform: scale(2);
    opacity: 0; } }

@-webkit-keyframes inkRippleCheckbox {
  0% {
    -webkit-transform: scale(0);
    transform: scale(0);
    opacity: 0.4; }

  50% {
    -webkit-transform: scale(1);
    transform: scale(1);
    opacity: 0.4; }

  100% {
    -webkit-transform: scale(1);
    transform: scale(1);
    opacity: 0; } }

@keyframes inkRippleCheckbox {
  0% {
    -webkit-transform: scale(0);
    transform: scale(0);
    opacity: 0.4; }

  50% {
    -webkit-transform: scale(1);
    transform: scale(1);
    opacity: 0.4; }

  100% {
    -webkit-transform: scale(1);
    transform: scale(1);
    opacity: 0; } }

/*
 * A container inside of a rippling element (eg a button),
 * which contains all of the individual ripples
 */
.material-ripple-container {
  pointer-events: none;
  position: absolute;
  overflow: hidden;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%; }

.material-ripple {
  position: absolute; }

material-backdrop {
  z-index: 7;
  background-color: rgba(0, 0, 0, 0);
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  -webkit-transition: all 0.2s ease-out;
  transition: all 0.2s ease-out; }
  material-backdrop.opaque {
    background-color: rgba(0, 0, 0, 0.4); }
  material-backdrop.ng-enter {
    -webkit-transition-delay: 0.1s;
    transition-delay: 0.1s; }
  material-backdrop.ng-enter, material-backdrop.ng-leave.ng-leave-active {
    opacity: 0; }
  material-backdrop.ng-leave, material-backdrop.ng-enter.ng-enter-active {
    opacity: 1; }

material-bottom-sheet {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 8px 16px 88px 16px;
  z-index: 8;
  background-color: #FAFAFA;
  border-top: 1px solid #BCBBBB;
  -webkit-transform: translate3d(0, 80px, 0);
  transform: translate3d(0, 80px, 0);
  -webkit-transition: 0.2s linear;
  transition: 0.2s linear;
  -webkit-transition-property: -webkit-transform;
  transition-property: transform; }
  material-bottom-sheet.has-header {
    padding-top: 0; }
  material-bottom-sheet.ng-enter {
    opacity: 0;
    -webkit-transform: translate3d(0, 100%, 0);
    transform: translate3d(0, 100%, 0); }
  material-bottom-sheet.ng-enter-active {
    opacity: 1;
    display: block;
    -webkit-transform: translate3d(0, 80px, 0) !important;
    transform: translate3d(0, 80px, 0) !important; }
  material-bottom-sheet.ng-leave-active {
    -webkit-transform: translate3d(0, 100%, 0) !important;
    transform: translate3d(0, 100%, 0) !important; }
  material-bottom-sheet h2.material-subheader {
    background-color: transparent;
    font-family: 'RobotoDraft', 'Helvetica Neue', Helvetica, Arial;
    color: #999;
    line-height: 56px;
    padding: 0;
    white-space: nowrap; }
  material-bottom-sheet material-inline-icon {
    display: inline-block;
    height: 24px;
    width: 24px;
    fill: #444; }
  material-bottom-sheet material-item {
    display: -webkit-box;
    display: -webkit-flex;
    display: -moz-box;
    display: -moz-flex;
    display: -ms-flexbox;
    display: flex;
    outline: none; }
    material-bottom-sheet material-item:hover {
      cursor: pointer; }
  material-bottom-sheet.list material-item {
    -webkit-box-align: center;
    -ms-flex-align: center;
    -webkit-align-items: center;
    -moz-align-items: center;
    align-items: center;
    height: 48px;
    color: #999; }
    material-bottom-sheet.list material-item div.material-icon-container {
      display: inline-block;
      height: 24px;
      margin-right: 32px; }
  material-bottom-sheet.grid {
    padding-left: 24px;
    padding-right: 24px;
    padding-top: 0; }
    material-bottom-sheet.grid material-list {
      display: -webkit-box;
      display: -webkit-flex;
      display: -moz-box;
      display: -moz-flex;
      display: -ms-flexbox;
      display: flex;
      -webkit-box-direction: normal;
      -webkit-box-orient: horizontal;
      -webkit-flex-direction: row;
      -moz-flex-direction: row;
      -ms-flex-direction: row;
      flex-direction: row;
      -webkit-flex-wrap: wrap;
      -moz-flex-wrap: wrap;
      -ms-flex-wrap: wrap;
      flex-wrap: wrap;
      -webkit-transition: all 0.5s;
      transition: all 0.5s; }
    material-bottom-sheet.grid material-item {
      -webkit-box-direction: normal;
      -webkit-box-orient: vertical;
      -webkit-flex-direction: column;
      -moz-flex-direction: column;
      -ms-flex-direction: column;
      flex-direction: column;
      -webkit-box-align: center;
      -ms-flex-align: center;
      -webkit-align-items: center;
      -moz-align-items: center;
      align-items: center;
      -webkit-transition: all 0.5s;
      transition: all 0.5s;
      height: 80px;
      margin-top: 8px;
      margin-bottom: 8px;
      /* Mixin for how many grid items to show per row */ }
      @media screen and (max-width: 600px) {
        material-bottom-sheet.grid material-item {
          -webkit-box-flex: 1;
          -webkit-flex: 1 1 33.33333%;
          -moz-box-flex: 1;
          -moz-flex: 1 1 33.33333%;
          -ms-flex: 1 1 33.33333%;
          flex: 1 1 33.33333%;
          max-width: 33.33333%; }
          material-bottom-sheet.grid material-item:nth-of-type(3n+1) {
            -webkit-box-align: start;
            -ms-flex-align: start;
            -webkit-align-items: flex-start;
            -moz-align-items: flex-start;
            align-items: flex-start; }
          material-bottom-sheet.grid material-item:nth-of-type(3n) {
            -webkit-box-align: end;
            -ms-flex-align: end;
            -webkit-align-items: flex-end;
            -moz-align-items: flex-end;
            align-items: flex-end; } }
      @media screen and (min-width: 600px) and (max-width: 960px) {
        material-bottom-sheet.grid material-item {
          -webkit-box-flex: 1;
          -webkit-flex: 1 1 25%;
          -moz-box-flex: 1;
          -moz-flex: 1 1 25%;
          -ms-flex: 1 1 25%;
          flex: 1 1 25%;
          max-width: 25%; } }
      @media screen and (min-width: 960px) and (max-width: 1200px) {
        material-bottom-sheet.grid material-item {
          -webkit-box-flex: 1;
          -webkit-flex: 1 1 16.66667%;
          -moz-box-flex: 1;
          -moz-flex: 1 1 16.66667%;
          -ms-flex: 1 1 16.66667%;
          flex: 1 1 16.66667%;
          max-width: 16.66667%; } }
      @media screen and (min-width: 1200px) {
        material-bottom-sheet.grid material-item {
          -webkit-box-flex: 1;
          -webkit-flex: 1 1 14.28571%;
          -moz-box-flex: 1;
          -moz-flex: 1 1 14.28571%;
          -ms-flex: 1 1 14.28571%;
          flex: 1 1 14.28571%;
          max-width: 14.28571%; } }
      material-bottom-sheet.grid material-item .material-item-content {
        display: -webkit-box;
        display: -webkit-flex;
        display: -moz-box;
        display: -moz-flex;
        display: -ms-flexbox;
        display: flex;
        -webkit-box-direction: normal;
        -webkit-box-orient: vertical;
        -webkit-flex-direction: column;
        -moz-flex-direction: column;
        -ms-flex-direction: column;
        flex-direction: column;
        -webkit-box-align: center;
        -ms-flex-align: center;
        -webkit-align-items: center;
        -moz-align-items: center;
        align-items: center;
        width: 48px; }
      material-bottom-sheet.grid material-item .material-icon-container {
        display: inline-block;
        box-sizing: border-box;
        height: 48px;
        width: 48px;
        margin: 8px 0; }
      material-bottom-sheet.grid material-item p.grid-text {
        font-weight: 300;
        line-height: 16px;
        font-size: 13px;
        margin: 0;
        white-space: nowrap;
        width: 48px;
        text-align: center; }

material-content {
  display: block;
  position: relative;
  overflow: auto;
  -webkit-overflow-scrolling: touch; }
  material-content[scroll-y] {
    overflow-y: auto;
    overflow-x: hidden; }
  material-content[scroll-x] {
    overflow-x: auto;
    overflow-y: hidden; }
  material-content.material-content-padding {
    padding: 8px; }

@media (min-width: 600px) {
  material-content.material-content-padding {
    padding: 16px; } }

material-icon {
  margin: auto;
  padding: 0;
  display: inline-block;
  margin-top: 5px;
  background-repeat: no-repeat no-repeat;
  pointer-events: none; }

svg, object {
  fill: currentColor;
  color-fill: currentColor; }

/**
 * Position a FAB button.
 */
material-button {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  position: relative;
  display: inline-block;
  outline: none;
  border: 0;
  padding: 0;
  margin: 0;
  border-radius: 3px;
  text-align: center;
  text-transform: uppercase;
  font-weight: inherit;
  font-style: inherit;
  font-variant: inherit;
  font-size: inherit;
  font-family: inherit;
  line-height: inherit;
  cursor: pointer;
  overflow: hidden; }
  material-button .material-button-inner {
    display: block;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background: transparent;
    border: none;
    color: inherit;
    outline: none;
    text-transform: inherit;
    font-weight: inherit;
    font-style: inherit;
    font-variant: inherit;
    font-size: inherit;
    font-family: inherit;
    line-height: inherit;
    white-space: nowrap;
    padding: 6px; }
  material-button a {
    text-decoration: none; }
  material-button[href] {
    pointer-events: none; }
    material-button[href] .material-button-inner {
      pointer-events: auto; }
  material-button.material-button-colored {
    color: #4285f4;
    fill: #4285f4; }
  material-button.material-button-cornered {
    border-radius: 0; }
  material-button:not([disabled]):hover, material-button:not([disabled]).focus {
    background-color: #e4e4e4; }
  material-button[disabled] {
    background-color: #eaeaea !important;
    color: #a8a8a8 !important;
    cursor: auto; }
  material-button.material-button-icon {
    padding: 0;
    background: none; }
  material-button.material-button-raised {
    background-color: #dfdfe9;
    -webkit-transition: 0.2s linear;
    -webkit-transition-property: box-shadow, -webkit-transform, background-color;
    transition: 0.2s linear transform;
    transition-property: box-shadow, transform, background-color;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0); }
    material-button.material-button-raised:not([disabled]):hover, material-button.material-button-raised:not([disabled]).focus {
      background-color: #d6d6d6; }
    material-button.material-button-raised.material-button-colored {
      background-color: #4285f4;
      color: #fff; }
      material-button.material-button-raised.material-button-colored:hover:not([disabled]), material-button.material-button-raised.material-button-colored.focus {
        background-color: #3367d6; }
  material-button.material-button-fab {
    z-index: 2;
    width: 56px;
    height: 56px;
    border-radius: 28px;
    border-radius: 50%;
    overflow: hidden;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    -webkit-transition: 0.2s linear;
    -webkit-transition-property: -webkit-transform, box-shadow;
    transition: transform 0.2s linear;
    transition-property: transform, box-shadow; }
    material-button.material-button-fab.material-button-fab-bottom-right {
      top: auto;
      right: 28px;
      bottom: 28px;
      left: auto;
      position: absolute; }
    material-button.material-button-fab.material-button-fab-bottom-left {
      top: auto;
      right: auto;
      bottom: 28px;
      left: 28px;
      position: absolute; }
    material-button.material-button-fab.material-button-fab-top-right {
      top: 28px;
      right: 28px;
      bottom: auto;
      left: auto;
      position: absolute; }
    material-button.material-button-fab.material-button-fab-top-left {
      top: 28px;
      right: auto;
      bottom: auto;
      left: 28px;
      position: absolute; }
  material-button:not([disabled]).material-button-raised.focus, material-button:not([disabled]).material-button-raised:hover, material-button:not([disabled]).material-button-fab.focus, material-button:not([disabled]).material-button-fab:hover {
    -webkit-transform: translate3d(0, -1px, 0);
    transform: translate3d(0, -1px, 0); }

.material-toast-open-top material-button.material-button-fab-top-left, .material-toast-open-top material-button.material-button-fab-top-right {
  -webkit-transform: translate3d(0, 32px, 0);
  transform: translate3d(0, 32px, 0); }
  .material-toast-open-top material-button.material-button-fab-top-left.focus, .material-toast-open-top material-button.material-button-fab-top-left:hover:not([disabled]), .material-toast-open-top material-button.material-button-fab-top-right.focus, .material-toast-open-top material-button.material-button-fab-top-right:hover:not([disabled]) {
    -webkit-transform: translate3d(0, 31px, 0);
    transform: translate3d(0, 31px, 0); }

.material-toast-open-bottom material-button.material-button-fab-bottom-left, .material-toast-open-bottom material-button.material-button-fab-bottom-right {
  -webkit-transform: translate3d(0, -32px, 0);
  transform: translate3d(0, -32px, 0); }
  .material-toast-open-bottom material-button.material-button-fab-bottom-left.focus, .material-toast-open-bottom material-button.material-button-fab-bottom-left:hover, .material-toast-open-bottom material-button.material-button-fab-bottom-right.focus, .material-toast-open-bottom material-button.material-button-fab-bottom-right:hover {
    -webkit-transform: translate3d(0, -33px, 0);
    transform: translate3d(0, -33px, 0); }

.material-button-group {
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -moz-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-flex: 1;
  -webkit-flex: 1;
  -moz-box-flex: 1;
  -moz-flex: 1;
  -ms-flex: 1;
  flex: 1;
  width: 100%; }

.material-button-group > .material-button {
  -webkit-box-flex: 1;
  -webkit-flex: 1;
  -moz-box-flex: 1;
  -moz-flex: 1;
  -ms-flex: 1;
  flex: 1;
  display: block;
  overflow: hidden;
  width: 0;
  border-width: 1px 0px 1px 1px;
  border-radius: 0;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap; }
  .material-button-group > .material-button:first-child {
    border-radius: 2px 0px 0px 2px; }
  .material-button-group > .material-button:last-child {
    border-right-width: 1px;
    border-radius: 0px 2px 2px 0px; }

.material-dialog-container {
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -moz-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  -webkit-justify-content: center;
  -moz-justify-content: center;
  justify-content: center;
  -webkit-box-align: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  -moz-align-items: center;
  align-items: center;
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 10; }
  .material-dialog-container.active {
    -webkit-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
    transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
    -webkit-transform: translate3d(0, 0, 0) scale(1);
    transform: translate3d(0, 0, 0) scale(1);
    opacity: 1; }
  .material-dialog-container.ng-leave.ng-leave-active {
    -webkit-transform: translate3d(0, 100%, 0) scale(0.5);
    transform: translate3d(0, 100%, 0) scale(0.5);
    opacity: 0; }

material-dialog {
  min-width: 240px;
  max-width: 80%;
  max-height: 80%;
  margin: auto;
  position: relative;
  background-color: #fff;
  border-radius: 4px;
  box-shadow: 0px 27px 24px 0 rgba(0, 0, 0, 0.2);
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -moz-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-direction: normal;
  -webkit-box-orient: vertical;
  -webkit-flex-direction: column;
  -moz-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column; }
  material-dialog .dialog-content {
    -webkit-order: 1;
    -ms-flex-order: 1;
    order: 1;
    padding: 24px;
    overflow: auto;
    -webkit-overflow-scrolling: touch; }
  material-dialog .dialog-actions {
    -webkit-order: 2;
    -ms-flex-order: 2;
    order: 2;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    display: -webkit-box;
    display: -webkit-flex;
    display: -moz-box;
    display: -moz-flex;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-align: center;
    -ms-flex-align: center;
    -webkit-align-items: center;
    -moz-align-items: center;
    align-items: center;
    -webkit-box-pack: end;
    -ms-flex-pack: end;
    -webkit-justify-content: flex-end;
    -moz-justify-content: flex-end;
    justify-content: flex-end;
    padding: 8px 16px;
    min-height: 40px; }
    material-dialog .dialog-actions > * {
      margin-left: 8px; }
  material-dialog.dialog-content-overflow .dialog-actions {
    border-top: 1px solid #eee; }

material-divider {
  display: block;
  border-top: 1px solid rgba(0, 0, 0, 0.12) !important;
  margin: 0; }
  material-divider[inset] {
    margin-left: 80px; }

material-checkbox {
  display: block;
  margin: 15px;
  white-space: nowrap;
  cursor: pointer;
  outline: none; }
  material-checkbox .material-container {
    position: relative;
    top: 4px;
    display: inline-block;
    width: 18px;
    height: 18px; }
    material-checkbox .material-container .material-ripple-container {
      position: absolute;
      display: block;
      width: 54px;
      height: 54px;
      left: -18px;
      top: -18px; }
    material-checkbox .material-container .material-ripple {
      color: #0f9d58; }
  material-checkbox.material-checked .material-ripple {
    color: #5a5f5a; }
  material-checkbox .circle {
    border-radius: 50%; }
  material-checkbox .material-icon {
    -webkit-transition: 240ms;
    transition: 240ms;
    position: absolute;
    top: 0;
    left: 0;
    width: 18px;
    height: 18px;
    border: 2px solid #6D6D6D;
    border-radius: 2px; }
  material-checkbox.material-checked .material-icon {
    border-color: #4CAF50;
    background: #4CAF50; }
  material-checkbox[disabled] {
    cursor: no-drop; }
    material-checkbox[disabled] .material-icon {
      border-color: #a0a0a0; }
    material-checkbox[disabled].material-checked .material-icon {
      background: #a0a0a0; }
  material-checkbox:focus .material-label {
    border-color: black; }
  material-checkbox.material-checked .material-icon:after {
    -webkit-transform: rotate(45deg);
    transform: rotate(45deg);
    position: absolute;
    left: 4px;
    display: table;
    width: 6px;
    height: 12px;
    border: 2px solid #eeeeee;
    border-top: 0;
    border-left: 0;
    content: ' '; }
  material-checkbox .material-label {
    border: 1px dotted transparent;
    position: relative;
    display: inline-block;
    margin-left: 10px;
    vertical-align: middle;
    white-space: normal;
    pointer-events: none; }

material-card {
  display: block;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.26);
  margin: 8px;
  padding: 8px;
  border-radius: 2px; }
  material-card .material-card-image {
    display: block;
    width: 100%;
    border-radius: 2px 2px 0 0; }

material-radio-button, .material-switch-thumb {
  display: block;
  margin: 15px;
  white-space: nowrap;
  cursor: pointer; }
  material-radio-button input, .material-switch-thumb input {
    display: none; }
  material-radio-button .material-container, .material-switch-thumb .material-container {
    position: relative;
    top: 4px;
    display: inline-block;
    width: 16px;
    height: 16px;
    cursor: pointer; }
    material-radio-button .material-container .material-ripple-container, .material-switch-thumb .material-container .material-ripple-container {
      position: absolute;
      display: block;
      width: 48px;
      height: 48px;
      left: -16px;
      top: -16px; }
    material-radio-button .material-container .material-ripple, .material-switch-thumb .material-container .material-ripple {
      color: #0f9d58; }
  material-radio-button .material-off, .material-switch-thumb .material-off {
    position: absolute;
    top: 0px;
    left: 0px;
    width: 16px;
    height: 16px;
    border: solid 2px;
    border-color: #5a5a5a;
    border-radius: 50%; }
  material-radio-button .material-on, .material-switch-thumb .material-on {
    position: absolute;
    top: 0;
    left: 0;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background-color: #0f9d58;
    transition: -webkit-transform ease 0.28s;
    transition: transform ease 0.28s;
    -webkit-transform: scale(0);
    transform: scale(0); }
  material-radio-button.material-checked .material-on, .material-switch-thumb.material-checked .material-on {
    -webkit-transform: scale(1.1);
    transform: scale(1.1); }
  material-radio-button.material-checked .material-ink-ripple, .material-switch-thumb.material-checked .material-ink-ripple {
    color: #119957; }
  material-radio-button .material-label, .material-switch-thumb .material-label {
    position: relative;
    display: inline-block;
    margin-left: 10px;
    vertical-align: middle;
    white-space: normal;
    pointer-events: none;
    width: auto; }
  material-radio-button .circle, .material-switch-thumb .circle {
    border-radius: 50%; }

material-radio-group {
  border: 1px dotted transparent;
  display: block;
  outline: none; }
  material-radio-group:focus {
    border-color: #111111; }

material-sidenav {
  position: absolute;
  width: 304px;
  bottom: 0;
  background-color: white;
  -webkit-transition: -webkit-transform 0.3s ease-in-out;
  transition: transform 0.3s ease-in-out; }

.material-sidenav-left, material-sidenav {
  left: 0;
  top: 0;
  -webkit-transform: translate3d(-100%, 0, 0);
  transform: translate3d(-100%, 0, 0); }
  .material-sidenav-left.open, material-sidenav.open {
    -webkit-transform: translate3d(0%, 0, 0);
    transform: translate3d(0%, 0, 0);
    z-index: 8; }

.material-sidenav-right {
  left: 100%;
  top: 0;
  -webkit-transform: translate3d(100%, 0, 0);
  transform: translate3d(100%, 0, 0); }
  .material-sidenav-right.open {
    -webkit-transform: translate3d(-100%, 0, 0);
    transform: translate3d(-100%, 0, 0);
    z-index: 8; }

@media (min-width: 960px) {
  material-sidenav {
    position: static;
    -webkit-transform: translate3d(0, 0, 0) !important;
    transform: translate3d(0, 0, 0) !important; }
  .material-sidenav-backdrop {
    display: none !important; } }

@media (max-width: 416px) {
  material-sidenav {
    max-width: 75%; } }

@-webkit-keyframes sliderFocusThumb {
  0% {
    opacity: 0;
    -webkit-transform: scale(0);
    transform: scale(0); }

  50% {
    -webkit-transform: scale(1);
    transform: scale(1);
    opacity: 1; }

  100% {
    opacity: 0; } }

@keyframes sliderFocusThumb {
  0% {
    opacity: 0;
    -webkit-transform: scale(0);
    transform: scale(0); }

  50% {
    -webkit-transform: scale(1);
    transform: scale(1);
    opacity: 1; }

  100% {
    opacity: 0; } }

material-slider {
  height: 48px;
  position: relative;
  display: block;
  margin-left: 4px;
  margin-right: 4px;
  /**
   * Track
   */
  /**
   * Slider thumb
   */
  /* The sign that's focused in discrete mode */
  /**
   * The border/background that comes in when focused in non-discrete mode
   */
  /* Don't animate left/right while panning */ }
  material-slider .slider-track-container {
    width: 100%;
    position: absolute;
    top: 23px;
    height: 2px; }
  material-slider .slider-track {
    position: absolute;
    left: 0;
    right: 0;
    height: 100%;
    background: #C8C8C8; }
  material-slider .slider-track-fill {
    background: #03A9F4;
    -webkit-transition: width 0.05s linear;
    transition: width 0.05s linear; }
  material-slider .slider-track-ticks {
    position: absolute;
    left: 0;
    right: 0;
    height: 100%; }
  material-slider .slider-thumb-container {
    position: absolute;
    left: 0;
    top: 0;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    transition: transform 0.1s linear;
    -webkit-transition: -webkit-transform 0.1s linear; }
  material-slider .slider-thumb {
    z-index: 1;
    position: absolute;
    left: -19px;
    top: 5px;
    width: 38px;
    height: 38px;
    border-radius: 38px;
    -webkit-transform: scale(0.5);
    transform: scale(0.5);
    -webkit-transition: all 0.1s linear;
    transition: all 0.1s linear; }
    material-slider .slider-thumb:after {
      content: '';
      position: absolute;
      left: 3px;
      top: 3px;
      width: 32px;
      height: 32px;
      border-radius: 32px;
      border: 3px solid #03a9f4;
      background-color: #03a9f4; }
  material-slider .slider-sign {
    /* Center the children (slider-thumb-text) */
    display: -webkit-box;
    display: -webkit-flex;
    display: -moz-box;
    display: -moz-flex;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-align: center;
    -ms-flex-align: center;
    -webkit-align-items: center;
    -moz-align-items: center;
    align-items: center;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    -webkit-justify-content: center;
    -moz-justify-content: center;
    justify-content: center;
    position: absolute;
    left: -14px;
    top: -20px;
    width: 28px;
    height: 28px;
    border-radius: 28px;
    background-color: #03a9f4;
    -webkit-transform: scale(0.4) translate3d(0, 70px, 0);
    transform: scale(0.4) translate3d(0, 70px, 0);
    -webkit-transition: all 0.2s ease-in-out;
    transition: all 0.2s ease-in-out;
    /* The arrow pointing down under the sign */ }
    material-slider .slider-sign:after {
      position: absolute;
      content: '';
      left: -0px;
      border-radius: 16px;
      top: 19px;
      border-left: 14px solid transparent;
      border-right: 14px solid transparent;
      border-top: 16px solid #03a9f4;
      opacity: 0;
      -webkit-transform: translate3d(0, -8px, 0);
      transform: translate3d(0, -8px, 0);
      -webkit-transition: all 0.2s ease-in-out;
      transition: all 0.2s ease-in-out; }
    material-slider .slider-sign .slider-thumb-text {
      z-index: 1;
      color: white;
      font-size: 12px;
      font-weight: bold; }
  material-slider .slider-focus-thumb {
    position: absolute;
    left: -24px;
    top: 0px;
    width: 48px;
    height: 48px;
    border-radius: 48px;
    display: none;
    opacity: 0;
    background-color: #C0C0C0;
    -webkit-animation: sliderFocusThumb 0.4s linear;
    animation: sliderFocusThumb 0.4s linear; }
  material-slider .slider-focus-ring {
    position: absolute;
    left: -24px;
    top: 0px;
    width: 48px;
    height: 48px;
    border-radius: 48px;
    border: 2px solid #D6D6D6;
    background-color: transparent;
    -webkit-transform: scale(0);
    transform: scale(0);
    -webkit-transition: all 0.2s linear;
    transition: all 0.2s linear; }
  material-slider .slider-disabled-thumb {
    position: absolute;
    left: -22px;
    top: 2px;
    width: 44px;
    height: 44px;
    border-radius: 44px;
    -webkit-transform: scale(0.35);
    transform: scale(0.35);
    border: 6px solid white;
    display: none; }
  material-slider.slider-min .slider-thumb:after {
    background-color: white; }
  material-slider.slider-min .slider-sign {
    opacity: 0; }
  material-slider:focus {
    outline: none; }
  material-slider.panning .slider-thumb-container, material-slider.panning .slider-track-fill {
    -webkit-transition: none;
    transition: none; }
  material-slider:not([discrete]) {
    /* Hide the sign and ticks in non-discrete mode */ }
    material-slider:not([discrete]) .slider-track-ticks, material-slider:not([discrete]) .slider-sign {
      display: none; }
    material-slider:not([discrete]):not([disabled]):hover .slider-thumb {
      -webkit-transform: scale(0.6);
      transform: scale(0.6); }
    material-slider:not([discrete]):not([disabled]):focus .slider-focus-thumb, material-slider:not([discrete]):not([disabled]).active .slider-focus-thumb {
      display: block; }
    material-slider:not([discrete]):not([disabled]):focus .slider-focus-ring, material-slider:not([discrete]):not([disabled]).active .slider-focus-ring {
      -webkit-transform: scale(1);
      transform: scale(1); }
    material-slider:not([discrete]):not([disabled]):focus .slider-thumb, material-slider:not([discrete]):not([disabled]).active .slider-thumb {
      -webkit-transform: scale(0.85);
      transform: scale(0.85); }
  material-slider[discrete] {
    /* Hide the focus thumb in discrete mode */ }
    material-slider[discrete] .slider-focus-thumb, material-slider[discrete] .slider-focus-ring {
      display: none; }
    material-slider[discrete]:not([disabled]):focus .slider-sign, material-slider[discrete]:not([disabled]):focus .slider-sign:after, material-slider[discrete]:not([disabled]).active .slider-sign, material-slider[discrete]:not([disabled]).active .slider-sign:after {
      opacity: 1;
      -webkit-transform: translate3d(0, 0, 0) scale(1);
      transform: translate3d(0, 0, 0) scale(1); }
  material-slider[disabled] .slider-track-fill {
    display: none; }
  material-slider[disabled] .slider-thumb {
    -webkit-transform: scale(0.35);
    transform: scale(0.35); }
    material-slider[disabled] .slider-thumb:after {
      border-color: #BEBEBE; }
  material-slider[disabled]:not(.slider-min) .slider-thumb:after {
    background-color: #BEBEBE; }
  material-slider[disabled] .slider-disabled-thumb {
    display: block; }

@-webkit-keyframes subheaderStickyHoverIn {
  0% {
    box-shadow: 0 0 0 0 transparent; }

  100% {
    box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16); } }

@keyframes subheaderStickyHoverIn {
  0% {
    box-shadow: 0 0 0 0 transparent; }

  100% {
    box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16); } }

@-webkit-keyframes subheaderStickyHoverOut {
  0% {
    box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16); }

  100% {
    box-shadow: 0 0 0 0 transparent; } }

@keyframes subheaderStickyHoverOut {
  0% {
    box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16); }

  100% {
    box-shadow: 0 0 0 0 transparent; } }

.material-subheader {
  color: #999;
  display: block;
  font-size: 0.9em;
  font-weight: 400;
  line-height: 1em;
  padding: 16px 0px 16px 16px;
  margin: 0 0 0 0;
  margin-right: 16px;
  background-color: white;
  position: relative; }
  .material-subheader.material-subheader-colored {
    color: #03a9f4; }
  .material-subheader:not(.sticky-no-effect) {
    -webkit-transition: 0.2s ease-out margin;
    transition: 0.2s ease-out margin; }
    .material-subheader:not(.sticky-no-effect):after {
      position: absolute;
      left: 0;
      bottom: 0;
      top: 0;
      right: -16px;
      content: ''; }
    .material-subheader:not(.sticky-no-effect)[sticky-state="active"] {
      margin-top: -2px; }
    .material-subheader:not(.sticky-no-effect):not(.material-sticky-clone)[sticky-prev-state="active"]:after {
      -webkit-animation: subheaderStickyHoverOut 0.3s ease-out both;
      animation: subheaderStickyHoverOut 0.3s ease-out both; }

.material-sticky-clone {
  z-index: 1;
  top: 0;
  left: 0;
  right: 0;
  position: absolute;
  -webkit-transform: translate3d(-9999px, -9999px, 0);
  transform: translate3d(-9999px, -9999px, 0); }
  .material-sticky-clone[sticky-state="active"] {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0); }
    .material-sticky-clone[sticky-state="active"]:not(.sticky-no-effect):after {
      -webkit-animation: subheaderStickyHoverIn 0.3s ease-out both;
      animation: subheaderStickyHoverIn 0.3s ease-out both; }

material-switch {
  display: block;
  position: relative;
  height: 24px;
  margin: 8px;
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -moz-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  -moz-align-items: center;
  align-items: center;
  /* used also in _radio-button.scss */ }
  material-switch .material-switch-bar {
    position: absolute;
    left: 16px;
    top: 12px;
    width: 32px;
    height: 1px;
    background-color: #5a5a5a;
    pointer-events: none; }
  material-switch .material-switch-thumb {
    position: absolute;
    margin: 0;
    left: 0;
    top: 0;
    outline: none; }
    material-switch .material-switch-thumb .material-container {
      position: absolute;
      -webkit-transition: -webkit-transform 0.2s linear;
      transition: transform 0.2s linear;
      -webkit-transform: translate3d(0, 0, 0);
      transform: translate3d(0, 0, 0); }
    material-switch .material-switch-thumb.material-checked .material-container {
      -webkit-transform: translate3d(48px, 0, 0);
      transform: translate3d(48px, 0, 0); }
    material-switch .material-switch-thumb:focus .material-label {
      border: 1px dotted black; }
    material-switch .material-switch-thumb .material-label {
      margin-left: 72px; }

label {
  display: block;
  font-size: 0.75em; }

textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"] {
  display: block;
  border-width: 0 0 1px 0;
  padding-top: 2px;
  line-height: 26px; }
  textarea:focus, input[type="text"]:focus, input[type="password"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="date"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, input[type="number"]:focus, input[type="email"]:focus, input[type="url"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="color"]:focus {
    outline: 0; }

input, textarea {
  background: none; }
  input:-ms-input-placeholder, textarea:-ms-input-placeholder {
    color: #a4a4a4; }
  input::-webkit-input-placeholder, textarea::-webkit-input-placeholder {
    color: #a4a4a4; }

material-input-group, .material-input-group {
  margin: 10px 0 10px 0;
  position: relative;
  display: block; }
  material-input-group label, .material-input-group label {
    z-index: 1;
    pointer-events: none;
    -webkit-font-smoothing: antialiased; }
    material-input-group label:hover, .material-input-group label:hover {
      cursor: text; }
  material-input-group label, .material-input-group label {
    color: #999;
    -webkit-transform: translate3d(0, 22px, 0);
    transform: translate3d(0, 22px, 0);
    -webkit-transform-origin: left center;
    transform-origin: left center;
    -webkit-transition: all ease-out 150ms;
    transition: all ease-out 150ms;
    -webkit-transition: all ease-out 150ms;
    transition: all ease-out 150ms; }
  material-input-group input, material-input-group textarea, .material-input-group input, .material-input-group textarea {
    color: #2f2f2f;
    border-color: #c7c7c7;
    border-bottom-width: 1px;
    -webkit-transition: all ease-out 150ms;
    transition: all ease-out 150ms; }
  material-input-group.material-input-focused label, .material-input-group.material-input-focused label {
    color: #EE008B;
    -webkit-transform: translate3d(0, 4px, 0) scale(0.75);
    transform: translate3d(0, 4px, 0) scale(0.75); }
  material-input-group.material-input-focused input, material-input-group.material-input-focused textarea, .material-input-group.material-input-focused input, .material-input-group.material-input-focused textarea {
    color: #2f2f2f;
    border-color: #EE008B;
    border-bottom-width: 2px; }
  material-input-group.material-input-has-value label, .material-input-group.material-input-has-value label {
    color: #EE008B;
    -webkit-transform: translate3d(0, 4px, 0) scale(0.75);
    transform: translate3d(0, 4px, 0) scale(0.75); }
  material-input-group.material-input-has-value:not(.material-input-focused) label, .material-input-group.material-input-has-value:not(.material-input-focused) label {
    color: #999;
    -webkit-transform: translate3d(0, 4px, 0) scale(0.75);
    transform: translate3d(0, 4px, 0) scale(0.75); }
  material-input-group[disabled] input, material-input-group[disabled] textarea, .material-input-group[disabled] input, .material-input-group[disabled] textarea {
    color: #bcbcbc;
    border-color: #bcbcbc;
    border-bottom-width: 0px; }
  material-input-group[disabled] input, material-input-group[disabled] textarea, .material-input-group[disabled] input, .material-input-group[disabled] textarea {
    background-image: linear-gradient(to right, #cfcfcf 0%, #cfcfcf 50%, rgba(0, 0, 0, 0) 0%);
    background-position: 0 bottom;
    background-size: 2px 1px;
    background-repeat: repeat-x;
    background-size: 3px 1px;
    pointer-events: none;
    tabindex: -1; }
  material-input-group[disabled] label, .material-input-group[disabled] label {
    color: #b0b0b0;
    -webkit-transform: translate3d(0, 4px, 0) scale(0.75);
    transform: translate3d(0, 4px, 0) scale(0.75); }
  material-input-group[disabled] *:not(.material-input-has-value) label, .material-input-group[disabled] *:not(.material-input-has-value) label {
    color: #b0b0b0;
    -webkit-transform: translate3d(0, 22px, 0);
    transform: translate3d(0, 22px, 0);
    -webkit-transform-origin: left center;
    transform-origin: left center;
    -webkit-transition: all ease-out 150ms;
    transition: all ease-out 150ms; }

.dark material-input-group label, .dark .material-input-group label {
  color: #5d5d5d;
  -webkit-transform: translate3d(0, 22px, 0);
  transform: translate3d(0, 22px, 0);
  -webkit-transform-origin: left center;
  transform-origin: left center;
  -webkit-transition: all ease-out 150ms;
  transition: all ease-out 150ms;
  -webkit-transition: all ease-out 150ms;
  transition: all ease-out 150ms; }
.dark material-input-group input, .dark material-input-group textarea, .dark .material-input-group input, .dark .material-input-group textarea {
  color: #d6d6d6;
  border-color: #4c4c4c;
  border-bottom-width: 1px;
  -webkit-transition: all ease-out 150ms;
  transition: all ease-out 150ms; }
.dark material-input-group.material-input-focused label, .dark .material-input-group.material-input-focused label {
  color: #1194f6;
  -webkit-transform: translate3d(0, 4px, 0) scale(0.75);
  transform: translate3d(0, 4px, 0) scale(0.75); }
.dark material-input-group.material-input-focused input, .dark material-input-group.material-input-focused textarea, .dark .material-input-group.material-input-focused input, .dark .material-input-group.material-input-focused textarea {
  color: #d6d6d6;
  border-color: #1194f6;
  border-bottom-width: 2px; }
.dark material-input-group.material-input-has-value label, .dark .material-input-group.material-input-has-value label {
  color: #1194f6;
  -webkit-transform: translate3d(0, 4px, 0) scale(0.75);
  transform: translate3d(0, 4px, 0) scale(0.75); }
.dark material-input-group.material-input-has-value:not(.material-input-focused) label, .dark .material-input-group.material-input-has-value:not(.material-input-focused) label {
  color: #5d5d5d;
  -webkit-transform: translate3d(0, 4px, 0) scale(0.75);
  transform: translate3d(0, 4px, 0) scale(0.75); }
.dark material-input-group[disabled] input, .dark material-input-group[disabled] textarea, .dark .material-input-group[disabled] input, .dark .material-input-group[disabled] textarea {
  color: #5d5d5d;
  border-color: #333333;
  border-bottom-width: 0px; }
.dark material-input-group[disabled] input, .dark material-input-group[disabled] textarea, .dark .material-input-group[disabled] input, .dark .material-input-group[disabled] textarea {
  background-image: linear-gradient(to right, #525252 0%, #525252 50%, rgba(0, 0, 0, 0) 0%);
  background-position: 0 bottom;
  background-size: 2px 1px;
  background-repeat: repeat-x;
  background-size: 3px 1px;
  pointer-events: none;
  tabindex: -1; }
.dark material-input-group[disabled] label, .dark .material-input-group[disabled] label {
  color: #858585;
  -webkit-transform: translate3d(0, 4px, 0) scale(0.75);
  transform: translate3d(0, 4px, 0) scale(0.75); }
.dark material-input-group[disabled] *:not(.material-input-has-value) label, .dark .material-input-group[disabled] *:not(.material-input-has-value) label {
  color: #858585;
  -webkit-transform: translate3d(0, 22px, 0);
  transform: translate3d(0, 22px, 0);
  -webkit-transform-origin: left center;
  transform-origin: left center;
  -webkit-transition: all ease-out 150ms;
  transition: all ease-out 150ms; }

.theme-dark-tff {
  background-color: #333 !important;
  color: #999 !important; }

material-toast {
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -moz-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  -webkit-box-align: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  -moz-align-items: center;
  align-items: center;
  background: #323232;
  color: #f1f1f1;
  min-height: 48px;
  padding-left: 24px;
  padding-right: 24px;
  height: 24px;
  box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
  border-radius: 2px;
  font-size: 14px;
  cursor: default;
  position: fixed;
  max-width: 879px;
  max-height: 40px;
  z-index: 9;
  opacity: 1;
  -webkit-transform: translate3d(0, 0, 0) rotateZ(0deg);
  transform: translate3d(0, 0, 0) rotateZ(0deg);
  -webkit-transition: 0.2s linear;
  transition: 0.2s linear;
  transition-property: transform, opacity;
  -webkit-transition-property: -webkit-transform, opacity;
  /* Transition differently when swiping */ }
  material-toast material-button {
    color: white; }
  material-toast.capsule {
    border-radius: 24px; }
  material-toast.swipeleft, material-toast.swiperight, material-toast.swipeup, material-toast.swipedown {
    -webkit-transition: 0.15s ease-out;
    transition: 0.15s ease-out; }
  material-toast.ng-enter {
    -webkit-transform: translate3d(0, 100%, 0);
    transform: translate3d(0, 100%, 0);
    opacity: 0; }
    material-toast.ng-enter.top {
      -webkit-transform: translate3d(0, -100%, 0);
      transform: translate3d(0, -100%, 0); }
    material-toast.ng-enter.ng-enter-active {
      -webkit-transform: translate3d(0, 0, 0);
      transform: translate3d(0, 0, 0);
      opacity: 1; }
  material-toast.ng-leave.ng-leave-active {
    opacity: 0;
    -webkit-transform: translate3d(0, 100%, 0);
    transform: translate3d(0, 100%, 0); }
    material-toast.ng-leave.ng-leave-active.top {
      -webkit-transform: translate3d(0, -100%, 0);
      transform: translate3d(0, -100%, 0); }
    material-toast.ng-leave.ng-leave-active.swipeleft {
      -webkit-transform: translate3d(-100%, 0, 0);
      transform: translate3d(-100%, 0, 0); }
    material-toast.ng-leave.ng-leave-active.swiperight {
      -webkit-transform: translate3d(100%, 0, 0);
      transform: translate3d(100%, 0, 0); }

.toast-action {
  line-height: 19px;
  color: #eeff41;
  padding-left: 24px;
  cursor: pointer;
  text-transform: uppercase;
  float: right; }

@media (max-width: 600px) {
  material-toast {
    left: 0;
    right: 0;
    width: 100%;
    max-width: 100%;
    min-width: 0;
    border-radius: 0;
    bottom: 0; }
    material-toast.top {
      bottom: auto;
      top: 0; } }

@media (min-width: 600px) {
  material-toast {
    min-width: 288px;
    /* 
     * When the toast doesn't take up the whole screen,
     * make it rotate when the user swipes it away
     */ }
    material-toast.bottom {
      bottom: 8px; }
    material-toast.left {
      left: 8px; }
    material-toast.right {
      right: 8px; }
    material-toast.top {
      top: 8px; }
    material-toast.ng-leave.ng-leave-active.swipeleft {
      -webkit-transform: translate3d(-100%, 25%, 0) rotateZ(-15deg);
      transform: translate3d(-100%, 25%, 0) rotateZ(-15deg); }
    material-toast.ng-leave.ng-leave-active.swiperight {
      -webkit-transform: translate3d(100%, 25%, 0) rotateZ(15deg);
      transform: translate3d(100%, 25%, 0) rotateZ(15deg); }
    material-toast.ng-leave.ng-leave-active.top.swipeleft {
      -webkit-transform: translate3d(-100%, 0, 0) rotateZ(-15deg);
      transform: translate3d(-100%, 0, 0) rotateZ(-15deg); }
    material-toast.ng-leave.ng-leave-active.top.swiperight {
      -webkit-transform: translate3d(100%, 0, 0) rotateZ(15deg);
      transform: translate3d(100%, 0, 0) rotateZ(15deg); } }

material-toolbar {
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -moz-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-direction: normal;
  -webkit-box-orient: vertical;
  -webkit-flex-direction: column;
  -moz-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column;
  position: relative;
  z-index: 2;
  font-size: 1.3em;
  min-height: 64px;
  width: 100%; }
  material-toolbar.material-tall {
    height: 192px; }
  material-toolbar.material-medium-tall {
    height: 88px; }
    material-toolbar.material-medium-tall .material-toolbar-tools {
      height: 48px; }
  material-toolbar .material-indent {
    margin-left: 64px; }

.material-toolbar-tools {
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -moz-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  -moz-align-items: center;
  align-items: center;
  -webkit-box-direction: normal;
  -webkit-box-orient: horizontal;
  -webkit-flex-direction: row;
  -moz-flex-direction: row;
  -ms-flex-direction: row;
  flex-direction: row;
  width: 100%;
  height: 64px;
  font-size: inherit;
  font-weight: normal;
  padding: 0 10px;
  margin: 0; }
  .material-toolbar-tools > * {
    font-size: inherit;
    margin: 0 8px; }
  .material-toolbar-tools h2, .material-toolbar-tools h3 {
    font-weight: normal; }
  .material-toolbar-tools a {
    color: inherit;
    text-decoration: none; }
  .material-toolbar-tools material-button {
    font-size: 16px; }

@-webkit-keyframes tooltipBackgroundShow {
  0% {
    -webkit-transform: scale(0.2);
    transform: scale(0.2);
    opacity: 0.25; }

  50% {
    opacity: 1; }

  100% {
    -webkit-transform: scale(1);
    transform: scale(1);
    opacity: 1; } }

@keyframes tooltipBackgroundShow {
  0% {
    -webkit-transform: scale(0.2);
    transform: scale(0.2);
    opacity: 0.25; }

  50% {
    opacity: 1; }

  100% {
    -webkit-transform: scale(1);
    transform: scale(1);
    opacity: 1; } }

@-webkit-keyframes tooltipBackgroundHide {
  0% {
    opacity: 1; }

  100% {
    opacity: 0; } }

@keyframes tooltipBackgroundHide {
  0% {
    opacity: 1; }

  100% {
    opacity: 0; } }

material-tooltip {
  position: absolute;
  font-size: 14px;
  z-index: 6;
  overflow: hidden;
  pointer-events: none;
  color: white;
  border-radius: 4px;
  /**
   * Depending on the tooltip's size as a multiple of 32 (set by JS),
   * change the background's animation duration.
   * The larger the tooltip, the less time the background should take to ripple outwards.
   */ }
  material-tooltip[tooltip-direction="bottom"] {
    -webkit-transform: translate3d(0, -30%, 0);
    transform: translate3d(0, -30%, 0);
    margin-top: 8px; }
  material-tooltip[tooltip-direction="top"] {
    -webkit-transform: translate3d(0, 30%, 0);
    transform: translate3d(0, 30%, 0);
    margin-bottom: 8px; }
  material-tooltip .tooltip-background {
    background: #737373;
    position: absolute;
    left: 50%;
    width: 256px;
    height: 256px;
    margin-left: -128px;
    margin-top: -128px;
    border-radius: 256px;
    opacity: 0.25;
    -webkit-transform: scale(0.2);
    transform: scale(0.2); }
  material-tooltip .tooltip-content {
    max-width: 240px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    padding: 8px;
    background: transparent;
    opacity: 0.3;
    -webkit-transition: inherit;
    transition: inherit; }
  material-tooltip.tooltip-show, material-tooltip.tooltip-hide {
    -webkit-transition: 0.2s ease-out;
    transition: 0.2s ease-out;
    transition-property: transform, opacity;
    -webkit-transition-property: -webkit-transform, opacity; }
  material-tooltip.tooltip-show {
    pointer-events: auto;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0); }
    material-tooltip.tooltip-show .tooltip-background {
      -webkit-transform: scale(1);
      transform: scale(1);
      opacity: 1;
      -webkit-animation: tooltipBackgroundShow linear;
      animation: tooltipBackgroundShow linear; }
    material-tooltip.tooltip-show .tooltip-content {
      opacity: 0.99; }
  material-tooltip.tooltip-hide .tooltip-background {
    -webkit-transform: scale(1);
    transform: scale(1);
    opacity: 0;
    -webkit-animation: tooltipBackgroundHide 0.2s linear;
    animation: tooltipBackgroundHide 0.2s linear; }
  material-tooltip[width-32="1"].tooltip-show .tooltip-background {
    animation-duration: 900ms;
    -webkit-animation-duration: 900ms; }
  material-tooltip[width-32="2"].tooltip-show .tooltip-background {
    animation-duration: 800ms;
    -webkit-animation-duration: 800ms; }
  material-tooltip[width-32="3"].tooltip-show .tooltip-background {
    animation-duration: 700ms;
    -webkit-animation-duration: 700ms; }
  material-tooltip[width-32="4"].tooltip-show .tooltip-background {
    animation-duration: 600ms;
    -webkit-animation-duration: 600ms; }
  material-tooltip[width-32="5"].tooltip-show .tooltip-background {
    animation-duration: 500ms;
    -webkit-animation-duration: 500ms; }
  material-tooltip[width-32="6"].tooltip-show .tooltip-background {
    animation-duration: 400ms;
    -webkit-animation-duration: 400ms; }
  material-tooltip[width-32="7"].tooltip-show .tooltip-background {
    animation-duration: 300ms;
    -webkit-animation-duration: 300ms; }
  material-tooltip[width-32="8"].tooltip-show .tooltip-background {
    animation-duration: 200ms;
    -webkit-animation-duration: 200ms; }

material-tabs {
  display: block;
  width: 100%;
  font-weight: 500; }

.tabs-header {
  width: 100%;
  height: 48px;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  position: relative;
  background-color: #4285F4; }

.tab-paginator {
  z-index: 1;
  margin-right: -2px;
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -moz-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  -webkit-justify-content: center;
  -moz-justify-content: center;
  justify-content: center;
  -webkit-box-align: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  -moz-align-items: center;
  align-items: center;
  width: 32px;
  min-height: 100%;
  cursor: pointer;
  background-repeat: no-repeat;
  background-position: center center;
  position: absolute;
  /* TODO Once we have a better way to inline svg images, change this 
   to use svgs correctly */ }
  .tab-paginator.prev {
    left: 0; }
  .tab-paginator.next {
    right: 0; }
  .tab-paginator.prev {
    background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE3LjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPiA8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPiA8c3ZnIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSIyNHB4IiBoZWlnaHQ9IjI0cHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMjQgMjQiIHhtbDpzcGFjZT0icHJlc2VydmUiPiA8ZyBpZD0iSGVhZGVyIj4gPGc+IDxyZWN0IHg9Ii02MTgiIHk9Ii0xMjA4IiBmaWxsPSJub25lIiB3aWR0aD0iMTQwMCIgaGVpZ2h0PSIzNjAwIi8+IDwvZz4gPC9nPiA8ZyBpZD0iTGFiZWwiPiA8L2c+IDxnIGlkPSJJY29uIj4gPGc+IDxwb2x5Z29uIHBvaW50cz0iMTUuNCw3LjQgMTQsNiA4LDEyIDE0LDE4IDE1LjQsMTYuNiAxMC44LDEyIAkJIiBzdHlsZT0iZmlsbDp3aGl0ZTsiLz4gPHJlY3QgZmlsbD0ibm9uZSIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ii8+IDwvZz4gPC9nPiA8ZyBpZD0iR3JpZCIgZGlzcGxheT0ibm9uZSI+IDxnIGRpc3BsYXk9ImlubGluZSI+IDwvZz4gPC9nPiA8L3N2Zz4NCg=='); }
  .tab-paginator.next {
    background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE3LjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPiA8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPiA8c3ZnIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSIyNHB4IiBoZWlnaHQ9IjI0cHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMjQgMjQiIHhtbDpzcGFjZT0icHJlc2VydmUiPiA8ZyBpZD0iSGVhZGVyIj4gPGc+IDxyZWN0IHg9Ii02MTgiIHk9Ii0xMzM2IiBmaWxsPSJub25lIiB3aWR0aD0iMTQwMCIgaGVpZ2h0PSIzNjAwIi8+IDwvZz4gPC9nPiA8ZyBpZD0iTGFiZWwiPiA8L2c+IDxnIGlkPSJJY29uIj4gPGc+IDxwb2x5Z29uIHBvaW50cz0iMTAsNiA4LjYsNy40IDEzLjIsMTIgOC42LDE2LjYgMTAsMTggMTYsMTIgCQkiIHN0eWxlPSJmaWxsOndoaXRlOyIvPiA8cmVjdCBmaWxsPSJub25lIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiLz4gPC9nPiA8L2c+IDxnIGlkPSJHcmlkIiBkaXNwbGF5PSJub25lIj4gPGcgZGlzcGxheT0iaW5saW5lIj4gPC9nPiA8L2c+IDwvc3ZnPg0K'); }

/* If `center` justified, change to left-justify if paginating */
material-tabs[center] .tabs-header:not(.tab-paginating) .tabs-header-items {
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  -webkit-justify-content: center;
  -moz-justify-content: center;
  justify-content: center; }

.tab-paginating .tabs-header-items-container {
  left: 32px;
  right: 32px; }

.tabs-header-items-container {
  overflow: hidden;
  position: absolute;
  left: 0;
  right: 0;
  height: 100%;
  white-space: nowrap;
  font-size: 16px;
  font-weight: 500;
  text-transform: uppercase;
  margin: auto; }
  .tabs-header-items-container .tabs-header-items {
    display: -webkit-box;
    display: -webkit-flex;
    display: -moz-box;
    display: -moz-flex;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    -webkit-transition: -webkit-transform 0.2s linear;
    transition: transform 0.2s linear;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    width: 100%;
    height: 100%; }

.tabs-content {
  overflow: hidden;
  width: 100%; }
  .tabs-content .tab-content {
    height: 100%; }

material-tabs-ink-bar {
  left: 0;
  bottom: 0;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  -webkit-transition: all 0.2s linear;
  transition: all 0.2s linear; }

material-tab {
  -webkit-box-flex: 1;
  -webkit-flex: 1;
  -moz-box-flex: 1;
  -moz-flex: 1;
  -ms-flex: 1;
  flex: 1;
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -moz-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  -webkit-box-align: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  -moz-align-items: center;
  align-items: center;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  -webkit-justify-content: center;
  -moz-justify-content: center;
  justify-content: center;
  position: relative;
  z-index: 0;
  overflow: hidden;
  height: 100%;
  text-align: center;
  cursor: pointer;
  min-width: 96px;
  border: 1px dotted transparent;
  color: #9FC1FB;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none; }
  material-tab.active {
    color: white; }
  material-tab[disabled] {
    pointer-events: none;
    color: #6a6a6a;
    opacity: 0.5;
    cursor: default; }
  material-tab:focus {
    border-color: #111111;
    outline: none; }
  material-tab material-tab-label {
    -webkit-box-flex: 1;
    -webkit-flex: 1;
    -moz-box-flex: 1;
    -moz-flex: 1;
    -ms-flex: 1;
    flex: 1;
    z-index: 100;
    opacity: 1;
    overflow: hidden;
    text-overflow: ellipsis; }
  material-tab .material-ripple-container {
    color: #ffff85; }

shadow {
  box-shadow: 0px 3px 2px rgba(0, 0, 0, 0.2); }

material-list {
  padding: 8px 0px 8px 0px; }
  material-list.with-subheader {
    padding-top: 0px; }

material-item-content {
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -moz-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  -moz-align-items: center;
  align-items: center;
  -webkit-box-direction: normal;
  -webkit-box-orient: horizontal;
  -webkit-flex-direction: row;
  -moz-flex-direction: row;
  -ms-flex-direction: row;
  flex-direction: row;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  position: relative;
  padding: 0px 0px 0px 0px; }

/**
 * The left tile for a list item.
 */
.material-tile-left {
  min-width: 56px;
  margin-right: -16px; }

/**
 * The center content tile for a list item.
 */
.material-tile-content {
  -webkit-box-flex: 1;
  -webkit-flex: 1;
  -moz-box-flex: 1;
  -moz-flex: 1;
  -ms-flex: 1;
  flex: 1;
  padding: 16px;
  text-overflow: ellipsis; }
  .material-tile-content h3 {
    margin: 0 0 3px 0;
    font-weight: 400;
    font-size: 1.1em; }
  .material-tile-content h4 {
    margin: 0 0 3px 0;
    font-weight: 400;
    font-size: 0.9em; }
  .material-tile-content p {
    margin: 0 0 3px 0;
    font-size: 0.75em; }

/**
 * The right tile for a list item.
 */
.material-tile-right {
  padding-right: 0px; }

material-divider {
  display: block;
  border-top: 1px solid rgba(0, 0, 0, 0.12) !important;
  margin: 0; }
  material-divider[inset] {
    margin-left: 80px; }

.material-whiteframe-z1 {
  z-index: 1;
  box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.26); }

.material-whiteframe-z2 {
  z-index: 2;
  box-shadow: 0px 8px 17px rgba(0, 0, 0, 0.2); }

.material-whiteframe-z3 {
  z-index: 3;
  box-shadow: 0px 17px 50px rgba(0, 0, 0, 0.19); }

.material-whiteframe-z4 {
  z-index: 4;
  box-shadow: 0px 16px 28px 0 rgba(0, 0, 0, 0.22); }

.material-whiteframe-z5 {
  z-index: 5;
  box-shadow: 0px 27px 24px 0 rgba(0, 0, 0, 0.2); }

material-linear-progress {
  display: block;
  width: 100%;
  height: 5px; }
  material-linear-progress .container {
    overflow: hidden;
    position: relative;
    height: 5px;
    background-color: #d0d9ff;
    top: 5px;
    -webkit-transform: translate(0, 5px) scale(1, 0);
    transform: translate(0, 5px) scale(1, 0);
    -webkit-transition: all 0.3s linear;
    transition: all 0.3s linear; }
  material-linear-progress .container.ready {
    -webkit-transform: translate(0, 0) scale(1, 1);
    transform: translate(0, 0) scale(1, 1); }
  material-linear-progress .bar {
    height: 5px;
    background-color: #5677fc;
    position: absolute;
    width: 100%; }
  material-linear-progress .bar1, material-linear-progress .bar2 {
    -webkit-transition: all 0.2s linear;
    transition: all 0.2s linear; }
  material-linear-progress[mode=determinate] .bar1 {
    display: none; }
  material-linear-progress[mode=indeterminate] .bar1 {
    -webkit-animation: indeterminate1 4s infinite linear;
    animation: indeterminate1 4s infinite linear; }
  material-linear-progress[mode=indeterminate] .bar2 {
    -webkit-animation: indeterminate2 4s infinite linear;
    animation: indeterminate2 4s infinite linear; }
  material-linear-progress[mode=buffer] .container {
    background-color: transparent; }
  material-linear-progress[mode=buffer] .dashed:before {
    content: "";
    display: block;
    height: 5px;
    width: 100%;
    margin-top: 0px;
    position: absolute;
    background: radial-gradient(#d0d9ff 0%, #d0d9ff 16%, transparent 42%);
    background-color: transparent;
    background-size: 10px 10px;
    background-position: 0px -23px;
    -webkit-animation: buffer 3s infinite linear;
    animation: buffer 3s infinite linear; }
  material-linear-progress[mode=buffer] .bar1 {
    background-color: #d0d9ff; }
  material-linear-progress[mode=query] .bar2 {
    -webkit-animation: query 0.8s infinite cubic-bezier(0.39, 0.575, 0.565, 1);
    animation: query 0.8s infinite cubic-bezier(0.39, 0.575, 0.565, 1); }

@-webkit-keyframes indeterminate1 {
  0% {
    -webkit-transform: translateX(-25%) scale(0.5, 1);
    transform: translateX(-25%) scale(0.5, 1); }

  10% {
    -webkit-transform: translateX(25%) scale(0.5, 1);
    transform: translateX(25%) scale(0.5, 1); }

  19.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  20% {
    -webkit-transform: translateX(-37.5%) scale(0.25, 1);
    transform: translateX(-37.5%) scale(0.25, 1); }

  30% {
    -webkit-transform: translateX(37.5%) scale(0.25, 1);
    transform: translateX(37.5%) scale(0.25, 1); }

  34.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  36.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  37% {
    -webkit-transform: translateX(-37.5%) scale(0.25, 1);
    transform: translateX(-37.5%) scale(0.25, 1); }

  47% {
    -webkit-transform: translateX(20%) scale(0.25, 1);
    transform: translateX(20%) scale(0.25, 1); }

  52% {
    -webkit-transform: translateX(35%) scale(0.05, 1);
    transform: translateX(35%) scale(0.05, 1); }

  55% {
    -webkit-transform: translateX(35%) scale(0.1, 1);
    transform: translateX(35%) scale(0.1, 1); }

  58% {
    -webkit-transform: translateX(50%) scale(0.1, 1);
    transform: translateX(50%) scale(0.1, 1); }

  61.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  69.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  70% {
    -webkit-transform: translateX(-37.5%) scale(0.25, 1);
    transform: translateX(-37.5%) scale(0.25, 1); }

  80% {
    -webkit-transform: translateX(20%) scale(0.25, 1);
    transform: translateX(20%) scale(0.25, 1); }

  85% {
    -webkit-transform: translateX(35%) scale(0.05, 1);
    transform: translateX(35%) scale(0.05, 1); }

  88% {
    -webkit-transform: translateX(35%) scale(0.1, 1);
    transform: translateX(35%) scale(0.1, 1); }

  91% {
    -webkit-transform: translateX(50%) scale(0.1, 1);
    transform: translateX(50%) scale(0.1, 1); }

  92.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  93% {
    -webkit-transform: translateX(-50%) scale(0, 1);
    transform: translateX(-50%) scale(0, 1); }

  100% {
    -webkit-transform: translateX(-25%) scale(0.5, 1);
    transform: translateX(-25%) scale(0.5, 1); } }

@keyframes indeterminate1 {
  0% {
    -webkit-transform: translateX(-25%) scale(0.5, 1);
    transform: translateX(-25%) scale(0.5, 1); }

  10% {
    -webkit-transform: translateX(25%) scale(0.5, 1);
    transform: translateX(25%) scale(0.5, 1); }

  19.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  20% {
    -webkit-transform: translateX(-37.5%) scale(0.25, 1);
    transform: translateX(-37.5%) scale(0.25, 1); }

  30% {
    -webkit-transform: translateX(37.5%) scale(0.25, 1);
    transform: translateX(37.5%) scale(0.25, 1); }

  34.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  36.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  37% {
    -webkit-transform: translateX(-37.5%) scale(0.25, 1);
    transform: translateX(-37.5%) scale(0.25, 1); }

  47% {
    -webkit-transform: translateX(20%) scale(0.25, 1);
    transform: translateX(20%) scale(0.25, 1); }

  52% {
    -webkit-transform: translateX(35%) scale(0.05, 1);
    transform: translateX(35%) scale(0.05, 1); }

  55% {
    -webkit-transform: translateX(35%) scale(0.1, 1);
    transform: translateX(35%) scale(0.1, 1); }

  58% {
    -webkit-transform: translateX(50%) scale(0.1, 1);
    transform: translateX(50%) scale(0.1, 1); }

  61.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  69.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  70% {
    -webkit-transform: translateX(-37.5%) scale(0.25, 1);
    transform: translateX(-37.5%) scale(0.25, 1); }

  80% {
    -webkit-transform: translateX(20%) scale(0.25, 1);
    transform: translateX(20%) scale(0.25, 1); }

  85% {
    -webkit-transform: translateX(35%) scale(0.05, 1);
    transform: translateX(35%) scale(0.05, 1); }

  88% {
    -webkit-transform: translateX(35%) scale(0.1, 1);
    transform: translateX(35%) scale(0.1, 1); }

  91% {
    -webkit-transform: translateX(50%) scale(0.1, 1);
    transform: translateX(50%) scale(0.1, 1); }

  92.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  93% {
    -webkit-transform: translateX(-50%) scale(0, 1);
    transform: translateX(-50%) scale(0, 1); }

  100% {
    -webkit-transform: translateX(-25%) scale(0.5, 1);
    transform: translateX(-25%) scale(0.5, 1); } }

@-webkit-keyframes indeterminate2 {
  0% {
    -webkit-transform: translateX(-50%) scale(0, 1);
    transform: translateX(-50%) scale(0, 1); }

  25.99% {
    -webkit-transform: translateX(-50%) scale(0, 1);
    transform: translateX(-50%) scale(0, 1); }

  28% {
    -webkit-transform: translateX(-37.5%) scale(0.25, 1);
    transform: translateX(-37.5%) scale(0.25, 1); }

  38% {
    -webkit-transform: translateX(37.5%) scale(0.25, 1);
    transform: translateX(37.5%) scale(0.25, 1); }

  42.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  46.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  49.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  50% {
    -webkit-transform: translateX(-50%) scale(0, 1);
    transform: translateX(-50%) scale(0, 1); }

  60% {
    -webkit-transform: translateX(-25%) scale(0.5, 1);
    transform: translateX(-25%) scale(0.5, 1); }

  70% {
    -webkit-transform: translateX(25%) scale(0.5, 1);
    transform: translateX(25%) scale(0.5, 1); }

  79.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); } }

@keyframes indeterminate2 {
  0% {
    -webkit-transform: translateX(-50%) scale(0, 1);
    transform: translateX(-50%) scale(0, 1); }

  25.99% {
    -webkit-transform: translateX(-50%) scale(0, 1);
    transform: translateX(-50%) scale(0, 1); }

  28% {
    -webkit-transform: translateX(-37.5%) scale(0.25, 1);
    transform: translateX(-37.5%) scale(0.25, 1); }

  38% {
    -webkit-transform: translateX(37.5%) scale(0.25, 1);
    transform: translateX(37.5%) scale(0.25, 1); }

  42.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  46.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  49.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); }

  50% {
    -webkit-transform: translateX(-50%) scale(0, 1);
    transform: translateX(-50%) scale(0, 1); }

  60% {
    -webkit-transform: translateX(-25%) scale(0.5, 1);
    transform: translateX(-25%) scale(0.5, 1); }

  70% {
    -webkit-transform: translateX(25%) scale(0.5, 1);
    transform: translateX(25%) scale(0.5, 1); }

  79.99% {
    -webkit-transform: translateX(50%) scale(0, 1);
    transform: translateX(50%) scale(0, 1); } }

@-webkit-keyframes query {
  0% {
    opacity: 1;
    -webkit-transform: translateX(35%) scale(0.3, 1);
    transform: translateX(35%) scale(0.3, 1); }

  100% {
    opacity: 0;
    -webkit-transform: translateX(-50%) scale(0, 1);
    transform: translateX(-50%) scale(0, 1); } }

@keyframes query {
  0% {
    opacity: 1;
    -webkit-transform: translateX(35%) scale(0.3, 1);
    transform: translateX(35%) scale(0.3, 1); }

  100% {
    opacity: 0;
    -webkit-transform: translateX(-50%) scale(0, 1);
    transform: translateX(-50%) scale(0, 1); } }

@-webkit-keyframes buffer {
  0% {
    opacity: 1;
    background-position: 0px -23px; }

  50% {
    opacity: 0; }

  100% {
    opacity: 1;
    background-position: -200px -23px; } }

@keyframes buffer {
  0% {
    opacity: 1;
    background-position: 0px -23px; }

  50% {
    opacity: 0; }

  100% {
    opacity: 1;
    background-position: -200px -23px; } }

material-circular-progress {
  display: block;
  width: 54px;
  height: 54px;
  background-color: transparent;
  border-radius: 50%;
  padding: 3px; }
  material-circular-progress .wrapper1, material-circular-progress .wrapper2 {
    width: 48px;
    height: 48px;
    position: absolute;
    border-radius: 50%; }
  material-circular-progress .circle .mask, material-circular-progress .circle .fill, material-circular-progress .circle .shadow {
    width: 48px;
    height: 48px;
    position: absolute;
    border-radius: 50%; }
  material-circular-progress .circle .mask, material-circular-progress .circle .fill {
    -webkit-backface-visibility: hidden;
    transition: -webkit-transform 0.3s;
    transition: -ms-transform 0.3s;
    transition: transform 0.3s; }
  material-circular-progress .circle .mask {
    clip: rect(0px, 48px, 48px, 24px); }
    material-circular-progress .circle .mask .fill {
      clip: rect(0px, 24px, 48px, 0px);
      background-color: #5677fc; }
  material-circular-progress .inset {
    width: 36px;
    height: 36px;
    position: absolute;
    margin-left: 6px;
    margin-top: 6px;
    background-color: white;
    border-radius: 50%; }
  material-circular-progress[mode=indeterminate] .wrapper1, material-circular-progress[mode=indeterminate] .wrapper2 {
    -ms-transform-origin: 50% 50%;
    /* IE 9 */
    webkit-transform-origin: 50% 50%;
    /* Chrome, Safari, Opera */
    transform-origin: 50% 50%; }
  material-circular-progress[mode=indeterminate] .wrapper1 {
    -webkit-animation: indeterminate_rotate1 3s infinite linear;
    animation: indeterminate_rotate1 3s infinite linear; }
  material-circular-progress[mode=indeterminate] .wrapper2 {
    -webkit-animation: indeterminate_rotate2 1.5s infinite linear;
    animation: indeterminate_rotate2 1.5s infinite linear; }
  material-circular-progress[mode=indeterminate] .fill, material-circular-progress[mode=indeterminate] .mask.full {
    -webkit-animation: indeterminate_size_fill 1.5s infinite linear;
    animation: indeterminate_size_fill 1.5s infinite linear; }
  material-circular-progress[mode=indeterminate] .fill.fix {
    -webkit-animation: indeterminate_size_fix 1.5s infinite linear;
    animation: indeterminate_size_fix 1.5s infinite linear; }

@-webkit-keyframes indeterminate_rotate1 {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg); }

  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg); } }

@keyframes indeterminate_rotate1 {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg); }

  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg); } }

@-webkit-keyframes indeterminate_rotate2 {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg); }

  70% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg); }

  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg); } }

@keyframes indeterminate_rotate2 {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg); }

  70% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg); }

  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg); } }

@-webkit-keyframes indeterminate_size_fill {
  0% {
    -webkit-transform: rotate(5deg);
    transform: rotate(5deg); }

  10% {
    -webkit-transform: rotate(5deg);
    transform: rotate(5deg); }

  50% {
    -webkit-transform: rotate(135deg);
    transform: rotate(135deg); }

  70% {
    -webkit-transform: rotate(135deg);
    transform: rotate(135deg); }

  100% {
    -webkit-transform: rotate(5deg);
    transform: rotate(5deg); } }

@keyframes indeterminate_size_fill {
  0% {
    -webkit-transform: rotate(5deg);
    transform: rotate(5deg); }

  10% {
    -webkit-transform: rotate(5deg);
    transform: rotate(5deg); }

  50% {
    -webkit-transform: rotate(135deg);
    transform: rotate(135deg); }

  70% {
    -webkit-transform: rotate(135deg);
    transform: rotate(135deg); }

  100% {
    -webkit-transform: rotate(5deg);
    transform: rotate(5deg); } }

@-webkit-keyframes indeterminate_size_fix {
  0% {
    -webkit-transform: rotate(10deg);
    transform: rotate(10deg); }

  10% {
    -webkit-transform: rotate(10deg);
    transform: rotate(10deg); }

  50% {
    -webkit-transform: rotate(270deg);
    transform: rotate(270deg); }

  70% {
    -webkit-transform: rotate(270deg);
    transform: rotate(270deg); }

  100% {
    -webkit-transform: rotate(10deg);
    transform: rotate(10deg); } }

@keyframes indeterminate_size_fix {
  0% {
    -webkit-transform: rotate(10deg);
    transform: rotate(10deg); }

  10% {
    -webkit-transform: rotate(10deg);
    transform: rotate(10deg); }

  50% {
    -webkit-transform: rotate(270deg);
    transform: rotate(270deg); }

  70% {
    -webkit-transform: rotate(270deg);
    transform: rotate(270deg); }

  100% {
    -webkit-transform: rotate(10deg);
    transform: rotate(10deg); } }