/**
 * @license
 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 */
// @version 0.7.3
"undefined"==typeof WeakMap&&!function(){var e=Object.defineProperty,t=Date.now()%1e9,r=function(){this.name="__st"+(1e9*Math.random()>>>0)+(t++ +"__")};r.prototype={set:function(t,r){var i=t[this.name];return i&&i[0]===t?i[1]=r:e(t,this.name,{value:[t,r],writable:!0}),this},get:function(e){var t;return(t=e[this.name])&&t[0]===e?t[1]:void 0},"delete":function(e){var t=e[this.name];return t&&t[0]===e?(t[0]=t[1]=void 0,!0):!1},has:function(e){var t=e[this.name];return t?t[0]===e:!1}},window.WeakMap=r}(),function(e){function t(e){O.push(e),N||(N=!0,b(i))}function r(e){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(e)||e}function i(){N=!1;var e=O;O=[],e.sort(function(e,t){return e.uid_-t.uid_});var t=!1;e.forEach(function(e){var r=e.takeRecords();n(e),r.length&&(e.callback_(r,e),t=!0)}),t&&i()}function n(e){e.nodes_.forEach(function(t){var r=p.get(t);r&&r.forEach(function(t){t.observer===e&&t.removeTransientObservers()})})}function a(e,t){for(var r=e;r;r=r.parentNode){var i=p.get(r);if(i)for(var n=0;n<i.length;n++){var a=i[n],s=a.options;if(r===e||s.subtree){var o=t(s);o&&a.enqueue(o)}}}}function s(e){this.callback_=e,this.nodes_=[],this.records_=[],this.uid_=++M}function o(e,t){this.type=e,this.target=t,this.addedNodes=[],this.removedNodes=[],this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function d(e){var t=new o(e.type,e.target);return t.addedNodes=e.addedNodes.slice(),t.removedNodes=e.removedNodes.slice(),t.previousSibling=e.previousSibling,t.nextSibling=e.nextSibling,t.attributeName=e.attributeName,t.attributeNamespace=e.attributeNamespace,t.oldValue=e.oldValue,t}function u(e,t){return D=new o(e,t)}function h(e){return w?w:(w=d(D),w.oldValue=e,w)}function c(){D=w=void 0}function v(e){return e===w||e===D}function l(e,t){return e===t?e:w&&v(e)?w:null}function f(e,t,r){this.observer=e,this.target=t,this.options=r,this.transientObservedNodes=[]}var b,p=new WeakMap;if(/Trident|Edge/.test(navigator.userAgent))b=setTimeout;else if(window.setImmediate)b=window.setImmediate;else{var g=[],m=String(Math.random());window.addEventListener("message",function(e){if(e.data===m){var t=g;g=[],t.forEach(function(e){e()})}}),b=function(e){g.push(e),window.postMessage(m,"*")}}var N=!1,O=[],M=0;s.prototype={observe:function(e,t){if(e=r(e),!t.childList&&!t.attributes&&!t.characterData||t.attributeOldValue&&!t.attributes||t.attributeFilter&&t.attributeFilter.length&&!t.attributes||t.characterDataOldValue&&!t.characterData)throw new SyntaxError;var i=p.get(e);i||p.set(e,i=[]);for(var n,a=0;a<i.length;a++)if(i[a].observer===this){n=i[a],n.removeListeners(),n.options=t;break}n||(n=new f(this,e,t),i.push(n),this.nodes_.push(e)),n.addListeners()},disconnect:function(){this.nodes_.forEach(function(e){for(var t=p.get(e),r=0;r<t.length;r++){var i=t[r];if(i.observer===this){i.removeListeners(),t.splice(r,1);break}}},this),this.records_=[]},takeRecords:function(){var e=this.records_;return this.records_=[],e}};var D,w;f.prototype={enqueue:function(e){var r=this.observer.records_,i=r.length;if(r.length>0){var n=r[i-1],a=l(n,e);if(a)return void(r[i-1]=a)}else t(this.observer);r[i]=e},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(e){var t=this.options;t.attributes&&e.addEventListener("DOMAttrModified",this,!0),t.characterData&&e.addEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.addEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(e){var t=this.options;t.attributes&&e.removeEventListener("DOMAttrModified",this,!0),t.characterData&&e.removeEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.removeEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(e){if(e!==this.target){this.addListeners_(e),this.transientObservedNodes.push(e);var t=p.get(e);t||p.set(e,t=[]),t.push(this)}},removeTransientObservers:function(){var e=this.transientObservedNodes;this.transientObservedNodes=[],e.forEach(function(e){this.removeListeners_(e);for(var t=p.get(e),r=0;r<t.length;r++)if(t[r]===this){t.splice(r,1);break}},this)},handleEvent:function(e){switch(e.stopImmediatePropagation(),e.type){case"DOMAttrModified":var t=e.attrName,r=e.relatedNode.namespaceURI,i=e.target,n=new u("attributes",i);n.attributeName=t,n.attributeNamespace=r;var s=e.attrChange===MutationEvent.ADDITION?null:e.prevValue;a(i,function(e){return!e.attributes||e.attributeFilter&&e.attributeFilter.length&&-1===e.attributeFilter.indexOf(t)&&-1===e.attributeFilter.indexOf(r)?void 0:e.attributeOldValue?h(s):n});break;case"DOMCharacterDataModified":var i=e.target,n=u("characterData",i),s=e.prevValue;a(i,function(e){return e.characterData?e.characterDataOldValue?h(s):n:void 0});break;case"DOMNodeRemoved":this.addTransientObserver(e.target);case"DOMNodeInserted":var o,d,v=e.target;"DOMNodeInserted"===e.type?(o=[v],d=[]):(o=[],d=[v]);var l=v.previousSibling,f=v.nextSibling,n=u("childList",e.target.parentNode);n.addedNodes=o,n.removedNodes=d,n.previousSibling=l,n.nextSibling=f,a(e.relatedNode,function(e){return e.childList?n:void 0})}c()}},e.JsMutationObserver=s,e.MutationObserver||(e.MutationObserver=s)}(this);