text:
// @version 0.5.5
window.WebComponents = window.WebComponents || {};

(function (scope) {
    var flags = scope.flags || {};
    var file = "webcomponents.js";
    var script = document.querySelector('script[src*="' + file + '"]');
    if (!flags.noOpts) {
        location.search.slice(1).split("&").forEach(function (o) {
            o = o.split("=");
            o[0] && (flags[o[0]] = o[1] || true);
        });
        if (script) {
            for (var i = 0, a; a = script.attributes[i]; i++) {
                if (a.name !== "src") {
                    flags[a.name] = a.value || true;
                }
            }
        }
        if (flags.log) {
            var parts = flags.log.split(",");
            flags.log = {};
            parts.forEach(function (f) {
                flags.log[f] = true;
            });
        } else {
            flags.log = {};
        }
    }
    flags.shadow = flags.shadow || flags.shadowdom || flags.polyfill;
    if (flags.shadow === "native") {
        flags.shadow = false;
    } else {
        flags.shadow = flags.shadow || !HTMLElement.prototype.createShadowRoot;
    }
    if (flags.register) {
        window.CustomElements = window.CustomElements || {
                flags: {}
            };
        window.CustomElements.flags.register = flags.register;
    }
    scope.flags = flags;
})(WebComponents);

if (WebComponents.flags.shadow) {
    if (typeof WeakMap === "undefined") {
        (function () {
            var defineProperty = Object.defineProperty;
            var counter = Date.now() % 1e9;
            var WeakMap = function () {
                this.name = "__st" + (Math.random() * 1e9 >>> 0) + (counter++ + "__");
            };
            WeakMap.prototype = {
                set: function (key, value) {
                    var entry = key[this.name];
                    if (entry && entry[0] === key) entry[1] = value; else defineProperty(key, this.name, {
                        value: [key, value],
                        writable: true
                    });
                    return this;
                },
                get: function (key) {
                    var entry;
                    return (entry = key[this.name]) && entry[0] === key ? entry[1] : undefined;
                },
                "delete": function (key) {
                    var entry = key[this.name];
                    if (!entry || entry[0] !== key) return false;
                    entry[0] = entry[1] = undefined;
                    return true;
                },
                has: function (key) {
                    var entry = key[this.name];
                    if (!entry) return false;
                    return entry[0] === key;
                }
            };
            window.WeakMap = WeakMap;
        })();
    }
    window.ShadowDOMPolyfill = {};
    (function (scope) {
        "use strict";
        var constructorTable = new WeakMap();
        var nativePrototypeTable = new WeakMap();
        var wrappers = Object.create(null);

        function detectEval() {
            if (typeof chrome !== "undefined" && chrome.app && chrome.app.runtime) {
                return false;
            }
            if (navigator.getDeviceStorage) {
                return false;
            }
            try {
                var f = new Function("return true;");
                return f();
            } catch (ex) {
                return false;
            }
        }

        var hasEval = detectEval();

        function assert(b) {
            if (!b) throw new Error("Assertion failed");
        }

        var defineProperty = Object.defineProperty;
        var getOwnPropertyNames = Object.getOwnPropertyNames;
        var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;

        function mixin(to, from) {
            var names = getOwnPropertyNames(from);
            for (var i = 0; i < names.length; i++) {
                var name = names[i];
                defineProperty(to, name, getOwnPropertyDescriptor(from, name));
            }
            return to;
        }

        function mixinStatics(to, from) {
            var names = getOwnPropertyNames(from);
            for (var i = 0; i < names.length; i++) {
                var name = names[i];
                switch (name) {
                    case "arguments":
                    case "caller":
                    case "length":
                    case "name":
                    case "prototype":
                    case "toString":
                        continue;
                }
                defineProperty(to, name, getOwnPropertyDescriptor(from, name));
            }
            return to;
        }

        function oneOf(object, propertyNames) {
            for (var i = 0; i < propertyNames.length; i++) {
                if (propertyNames[i] in object) return propertyNames[i];
            }
        }

        var nonEnumerableDataDescriptor = {
            value: undefined,
            configurable: true,
            enumerable: false,
            writable: true
        };

        function defineNonEnumerableDataProperty(object, name, value) {
            nonEnumerableDataDescriptor.value = value;
            defineProperty(object, name, nonEnumerableDataDescriptor);
        }

        getOwnPropertyNames(window);
        function getWrapperConstructor(node) {
            var nativePrototype = node.__proto__ || Object.getPrototypeOf(node);
            if (isFirefox) {
                try {
                    getOwnPropertyNames(nativePrototype);
                } catch (error) {
                    nativePrototype = nativePrototype.__proto__;
                }
            }
            var wrapperConstructor = constructorTable.get(nativePrototype);
            if (wrapperConstructor) return wrapperConstructor;
            var parentWrapperConstructor = getWrapperConstructor(nativePrototype);
            var GeneratedWrapper = createWrapperConstructor(parentWrapperConstructor);
            registerInternal(nativePrototype, GeneratedWrapper, node);
            return GeneratedWrapper;
        }

        function addForwardingProperties(nativePrototype, wrapperPrototype) {
            installProperty(nativePrototype, wrapperPrototype, true);
        }

        function registerInstanceProperties(wrapperPrototype, instanceObject) {
            installProperty(instanceObject, wrapperPrototype, false);
        }

        var isFirefox = /Firefox/.test(navigator.userAgent);
        var dummyDescriptor = {
            get: function () {
            },
            set: function (v) {
            },
            configurable: true,
            enumerable: true
        };

        function isEventHandlerName(name) {
            return /^on[a-z]+$/.test(name);
        }

        function isIdentifierName(name) {
            return /^\w[a-zA-Z_0-9]*$/.test(name);
        }

        function getGetter(name) {
            return hasEval && isIdentifierName(name) ? new Function("return this.__impl4cf1e782hg__." + name) : function () {
                return this.__impl4cf1e782hg__[name];
            };
        }

        function getSetter(name) {
            return hasEval && isIdentifierName(name) ? new Function("v", "this.__impl4cf1e782hg__." + name + " = v") : function (v) {
                this.__impl4cf1e782hg__[name] = v;
            };
        }

        function getMethod(name) {
            return hasEval && isIdentifierName(name) ? new Function("return this.__impl4cf1e782hg__." + name + ".apply(this.__impl4cf1e782hg__, arguments)") : function () {
                return this.__impl4cf1e782hg__[name].apply(this.__impl4cf1e782hg__, arguments);
            };
        }

        function getDescriptor(source, name) {
            try {
                return Object.getOwnPropertyDescriptor(source, name);
            } catch (ex) {
                return dummyDescriptor;
            }
        }

        var isBrokenSafari = function () {
            var descr = Object.getOwnPropertyDescriptor(Node.prototype, "nodeType");
            return descr && !descr.get && !descr.set;
        }();

        function installProperty(source, target, allowMethod, opt_blacklist) {
            var names = getOwnPropertyNames(source);
            for (var i = 0; i < names.length; i++) {
                var name = names[i];
                if (name === "polymerBlackList_") continue;
                if (name in target) continue;
                if (source.polymerBlackList_ && source.polymerBlackList_[name]) continue;
                if (isFirefox) {
                    source.__lookupGetter__(name);
                }
                var descriptor = getDescriptor(source, name);
                var getter, setter;
                if (allowMethod && typeof descriptor.value === "function") {
                    target[name] = getMethod(name);
                    continue;
                }
                var isEvent = isEventHandlerName(name);
                if (isEvent) getter = scope.getEventHandlerGetter(name); else getter = getGetter(name);
                if (descriptor.writable || descriptor.set || isBrokenSafari) {
                    if (isEvent) setter = scope.getEventHandlerSetter(name); else setter = getSetter(name);
                }
                var configurable = isBrokenSafari || descriptor.configurable;
                defineProperty(target, name, {
                    get: getter,
                    set: setter,
                    configurable: configurable,
                    enumerable: descriptor.enumerable
                });
            }
        }

        function register(nativeConstructor, wrapperConstructor, opt_instance) {
            var nativePrototype = nativeConstructor.prototype;
            registerInternal(nativePrototype, wrapperConstructor, opt_instance);
            mixinStatics(wrapperConstructor, nativeConstructor);
        }

        function registerInternal(nativePrototype, wrapperConstructor, opt_instance) {
            var wrapperPrototype = wrapperConstructor.prototype;
            assert(constructorTable.get(nativePrototype) === undefined);
            constructorTable.set(nativePrototype, wrapperConstructor);
            nativePrototypeTable.set(wrapperPrototype, nativePrototype);
            addForwardingProperties(nativePrototype, wrapperPrototype);
            if (opt_instance) registerInstanceProperties(wrapperPrototype, opt_instance);
            defineNonEnumerableDataProperty(wrapperPrototype, "constructor", wrapperConstructor);
            wrapperConstructor.prototype = wrapperPrototype;
        }

        function isWrapperFor(wrapperConstructor, nativeConstructor) {
            return constructorTable.get(nativeConstructor.prototype) === wrapperConstructor;
        }

        function registerObject(object) {
            var nativePrototype = Object.getPrototypeOf(object);
            var superWrapperConstructor = getWrapperConstructor(nativePrototype);
            var GeneratedWrapper = createWrapperConstructor(superWrapperConstructor);
            registerInternal(nativePrototype, GeneratedWrapper, object);
            return GeneratedWrapper;
        }

        function createWrapperConstructor(superWrapperConstructor) {
            function GeneratedWrapper(node) {
                superWrapperConstructor.call(this, node);
            }

            var p = Object.create(superWrapperConstructor.prototype);
            p.constructor = GeneratedWrapper;
            GeneratedWrapper.prototype = p;
            return GeneratedWrapper;
        }

        function isWrapper(object) {
            return object && object.__impl4cf1e782hg__;
        }

        function isNative(object) {
            return !isWrapper(object);
        }

        function wrap(impl) {
            if (impl === null) return null;
            assert(isNative(impl));
            return impl.__wrapper8e3dd93a60__ || (impl.__wrapper8e3dd93a60__ = new (getWrapperConstructor(impl))(impl));
        }

        function unwrap(wrapper) {
            if (wrapper === null) return null;
            assert(isWrapper(wrapper));
            return wrapper.__impl4cf1e782hg__;
        }

        function unsafeUnwrap(wrapper) {
            return wrapper.__impl4cf1e782hg__;
        }

        function setWrapper(impl, wrapper) {
            wrapper.__impl4cf1e782hg__ = impl;
            impl.__wrapper8e3dd93a60__ = wrapper;
        }

        function unwrapIfNeeded(object) {
            return object && isWrapper(object) ? unwrap(object) : object;
        }

        function wrapIfNeeded(object) {
            return object && !isWrapper(object) ? wrap(object) : object;
        }

        function rewrap(node, wrapper) {
            if (wrapper === null) return;
            assert(isNative(node));
            assert(wrapper === undefined || isWrapper(wrapper));
            node.__wrapper8e3dd93a60__ = wrapper;
        }

        var getterDescriptor = {
            get: undefined,
            configurable: true,
            enumerable: true
        };

        function defineGetter(constructor, name, getter) {
            getterDescriptor.get = getter;
            defineProperty(constructor.prototype, name, getterDescriptor);
        }

        function defineWrapGetter(constructor, name) {
            defineGetter(constructor, name, function () {
                return wrap(this.__impl4cf1e782hg__[name]);
            });
        }

        function forwardMethodsToWrapper(constructors, names) {
            constructors.forEach(function (constructor) {
                names.forEach(function (name) {
                    constructor.prototype[name] = function () {
                        var w = wrapIfNeeded(this);
                        return w[name].apply(w, arguments);
                    };
                });
            });
        }

        scope.assert = assert;
        scope.constructorTable = constructorTable;
        scope.defineGetter = defineGetter;
        scope.defineWrapGetter = defineWrapGetter;
        scope.forwardMethodsToWrapper = forwardMethodsToWrapper;
        scope.isWrapper = isWrapper;
        scope.isWrapperFor = isWrapperFor;
        scope.mixin = mixin;
        scope.nativePrototypeTable = nativePrototypeTable;
        scope.oneOf = oneOf;
        scope.registerObject = registerObject;
        scope.registerWrapper = register;
        scope.rewrap = rewrap;
        scope.setWrapper = setWrapper;
        scope.unsafeUnwrap = unsafeUnwrap;
        scope.unwrap = unwrap;
        scope.unwrapIfNeeded = unwrapIfNeeded;
        scope.wrap = wrap;
        scope.wrapIfNeeded = wrapIfNeeded;
        scope.wrappers = wrappers;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        function newSplice(index, removed, addedCount) {
            return {
                index: index,
                removed: removed,
                addedCount: addedCount
            };
        }

        var EDIT_LEAVE = 0;
        var EDIT_UPDATE = 1;
        var EDIT_ADD = 2;
        var EDIT_DELETE = 3;

        function ArraySplice() {
        }

        ArraySplice.prototype = {
            calcEditDistances: function (current, currentStart, currentEnd, old, oldStart, oldEnd) {
                var rowCount = oldEnd - oldStart + 1;
                var columnCount = currentEnd - currentStart + 1;
                var distances = new Array(rowCount);
                for (var i = 0; i < rowCount; i++) {
                    distances[i] = new Array(columnCount);
                    distances[i][0] = i;
                }
                for (var j = 0; j < columnCount; j++) distances[0][j] = j;
                for (var i = 1; i < rowCount; i++) {
                    for (var j = 1; j < columnCount; j++) {
                        if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1])) distances[i][j] = distances[i - 1][j - 1]; else {
                            var north = distances[i - 1][j] + 1;
                            var west = distances[i][j - 1] + 1;
                            distances[i][j] = north < west ? north : west;
                        }
                    }
                }
                return distances;
            },
            spliceOperationsFromEditDistances: function (distances) {
                var i = distances.length - 1;
                var j = distances[0].length - 1;
                var current = distances[i][j];
                var edits = [];
                while (i > 0 || j > 0) {
                    if (i == 0) {
                        edits.push(EDIT_ADD);
                        j--;
                        continue;
                    }
                    if (j == 0) {
                        edits.push(EDIT_DELETE);
                        i--;
                        continue;
                    }
                    var northWest = distances[i - 1][j - 1];
                    var west = distances[i - 1][j];
                    var north = distances[i][j - 1];
                    var min;
                    if (west < north) min = west < northWest ? west : northWest; else min = north < northWest ? north : northWest;
                    if (min == northWest) {
                        if (northWest == current) {
                            edits.push(EDIT_LEAVE);
                        } else {
                            edits.push(EDIT_UPDATE);
                            current = northWest;
                        }
                        i--;
                        j--;
                    } else if (min == west) {
                        edits.push(EDIT_DELETE);
                        i--;
                        current = west;
                    } else {
                        edits.push(EDIT_ADD);
                        j--;
                        current = north;
                    }
                }
                edits.reverse();
                return edits;
            },
            calcSplices: function (current, currentStart, currentEnd, old, oldStart, oldEnd) {
                var prefixCount = 0;
                var suffixCount = 0;
                var minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart);
                if (currentStart == 0 && oldStart == 0) prefixCount = this.sharedPrefix(current, old, minLength);
                if (currentEnd == current.length && oldEnd == old.length) suffixCount = this.sharedSuffix(current, old, minLength - prefixCount);
                currentStart += prefixCount;
                oldStart += prefixCount;
                currentEnd -= suffixCount;
                oldEnd -= suffixCount;
                if (currentEnd - currentStart == 0 && oldEnd - oldStart == 0) return [];
                if (currentStart == currentEnd) {
                    var splice = newSplice(currentStart, [], 0);
                    while (oldStart < oldEnd) splice.removed.push(old[oldStart++]);
                    return [splice];
                } else if (oldStart == oldEnd) return [newSplice(currentStart, [], currentEnd - currentStart)];
                var ops = this.spliceOperationsFromEditDistances(this.calcEditDistances(current, currentStart, currentEnd, old, oldStart, oldEnd));
                var splice = undefined;
                var splices = [];
                var index = currentStart;
                var oldIndex = oldStart;
                for (var i = 0; i < ops.length; i++) {
                    switch (ops[i]) {
                        case EDIT_LEAVE:
                            if (splice) {
                                splices.push(splice);
                                splice = undefined;
                            }
                            index++;
                            oldIndex++;
                            break;

                        case EDIT_UPDATE:
                            if (!splice) splice = newSplice(index, [], 0);
                            splice.addedCount++;
                            index++;
                            splice.removed.push(old[oldIndex]);
                            oldIndex++;
                            break;

                        case EDIT_ADD:
                            if (!splice) splice = newSplice(index, [], 0);
                            splice.addedCount++;
                            index++;
                            break;

                        case EDIT_DELETE:
                            if (!splice) splice = newSplice(index, [], 0);
                            splice.removed.push(old[oldIndex]);
                            oldIndex++;
                            break;
                    }
                }
                if (splice) {
                    splices.push(splice);
                }
                return splices;
            },
            sharedPrefix: function (current, old, searchLength) {
                for (var i = 0; i < searchLength; i++) if (!this.equals(current[i], old[i])) return i;
                return searchLength;
            },
            sharedSuffix: function (current, old, searchLength) {
                var index1 = current.length;
                var index2 = old.length;
                var count = 0;
                while (count < searchLength && this.equals(current[--index1], old[--index2])) count++;
                return count;
            },
            calculateSplices: function (current, previous) {
                return this.calcSplices(current, 0, current.length, previous, 0, previous.length);
            },
            equals: function (currentValue, previousValue) {
                return currentValue === previousValue;
            }
        };
        scope.ArraySplice = ArraySplice;
    })(window.ShadowDOMPolyfill);
    (function (context) {
        "use strict";
        var OriginalMutationObserver = window.MutationObserver;
        var callbacks = [];
        var pending = false;
        var timerFunc;

        function handle() {
            pending = false;
            var copies = callbacks.slice(0);
            callbacks = [];
            for (var i = 0; i < copies.length; i++) {
                (0, copies[i])();
            }
        }

        if (OriginalMutationObserver) {
            var counter = 1;
            var observer = new OriginalMutationObserver(handle);
            var textNode = document.createTextNode(counter);
            observer.observe(textNode, {
                characterData: true
            });
            timerFunc = function () {
                counter = (counter + 1) % 2;
                textNode.data = counter;
            };
        } else {
            timerFunc = window.setTimeout;
        }
        function setEndOfMicrotask(func) {
            callbacks.push(func);
            if (pending) return;
            pending = true;
            timerFunc(handle, 0);
        }

        context.setEndOfMicrotask = setEndOfMicrotask;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var setEndOfMicrotask = scope.setEndOfMicrotask;
        var wrapIfNeeded = scope.wrapIfNeeded;
        var wrappers = scope.wrappers;
        var registrationsTable = new WeakMap();
        var globalMutationObservers = [];
        var isScheduled = false;

        function scheduleCallback(observer) {
            if (observer.scheduled_) return;
            observer.scheduled_ = true;
            globalMutationObservers.push(observer);
            if (isScheduled) return;
            setEndOfMicrotask(notifyObservers);
            isScheduled = true;
        }

        function notifyObservers() {
            isScheduled = false;
            while (globalMutationObservers.length) {
                var notifyList = globalMutationObservers;
                globalMutationObservers = [];
                notifyList.sort(function (x, y) {
                    return x.uid_ - y.uid_;
                });
                for (var i = 0; i < notifyList.length; i++) {
                    var mo = notifyList[i];
                    mo.scheduled_ = false;
                    var queue = mo.takeRecords();
                    removeTransientObserversFor(mo);
                    if (queue.length) {
                        mo.callback_(queue, mo);
                    }
                }
            }
        }

        function MutationRecord(type, target) {
            this.type = type;
            this.target = target;
            this.addedNodes = new wrappers.NodeList();
            this.removedNodes = new wrappers.NodeList();
            this.previousSibling = null;
            this.nextSibling = null;
            this.attributeName = null;
            this.attributeNamespace = null;
            this.oldValue = null;
        }

        function registerTransientObservers(ancestor, node) {
            for (; ancestor; ancestor = ancestor.parentNode) {
                var registrations = registrationsTable.get(ancestor);
                if (!registrations) continue;
                for (var i = 0; i < registrations.length; i++) {
                    var registration = registrations[i];
                    if (registration.options.subtree) registration.addTransientObserver(node);
                }
            }
        }

        function removeTransientObserversFor(observer) {
            for (var i = 0; i < observer.nodes_.length; i++) {
                var node = observer.nodes_[i];
                var registrations = registrationsTable.get(node);
                if (!registrations) return;
                for (var j = 0; j < registrations.length; j++) {
                    var registration = registrations[j];
                    if (registration.observer === observer) registration.removeTransientObservers();
                }
            }
        }

        function enqueueMutation(target, type, data) {
            var interestedObservers = Object.create(null);
            var associatedStrings = Object.create(null);
            for (var node = target; node; node = node.parentNode) {
                var registrations = registrationsTable.get(node);
                if (!registrations) continue;
                for (var j = 0; j < registrations.length; j++) {
                    var registration = registrations[j];
                    var options = registration.options;
                    if (node !== target && !options.subtree) continue;
                    if (type === "attributes" && !options.attributes) continue;
                    if (type === "attributes" && options.attributeFilter && (data.namespace !== null || options.attributeFilter.indexOf(data.name) === -1)) {
                        continue;
                    }
                    if (type === "characterData" && !options.characterData) continue;
                    if (type === "childList" && !options.childList) continue;
                    var observer = registration.observer;
                    interestedObservers[observer.uid_] = observer;
                    if (type === "attributes" && options.attributeOldValue || type === "characterData" && options.characterDataOldValue) {
                        associatedStrings[observer.uid_] = data.oldValue;
                    }
                }
            }
            for (var uid in interestedObservers) {
                var observer = interestedObservers[uid];
                var record = new MutationRecord(type, target);
                if ("name" in data && "namespace" in data) {
                    record.attributeName = data.name;
                    record.attributeNamespace = data.namespace;
                }
                if (data.addedNodes) record.addedNodes = data.addedNodes;
                if (data.removedNodes) record.removedNodes = data.removedNodes;
                if (data.previousSibling) record.previousSibling = data.previousSibling;
                if (data.nextSibling) record.nextSibling = data.nextSibling;
                if (associatedStrings[uid] !== undefined) record.oldValue = associatedStrings[uid];
                scheduleCallback(observer);
                observer.records_.push(record);
            }
        }

        var slice = Array.prototype.slice;

        function MutationObserverOptions(options) {
            this.childList = !!options.childList;
            this.subtree = !!options.subtree;
            if (!("attributes" in options) && ("attributeOldValue" in options || "attributeFilter" in options)) {
                this.attributes = true;
            } else {
                this.attributes = !!options.attributes;
            }
            if ("characterDataOldValue" in options && !("characterData" in options)) this.characterData = true; else this.characterData = !!options.characterData;
            if (!this.attributes && (options.attributeOldValue || "attributeFilter" in options) || !this.characterData && options.characterDataOldValue) {
                throw new TypeError();
            }
            this.characterData = !!options.characterData;
            this.attributeOldValue = !!options.attributeOldValue;
            this.characterDataOldValue = !!options.characterDataOldValue;
            if ("attributeFilter" in options) {
                if (options.attributeFilter == null || typeof options.attributeFilter !== "object") {
                    throw new TypeError();
                }
                this.attributeFilter = slice.call(options.attributeFilter);
            } else {
                this.attributeFilter = null;
            }
        }

        var uidCounter = 0;

        function MutationObserver(callback) {
            this.callback_ = callback;
            this.nodes_ = [];
            this.records_ = [];
            this.uid_ = ++uidCounter;
            this.scheduled_ = false;
        }

        MutationObserver.prototype = {
            constructor: MutationObserver,
            observe: function (target, options) {
                target = wrapIfNeeded(target);
                var newOptions = new MutationObserverOptions(options);
                var registration;
                var registrations = registrationsTable.get(target);
                if (!registrations) registrationsTable.set(target, registrations = []);
                for (var i = 0; i < registrations.length; i++) {
                    if (registrations[i].observer === this) {
                        registration = registrations[i];
                        registration.removeTransientObservers();
                        registration.options = newOptions;
                    }
                }
                if (!registration) {
                    registration = new Registration(this, target, newOptions);
                    registrations.push(registration);
                    this.nodes_.push(target);
                }
            },
            disconnect: function () {
                this.nodes_.forEach(function (node) {
                    var registrations = registrationsTable.get(node);
                    for (var i = 0; i < registrations.length; i++) {
                        var registration = registrations[i];
                        if (registration.observer === this) {
                            registrations.splice(i, 1);
                            break;
                        }
                    }
                }, this);
                this.records_ = [];
            },
            takeRecords: function () {
                var copyOfRecords = this.records_;
                this.records_ = [];
                return copyOfRecords;
            }
        };
        function Registration(observer, target, options) {
            this.observer = observer;
            this.target = target;
            this.options = options;
            this.transientObservedNodes = [];
        }

        Registration.prototype = {
            addTransientObserver: function (node) {
                if (node === this.target) return;
                scheduleCallback(this.observer);
                this.transientObservedNodes.push(node);
                var registrations = registrationsTable.get(node);
                if (!registrations) registrationsTable.set(node, registrations = []);
                registrations.push(this);
            },
            removeTransientObservers: function () {
                var transientObservedNodes = this.transientObservedNodes;
                this.transientObservedNodes = [];
                for (var i = 0; i < transientObservedNodes.length; i++) {
                    var node = transientObservedNodes[i];
                    var registrations = registrationsTable.get(node);
                    for (var j = 0; j < registrations.length; j++) {
                        if (registrations[j] === this) {
                            registrations.splice(j, 1);
                            break;
                        }
                    }
                }
            }
        };
        scope.enqueueMutation = enqueueMutation;
        scope.registerTransientObservers = registerTransientObservers;
        scope.wrappers.MutationObserver = MutationObserver;
        scope.wrappers.MutationRecord = MutationRecord;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        function TreeScope(root, parent) {
            this.root = root;
            this.parent = parent;
        }

        TreeScope.prototype = {
            get renderer() {
                if (this.root instanceof scope.wrappers.ShadowRoot) {
                    return scope.getRendererForHost(this.root.host);
                }
                return null;
            },
            contains: function (treeScope) {
                for (; treeScope; treeScope = treeScope.parent) {
                    if (treeScope === this) return true;
                }
                return false;
            }
        };
        function setTreeScope(node, treeScope) {
            if (node.treeScope_ !== treeScope) {
                node.treeScope_ = treeScope;
                for (var sr = node.shadowRoot; sr; sr = sr.olderShadowRoot) {
                    sr.treeScope_.parent = treeScope;
                }
                for (var child = node.firstChild; child; child = child.nextSibling) {
                    setTreeScope(child, treeScope);
                }
            }
        }

        function getTreeScope(node) {
            if (node instanceof scope.wrappers.Window) {
                debugger;
            }
            if (node.treeScope_) return node.treeScope_;
            var parent = node.parentNode;
            var treeScope;
            if (parent) treeScope = getTreeScope(parent); else treeScope = new TreeScope(node, null);
            return node.treeScope_ = treeScope;
        }

        scope.TreeScope = TreeScope;
        scope.getTreeScope = getTreeScope;
        scope.setTreeScope = setTreeScope;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var forwardMethodsToWrapper = scope.forwardMethodsToWrapper;
        var getTreeScope = scope.getTreeScope;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var setWrapper = scope.setWrapper;
        var unsafeUnwrap = scope.unsafeUnwrap;
        var unwrap = scope.unwrap;
        var wrap = scope.wrap;
        var wrappers = scope.wrappers;
        var wrappedFuns = new WeakMap();
        var listenersTable = new WeakMap();
        var handledEventsTable = new WeakMap();
        var currentlyDispatchingEvents = new WeakMap();
        var targetTable = new WeakMap();
        var currentTargetTable = new WeakMap();
        var relatedTargetTable = new WeakMap();
        var eventPhaseTable = new WeakMap();
        var stopPropagationTable = new WeakMap();
        var stopImmediatePropagationTable = new WeakMap();
        var eventHandlersTable = new WeakMap();
        var eventPathTable = new WeakMap();

        function isShadowRoot(node) {
            return node instanceof wrappers.ShadowRoot;
        }

        function rootOfNode(node) {
            return getTreeScope(node).root;
        }

        function getEventPath(node, event) {
            var path = [];
            var current = node;
            path.push(current);
            while (current) {
                var destinationInsertionPoints = getDestinationInsertionPoints(current);
                if (destinationInsertionPoints && destinationInsertionPoints.length > 0) {
                    for (var i = 0; i < destinationInsertionPoints.length; i++) {
                        var insertionPoint = destinationInsertionPoints[i];
                        if (isShadowInsertionPoint(insertionPoint)) {
                            var shadowRoot = rootOfNode(insertionPoint);
                            var olderShadowRoot = shadowRoot.olderShadowRoot;
                            if (olderShadowRoot) path.push(olderShadowRoot);
                        }
                        path.push(insertionPoint);
                    }
                    current = destinationInsertionPoints[destinationInsertionPoints.length - 1];
                } else {
                    if (isShadowRoot(current)) {
                        if (inSameTree(node, current) && eventMustBeStopped(event)) {
                            break;
                        }
                        current = current.host;
                        path.push(current);
                    } else {
                        current = current.parentNode;
                        if (current) path.push(current);
                    }
                }
            }
            return path;
        }

        function eventMustBeStopped(event) {
            if (!event) return false;
            switch (event.type) {
                case "abort":
                case "error":
                case "select":
                case "change":
                case "load":
                case "reset":
                case "resize":
                case "scroll":
                case "selectstart":
                    return true;
            }
            return false;
        }

        function isShadowInsertionPoint(node) {
            return node instanceof HTMLShadowElement;
        }

        function getDestinationInsertionPoints(node) {
            return scope.getDestinationInsertionPoints(node);
        }

        function eventRetargetting(path, currentTarget) {
            if (path.length === 0) return currentTarget;
            if (currentTarget instanceof wrappers.Window) currentTarget = currentTarget.document;
            var currentTargetTree = getTreeScope(currentTarget);
            var originalTarget = path[0];
            var originalTargetTree = getTreeScope(originalTarget);
            var relativeTargetTree = lowestCommonInclusiveAncestor(currentTargetTree, originalTargetTree);
            for (var i = 0; i < path.length; i++) {
                var node = path[i];
                if (getTreeScope(node) === relativeTargetTree) return node;
            }
            return path[path.length - 1];
        }

        function getTreeScopeAncestors(treeScope) {
            var ancestors = [];
            for (; treeScope; treeScope = treeScope.parent) {
                ancestors.push(treeScope);
            }
            return ancestors;
        }

        function lowestCommonInclusiveAncestor(tsA, tsB) {
            var ancestorsA = getTreeScopeAncestors(tsA);
            var ancestorsB = getTreeScopeAncestors(tsB);
            var result = null;
            while (ancestorsA.length > 0 && ancestorsB.length > 0) {
                var a = ancestorsA.pop();
                var b = ancestorsB.pop();
                if (a === b) result = a; else break;
            }
            return result;
        }

        function getTreeScopeRoot(ts) {
            if (!ts.parent) return ts;
            return getTreeScopeRoot(ts.parent);
        }

        function relatedTargetResolution(event, currentTarget, relatedTarget) {
            if (currentTarget instanceof wrappers.Window) currentTarget = currentTarget.document;
            var currentTargetTree = getTreeScope(currentTarget);
            var relatedTargetTree = getTreeScope(relatedTarget);
            var relatedTargetEventPath = getEventPath(relatedTarget, event);
            var lowestCommonAncestorTree;
            var lowestCommonAncestorTree = lowestCommonInclusiveAncestor(currentTargetTree, relatedTargetTree);
            if (!lowestCommonAncestorTree) lowestCommonAncestorTree = relatedTargetTree.root;
            for (var commonAncestorTree = lowestCommonAncestorTree; commonAncestorTree; commonAncestorTree = commonAncestorTree.parent) {
                var adjustedRelatedTarget;
                for (var i = 0; i < relatedTargetEventPath.length; i++) {
                    var node = relatedTargetEventPath[i];
                    if (getTreeScope(node) === commonAncestorTree) return node;
                }
            }
            return null;
        }

        function inSameTree(a, b) {
            return getTreeScope(a) === getTreeScope(b);
        }

        var NONE = 0;
        var CAPTURING_PHASE = 1;
        var AT_TARGET = 2;
        var BUBBLING_PHASE = 3;
        var pendingError;

        function dispatchOriginalEvent(originalEvent) {
            if (handledEventsTable.get(originalEvent)) return;
            handledEventsTable.set(originalEvent, true);
            dispatchEvent(wrap(originalEvent), wrap(originalEvent.target));
            if (pendingError) {
                var err = pendingError;
                pendingError = null;
                throw err;
            }
        }

        function isLoadLikeEvent(event) {
            switch (event.type) {
                case "load":
                case "beforeunload":
                case "unload":
                    return true;
            }
            return false;
        }

        function dispatchEvent(event, originalWrapperTarget) {
            if (currentlyDispatchingEvents.get(event)) throw new Error("InvalidStateError");
            currentlyDispatchingEvents.set(event, true);
            scope.renderAllPending();
            var eventPath;
            var overrideTarget;
            var win;
            if (isLoadLikeEvent(event) && !event.bubbles) {
                var doc = originalWrapperTarget;
                if (doc instanceof wrappers.Document && (win = doc.defaultView)) {
                    overrideTarget = doc;
                    eventPath = [];
                }
            }
            if (!eventPath) {
                if (originalWrapperTarget instanceof wrappers.Window) {
                    win = originalWrapperTarget;
                    eventPath = [];
                } else {
                    eventPath = getEventPath(originalWrapperTarget, event);
                    if (!isLoadLikeEvent(event)) {
                        var doc = eventPath[eventPath.length - 1];
                        if (doc instanceof wrappers.Document) win = doc.defaultView;
                    }
                }
            }
            eventPathTable.set(event, eventPath);
            if (dispatchCapturing(event, eventPath, win, overrideTarget)) {
                if (dispatchAtTarget(event, eventPath, win, overrideTarget)) {
                    dispatchBubbling(event, eventPath, win, overrideTarget);
                }
            }
            eventPhaseTable.set(event, NONE);
            currentTargetTable.delete(event, null);
            currentlyDispatchingEvents.delete(event);
            return event.defaultPrevented;
        }

        function dispatchCapturing(event, eventPath, win, overrideTarget) {
            var phase = CAPTURING_PHASE;
            if (win) {
                if (!invoke(win, event, phase, eventPath, overrideTarget)) return false;
            }
            for (var i = eventPath.length - 1; i > 0; i--) {
                if (!invoke(eventPath[i], event, phase, eventPath, overrideTarget)) return false;
            }
            return true;
        }

        function dispatchAtTarget(event, eventPath, win, overrideTarget) {
            var phase = AT_TARGET;
            var currentTarget = eventPath[0] || win;
            return invoke(currentTarget, event, phase, eventPath, overrideTarget);
        }

        function dispatchBubbling(event, eventPath, win, overrideTarget) {
            var phase = BUBBLING_PHASE;
            for (var i = 1; i < eventPath.length; i++) {
                if (!invoke(eventPath[i], event, phase, eventPath, overrideTarget)) return;
            }
            if (win && eventPath.length > 0) {
                invoke(win, event, phase, eventPath, overrideTarget);
            }
        }

        function invoke(currentTarget, event, phase, eventPath, overrideTarget) {
            var listeners = listenersTable.get(currentTarget);
            if (!listeners) return true;
            var target = overrideTarget || eventRetargetting(eventPath, currentTarget);
            if (target === currentTarget) {
                if (phase === CAPTURING_PHASE) return true;
                if (phase === BUBBLING_PHASE) phase = AT_TARGET;
            } else if (phase === BUBBLING_PHASE && !event.bubbles) {
                return true;
            }
            if ("relatedTarget" in event) {
                var originalEvent = unwrap(event);
                var unwrappedRelatedTarget = originalEvent.relatedTarget;
                if (unwrappedRelatedTarget) {
                    if (unwrappedRelatedTarget instanceof Object && unwrappedRelatedTarget.addEventListener) {
                        var relatedTarget = wrap(unwrappedRelatedTarget);
                        var adjusted = relatedTargetResolution(event, currentTarget, relatedTarget);
                        if (adjusted === target) return true;
                    } else {
                        adjusted = null;
                    }
                    relatedTargetTable.set(event, adjusted);
                }
            }
            eventPhaseTable.set(event, phase);
            var type = event.type;
            var anyRemoved = false;
            targetTable.set(event, target);
            currentTargetTable.set(event, currentTarget);
            listeners.depth++;
            for (var i = 0, len = listeners.length; i < len; i++) {
                var listener = listeners[i];
                if (listener.removed) {
                    anyRemoved = true;
                    continue;
                }
                if (listener.type !== type || !listener.capture && phase === CAPTURING_PHASE || listener.capture && phase === BUBBLING_PHASE) {
                    continue;
                }
                try {
                    if (typeof listener.handler === "function") listener.handler.call(currentTarget, event); else listener.handler.handleEvent(event);
                    if (stopImmediatePropagationTable.get(event)) return false;
                } catch (ex) {
                    if (!pendingError) pendingError = ex;
                }
            }
            listeners.depth--;
            if (anyRemoved && listeners.depth === 0) {
                var copy = listeners.slice();
                listeners.length = 0;
                for (var i = 0; i < copy.length; i++) {
                    if (!copy[i].removed) listeners.push(copy[i]);
                }
            }
            return !stopPropagationTable.get(event);
        }

        function Listener(type, handler, capture) {
            this.type = type;
            this.handler = handler;
            this.capture = Boolean(capture);
        }

        Listener.prototype = {
            equals: function (that) {
                return this.handler === that.handler && this.type === that.type && this.capture === that.capture;
            },
            get removed() {
                return this.handler === null;
            },
            remove: function () {
                this.handler = null;
            }
        };
        var OriginalEvent = window.Event;
        OriginalEvent.prototype.polymerBlackList_ = {
            returnValue: true,
            keyLocation: true
        };
        function Event(type, options) {
            if (type instanceof OriginalEvent) {
                var impl = type;
                if (!OriginalBeforeUnloadEvent && impl.type === "beforeunload" && !(this instanceof BeforeUnloadEvent)) {
                    return new BeforeUnloadEvent(impl);
                }
                setWrapper(impl, this);
            } else {
                return wrap(constructEvent(OriginalEvent, "Event", type, options));
            }
        }

        Event.prototype = {
            get target() {
                return targetTable.get(this);
            },
            get currentTarget() {
                return currentTargetTable.get(this);
            },
            get eventPhase() {
                return eventPhaseTable.get(this);
            },
            get path() {
                var eventPath = eventPathTable.get(this);
                if (!eventPath) return [];
                return eventPath.slice();
            },
            stopPropagation: function () {
                stopPropagationTable.set(this, true);
            },
            stopImmediatePropagation: function () {
                stopPropagationTable.set(this, true);
                stopImmediatePropagationTable.set(this, true);
            }
        };
        registerWrapper(OriginalEvent, Event, document.createEvent("Event"));
        function unwrapOptions(options) {
            if (!options || !options.relatedTarget) return options;
            return Object.create(options, {
                relatedTarget: {
                    value: unwrap(options.relatedTarget)
                }
            });
        }

        function registerGenericEvent(name, SuperEvent, prototype) {
            var OriginalEvent = window[name];
            var GenericEvent = function (type, options) {
                if (type instanceof OriginalEvent) setWrapper(type, this); else return wrap(constructEvent(OriginalEvent, name, type, options));
            };
            GenericEvent.prototype = Object.create(SuperEvent.prototype);
            if (prototype) mixin(GenericEvent.prototype, prototype);
            if (OriginalEvent) {
                try {
                    registerWrapper(OriginalEvent, GenericEvent, new OriginalEvent("temp"));
                } catch (ex) {
                    registerWrapper(OriginalEvent, GenericEvent, document.createEvent(name));
                }
            }
            return GenericEvent;
        }

        var UIEvent = registerGenericEvent("UIEvent", Event);
        var CustomEvent = registerGenericEvent("CustomEvent", Event);
        var relatedTargetProto = {
            get relatedTarget() {
                var relatedTarget = relatedTargetTable.get(this);
                if (relatedTarget !== undefined) return relatedTarget;
                return wrap(unwrap(this).relatedTarget);
            }
        };

        function getInitFunction(name, relatedTargetIndex) {
            return function () {
                arguments[relatedTargetIndex] = unwrap(arguments[relatedTargetIndex]);
                var impl = unwrap(this);
                impl[name].apply(impl, arguments);
            };
        }

        var mouseEventProto = mixin({
            initMouseEvent: getInitFunction("initMouseEvent", 14)
        }, relatedTargetProto);
        var focusEventProto = mixin({
            initFocusEvent: getInitFunction("initFocusEvent", 5)
        }, relatedTargetProto);
        var MouseEvent = registerGenericEvent("MouseEvent", UIEvent, mouseEventProto);
        var FocusEvent = registerGenericEvent("FocusEvent", UIEvent, focusEventProto);
        var defaultInitDicts = Object.create(null);
        var supportsEventConstructors = function () {
            try {
                new window.FocusEvent("focus");
            } catch (ex) {
                return false;
            }
            return true;
        }();

        function constructEvent(OriginalEvent, name, type, options) {
            if (supportsEventConstructors) return new OriginalEvent(type, unwrapOptions(options));
            var event = unwrap(document.createEvent(name));
            var defaultDict = defaultInitDicts[name];
            var args = [type];
            Object.keys(defaultDict).forEach(function (key) {
                var v = options != null && key in options ? options[key] : defaultDict[key];
                if (key === "relatedTarget") v = unwrap(v);
                args.push(v);
            });
            event["init" + name].apply(event, args);
            return event;
        }

        if (!supportsEventConstructors) {
            var configureEventConstructor = function (name, initDict, superName) {
                if (superName) {
                    var superDict = defaultInitDicts[superName];
                    initDict = mixin(mixin({}, superDict), initDict);
                }
                defaultInitDicts[name] = initDict;
            };
            configureEventConstructor("Event", {
                bubbles: false,
                cancelable: false
            });
            configureEventConstructor("CustomEvent", {
                detail: null
            }, "Event");
            configureEventConstructor("UIEvent", {
                view: null,
                detail: 0
            }, "Event");
            configureEventConstructor("MouseEvent", {
                screenX: 0,
                screenY: 0,
                clientX: 0,
                clientY: 0,
                ctrlKey: false,
                altKey: false,
                shiftKey: false,
                metaKey: false,
                button: 0,
                relatedTarget: null
            }, "UIEvent");
            configureEventConstructor("FocusEvent", {
                relatedTarget: null
            }, "UIEvent");
        }
        var OriginalBeforeUnloadEvent = window.BeforeUnloadEvent;

        function BeforeUnloadEvent(impl) {
            Event.call(this, impl);
        }

        BeforeUnloadEvent.prototype = Object.create(Event.prototype);
        mixin(BeforeUnloadEvent.prototype, {
            get returnValue() {
                return unsafeUnwrap(this).returnValue;
            },
            set returnValue(v) {
                unsafeUnwrap(this).returnValue = v;
            }
        });
        if (OriginalBeforeUnloadEvent) registerWrapper(OriginalBeforeUnloadEvent, BeforeUnloadEvent);
        function isValidListener(fun) {
            if (typeof fun === "function") return true;
            return fun && fun.handleEvent;
        }

        function isMutationEvent(type) {
            switch (type) {
                case "DOMAttrModified":
                case "DOMAttributeNameChanged":
                case "DOMCharacterDataModified":
                case "DOMElementNameChanged":
                case "DOMNodeInserted":
                case "DOMNodeInsertedIntoDocument":
                case "DOMNodeRemoved":
                case "DOMNodeRemovedFromDocument":
                case "DOMSubtreeModified":
                    return true;
            }
            return false;
        }

        var OriginalEventTarget = window.EventTarget;

        function EventTarget(impl) {
            setWrapper(impl, this);
        }

        var methodNames = ["addEventListener", "removeEventListener", "dispatchEvent"];
        [Node, Window].forEach(function (constructor) {
            var p = constructor.prototype;
            methodNames.forEach(function (name) {
                Object.defineProperty(p, name + "_", {
                    value: p[name]
                });
            });
        });
        function getTargetToListenAt(wrapper) {
            if (wrapper instanceof wrappers.ShadowRoot) wrapper = wrapper.host;
            return unwrap(wrapper);
        }

        EventTarget.prototype = {
            addEventListener: function (type, fun, capture) {
                if (!isValidListener(fun) || isMutationEvent(type)) return;
                var listener = new Listener(type, fun, capture);
                var listeners = listenersTable.get(this);
                if (!listeners) {
                    listeners = [];
                    listeners.depth = 0;
                    listenersTable.set(this, listeners);
                } else {
                    for (var i = 0; i < listeners.length; i++) {
                        if (listener.equals(listeners[i])) return;
                    }
                }
                listeners.push(listener);
                var target = getTargetToListenAt(this);
                target.addEventListener_(type, dispatchOriginalEvent, true);
            },
            removeEventListener: function (type, fun, capture) {
                capture = Boolean(capture);
                var listeners = listenersTable.get(this);
                if (!listeners) return;
                var count = 0, found = false;
                for (var i = 0; i < listeners.length; i++) {
                    if (listeners[i].type === type && listeners[i].capture === capture) {
                        count++;
                        if (listeners[i].handler === fun) {
                            found = true;
                            listeners[i].remove();
                        }
                    }
                }
                if (found && count === 1) {
                    var target = getTargetToListenAt(this);
                    target.removeEventListener_(type, dispatchOriginalEvent, true);
                }
            },
            dispatchEvent: function (event) {
                var nativeEvent = unwrap(event);
                var eventType = nativeEvent.type;
                handledEventsTable.set(nativeEvent, false);
                scope.renderAllPending();
                var tempListener;
                if (!hasListenerInAncestors(this, eventType)) {
                    tempListener = function () {
                    };
                    this.addEventListener(eventType, tempListener, true);
                }
                try {
                    return unwrap(this).dispatchEvent_(nativeEvent);
                } finally {
                    if (tempListener) this.removeEventListener(eventType, tempListener, true);
                }
            }
        };
        function hasListener(node, type) {
            var listeners = listenersTable.get(node);
            if (listeners) {
                for (var i = 0; i < listeners.length; i++) {
                    if (!listeners[i].removed && listeners[i].type === type) return true;
                }
            }
            return false;
        }

        function hasListenerInAncestors(target, type) {
            for (var node = unwrap(target); node; node = node.parentNode) {
                if (hasListener(wrap(node), type)) return true;
            }
            return false;
        }

        if (OriginalEventTarget) registerWrapper(OriginalEventTarget, EventTarget);
        function wrapEventTargetMethods(constructors) {
            forwardMethodsToWrapper(constructors, methodNames);
        }

        var originalElementFromPoint = document.elementFromPoint;

        function elementFromPoint(self, document, x, y) {
            scope.renderAllPending();
            var element = wrap(originalElementFromPoint.call(unsafeUnwrap(document), x, y));
            if (!element) return null;
            var path = getEventPath(element, null);
            var idx = path.lastIndexOf(self);
            if (idx == -1) return null; else path = path.slice(0, idx);
            return eventRetargetting(path, self);
        }

        function getEventHandlerGetter(name) {
            return function () {
                var inlineEventHandlers = eventHandlersTable.get(this);
                return inlineEventHandlers && inlineEventHandlers[name] && inlineEventHandlers[name].value || null;
            };
        }

        function getEventHandlerSetter(name) {
            var eventType = name.slice(2);
            return function (value) {
                var inlineEventHandlers = eventHandlersTable.get(this);
                if (!inlineEventHandlers) {
                    inlineEventHandlers = Object.create(null);
                    eventHandlersTable.set(this, inlineEventHandlers);
                }
                var old = inlineEventHandlers[name];
                if (old) this.removeEventListener(eventType, old.wrapped, false);
                if (typeof value === "function") {
                    var wrapped = function (e) {
                        var rv = value.call(this, e);
                        if (rv === false) e.preventDefault(); else if (name === "onbeforeunload" && typeof rv === "string") e.returnValue = rv;
                    };
                    this.addEventListener(eventType, wrapped, false);
                    inlineEventHandlers[name] = {
                        value: value,
                        wrapped: wrapped
                    };
                }
            };
        }

        scope.elementFromPoint = elementFromPoint;
        scope.getEventHandlerGetter = getEventHandlerGetter;
        scope.getEventHandlerSetter = getEventHandlerSetter;
        scope.wrapEventTargetMethods = wrapEventTargetMethods;
        scope.wrappers.BeforeUnloadEvent = BeforeUnloadEvent;
        scope.wrappers.CustomEvent = CustomEvent;
        scope.wrappers.Event = Event;
        scope.wrappers.EventTarget = EventTarget;
        scope.wrappers.FocusEvent = FocusEvent;
        scope.wrappers.MouseEvent = MouseEvent;
        scope.wrappers.UIEvent = UIEvent;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var UIEvent = scope.wrappers.UIEvent;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var setWrapper = scope.setWrapper;
        var unsafeUnwrap = scope.unsafeUnwrap;
        var wrap = scope.wrap;
        var OriginalTouchEvent = window.TouchEvent;
        if (!OriginalTouchEvent) return;
        var nativeEvent;
        try {
            nativeEvent = document.createEvent("TouchEvent");
        } catch (ex) {
            return;
        }
        var nonEnumDescriptor = {
            enumerable: false
        };

        function nonEnum(obj, prop) {
            Object.defineProperty(obj, prop, nonEnumDescriptor);
        }

        function Touch(impl) {
            setWrapper(impl, this);
        }

        Touch.prototype = {
            get target() {
                return wrap(unsafeUnwrap(this).target);
            }
        };
        var descr = {
            configurable: true,
            enumerable: true,
            get: null
        };
        ["clientX", "clientY", "screenX", "screenY", "pageX", "pageY", "identifier", "webkitRadiusX", "webkitRadiusY", "webkitRotationAngle", "webkitForce"].forEach(function (name) {
            descr.get = function () {
                return unsafeUnwrap(this)[name];
            };
            Object.defineProperty(Touch.prototype, name, descr);
        });
        function TouchList() {
            this.length = 0;
            nonEnum(this, "length");
        }

        TouchList.prototype = {
            item: function (index) {
                return this[index];
            }
        };
        function wrapTouchList(nativeTouchList) {
            var list = new TouchList();
            for (var i = 0; i < nativeTouchList.length; i++) {
                list[i] = new Touch(nativeTouchList[i]);
            }
            list.length = i;
            return list;
        }

        function TouchEvent(impl) {
            UIEvent.call(this, impl);
        }

        TouchEvent.prototype = Object.create(UIEvent.prototype);
        mixin(TouchEvent.prototype, {
            get touches() {
                return wrapTouchList(unsafeUnwrap(this).touches);
            },
            get targetTouches() {
                return wrapTouchList(unsafeUnwrap(this).targetTouches);
            },
            get changedTouches() {
                return wrapTouchList(unsafeUnwrap(this).changedTouches);
            },
            initTouchEvent: function () {
                throw new Error("Not implemented");
            }
        });
        registerWrapper(OriginalTouchEvent, TouchEvent, nativeEvent);
        scope.wrappers.Touch = Touch;
        scope.wrappers.TouchEvent = TouchEvent;
        scope.wrappers.TouchList = TouchList;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var unsafeUnwrap = scope.unsafeUnwrap;
        var wrap = scope.wrap;
        var nonEnumDescriptor = {
            enumerable: false
        };

        function nonEnum(obj, prop) {
            Object.defineProperty(obj, prop, nonEnumDescriptor);
        }

        function NodeList() {
            this.length = 0;
            nonEnum(this, "length");
        }

        NodeList.prototype = {
            item: function (index) {
                return this[index];
            }
        };
        nonEnum(NodeList.prototype, "item");
        function wrapNodeList(list) {
            if (list == null) return list;
            var wrapperList = new NodeList();
            for (var i = 0, length = list.length; i < length; i++) {
                wrapperList[i] = wrap(list[i]);
            }
            wrapperList.length = length;
            return wrapperList;
        }

        function addWrapNodeListMethod(wrapperConstructor, name) {
            wrapperConstructor.prototype[name] = function () {
                return wrapNodeList(unsafeUnwrap(this)[name].apply(unsafeUnwrap(this), arguments));
            };
        }

        scope.wrappers.NodeList = NodeList;
        scope.addWrapNodeListMethod = addWrapNodeListMethod;
        scope.wrapNodeList = wrapNodeList;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        scope.wrapHTMLCollection = scope.wrapNodeList;
        scope.wrappers.HTMLCollection = scope.wrappers.NodeList;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var EventTarget = scope.wrappers.EventTarget;
        var NodeList = scope.wrappers.NodeList;
        var TreeScope = scope.TreeScope;
        var assert = scope.assert;
        var defineWrapGetter = scope.defineWrapGetter;
        var enqueueMutation = scope.enqueueMutation;
        var getTreeScope = scope.getTreeScope;
        var isWrapper = scope.isWrapper;
        var mixin = scope.mixin;
        var registerTransientObservers = scope.registerTransientObservers;
        var registerWrapper = scope.registerWrapper;
        var setTreeScope = scope.setTreeScope;
        var unsafeUnwrap = scope.unsafeUnwrap;
        var unwrap = scope.unwrap;
        var unwrapIfNeeded = scope.unwrapIfNeeded;
        var wrap = scope.wrap;
        var wrapIfNeeded = scope.wrapIfNeeded;
        var wrappers = scope.wrappers;

        function assertIsNodeWrapper(node) {
            assert(node instanceof Node);
        }

        function createOneElementNodeList(node) {
            var nodes = new NodeList();
            nodes[0] = node;
            nodes.length = 1;
            return nodes;
        }

        var surpressMutations = false;

        function enqueueRemovalForInsertedNodes(node, parent, nodes) {
            enqueueMutation(parent, "childList", {
                removedNodes: nodes,
                previousSibling: node.previousSibling,
                nextSibling: node.nextSibling
            });
        }

        function enqueueRemovalForInsertedDocumentFragment(df, nodes) {
            enqueueMutation(df, "childList", {
                removedNodes: nodes
            });
        }

        function collectNodes(node, parentNode, previousNode, nextNode) {
            if (node instanceof DocumentFragment) {
                var nodes = collectNodesForDocumentFragment(node);
                surpressMutations = true;
                for (var i = nodes.length - 1; i >= 0; i--) {
                    node.removeChild(nodes[i]);
                    nodes[i].parentNode_ = parentNode;
                }
                surpressMutations = false;
                for (var i = 0; i < nodes.length; i++) {
                    nodes[i].previousSibling_ = nodes[i - 1] || previousNode;
                    nodes[i].nextSibling_ = nodes[i + 1] || nextNode;
                }
                if (previousNode) previousNode.nextSibling_ = nodes[0];
                if (nextNode) nextNode.previousSibling_ = nodes[nodes.length - 1];
                return nodes;
            }
            var nodes = createOneElementNodeList(node);
            var oldParent = node.parentNode;
            if (oldParent) {
                oldParent.removeChild(node);
            }
            node.parentNode_ = parentNode;
            node.previousSibling_ = previousNode;
            node.nextSibling_ = nextNode;
            if (previousNode) previousNode.nextSibling_ = node;
            if (nextNode) nextNode.previousSibling_ = node;
            return nodes;
        }

        function collectNodesNative(node) {
            if (node instanceof DocumentFragment) return collectNodesForDocumentFragment(node);
            var nodes = createOneElementNodeList(node);
            var oldParent = node.parentNode;
            if (oldParent) enqueueRemovalForInsertedNodes(node, oldParent, nodes);
            return nodes;
        }

        function collectNodesForDocumentFragment(node) {
            var nodes = new NodeList();
            var i = 0;
            for (var child = node.firstChild; child; child = child.nextSibling) {
                nodes[i++] = child;
            }
            nodes.length = i;
            enqueueRemovalForInsertedDocumentFragment(node, nodes);
            return nodes;
        }

        function snapshotNodeList(nodeList) {
            return nodeList;
        }

        function nodeWasAdded(node, treeScope) {
            setTreeScope(node, treeScope);
            node.nodeIsInserted_();
        }

        function nodesWereAdded(nodes, parent) {
            var treeScope = getTreeScope(parent);
            for (var i = 0; i < nodes.length; i++) {
                nodeWasAdded(nodes[i], treeScope);
            }
        }

        function nodeWasRemoved(node) {
            setTreeScope(node, new TreeScope(node, null));
        }

        function nodesWereRemoved(nodes) {
            for (var i = 0; i < nodes.length; i++) {
                nodeWasRemoved(nodes[i]);
            }
        }

        function ensureSameOwnerDocument(parent, child) {
            var ownerDoc = parent.nodeType === Node.DOCUMENT_NODE ? parent : parent.ownerDocument;
            if (ownerDoc !== child.ownerDocument) ownerDoc.adoptNode(child);
        }

        function adoptNodesIfNeeded(owner, nodes) {
            if (!nodes.length) return;
            var ownerDoc = owner.ownerDocument;
            if (ownerDoc === nodes[0].ownerDocument) return;
            for (var i = 0; i < nodes.length; i++) {
                scope.adoptNodeNoRemove(nodes[i], ownerDoc);
            }
        }

        function unwrapNodesForInsertion(owner, nodes) {
            adoptNodesIfNeeded(owner, nodes);
            var length = nodes.length;
            if (length === 1) return unwrap(nodes[0]);
            var df = unwrap(owner.ownerDocument.createDocumentFragment());
            for (var i = 0; i < length; i++) {
                df.appendChild(unwrap(nodes[i]));
            }
            return df;
        }

        function clearChildNodes(wrapper) {
            if (wrapper.firstChild_ !== undefined) {
                var child = wrapper.firstChild_;
                while (child) {
                    var tmp = child;
                    child = child.nextSibling_;
                    tmp.parentNode_ = tmp.previousSibling_ = tmp.nextSibling_ = undefined;
                }
            }
            wrapper.firstChild_ = wrapper.lastChild_ = undefined;
        }

        function removeAllChildNodes(wrapper) {
            if (wrapper.invalidateShadowRenderer()) {
                var childWrapper = wrapper.firstChild;
                while (childWrapper) {
                    assert(childWrapper.parentNode === wrapper);
                    var nextSibling = childWrapper.nextSibling;
                    var childNode = unwrap(childWrapper);
                    var parentNode = childNode.parentNode;
                    if (parentNode) originalRemoveChild.call(parentNode, childNode);
                    childWrapper.previousSibling_ = childWrapper.nextSibling_ = childWrapper.parentNode_ = null;
                    childWrapper = nextSibling;
                }
                wrapper.firstChild_ = wrapper.lastChild_ = null;
            } else {
                var node = unwrap(wrapper);
                var child = node.firstChild;
                var nextSibling;
                while (child) {
                    nextSibling = child.nextSibling;
                    originalRemoveChild.call(node, child);
                    child = nextSibling;
                }
            }
        }

        function invalidateParent(node) {
            var p = node.parentNode;
            return p && p.invalidateShadowRenderer();
        }

        function cleanupNodes(nodes) {
            for (var i = 0, n; i < nodes.length; i++) {
                n = nodes[i];
                n.parentNode.removeChild(n);
            }
        }

        var originalImportNode = document.importNode;
        var originalCloneNode = window.Node.prototype.cloneNode;

        function cloneNode(node, deep, opt_doc) {
            var clone;
            if (opt_doc) clone = wrap(originalImportNode.call(opt_doc, unsafeUnwrap(node), false)); else clone = wrap(originalCloneNode.call(unsafeUnwrap(node), false));
            if (deep) {
                for (var child = node.firstChild; child; child = child.nextSibling) {
                    clone.appendChild(cloneNode(child, true, opt_doc));
                }
                if (node instanceof wrappers.HTMLTemplateElement) {
                    var cloneContent = clone.content;
                    for (var child = node.content.firstChild; child; child = child.nextSibling) {
                        cloneContent.appendChild(cloneNode(child, true, opt_doc));
                    }
                }
            }
            return clone;
        }

        function contains(self, child) {
            if (!child || getTreeScope(self) !== getTreeScope(child)) return false;
            for (var node = child; node; node = node.parentNode) {
                if (node === self) return true;
            }
            return false;
        }

        var OriginalNode = window.Node;

        function Node(original) {
            assert(original instanceof OriginalNode);
            EventTarget.call(this, original);
            this.parentNode_ = undefined;
            this.firstChild_ = undefined;
            this.lastChild_ = undefined;
            this.nextSibling_ = undefined;
            this.previousSibling_ = undefined;
            this.treeScope_ = undefined;
        }

        var OriginalDocumentFragment = window.DocumentFragment;
        var originalAppendChild = OriginalNode.prototype.appendChild;
        var originalCompareDocumentPosition = OriginalNode.prototype.compareDocumentPosition;
        var originalInsertBefore = OriginalNode.prototype.insertBefore;
        var originalRemoveChild = OriginalNode.prototype.removeChild;
        var originalReplaceChild = OriginalNode.prototype.replaceChild;
        var isIe = /Trident|Edge/.test(navigator.userAgent);
        var removeChildOriginalHelper = isIe ? function (parent, child) {
            try {
                originalRemoveChild.call(parent, child);
            } catch (ex) {
                if (!(parent instanceof OriginalDocumentFragment)) throw ex;
            }
        } : function (parent, child) {
            originalRemoveChild.call(parent, child);
        };
        Node.prototype = Object.create(EventTarget.prototype);
        mixin(Node.prototype, {
            appendChild: function (childWrapper) {
                return this.insertBefore(childWrapper, null);
            },
            insertBefore: function (childWrapper, refWrapper) {
                assertIsNodeWrapper(childWrapper);
                var refNode;
                if (refWrapper) {
                    if (isWrapper(refWrapper)) {
                        refNode = unwrap(refWrapper);
                    } else {
                        refNode = refWrapper;
                        refWrapper = wrap(refNode);
                    }
                } else {
                    refWrapper = null;
                    refNode = null;
                }
                refWrapper && assert(refWrapper.parentNode === this);
                var nodes;
                var previousNode = refWrapper ? refWrapper.previousSibling : this.lastChild;
                var useNative = !this.invalidateShadowRenderer() && !invalidateParent(childWrapper);
                if (useNative) nodes = collectNodesNative(childWrapper); else nodes = collectNodes(childWrapper, this, previousNode, refWrapper);
                if (useNative) {
                    ensureSameOwnerDocument(this, childWrapper);
                    clearChildNodes(this);
                    originalInsertBefore.call(unsafeUnwrap(this), unwrap(childWrapper), refNode);
                } else {
                    if (!previousNode) this.firstChild_ = nodes[0];
                    if (!refWrapper) {
                        this.lastChild_ = nodes[nodes.length - 1];
                        if (this.firstChild_ === undefined) this.firstChild_ = this.firstChild;
                    }
                    var parentNode = refNode ? refNode.parentNode : unsafeUnwrap(this);
                    if (parentNode) {
                        originalInsertBefore.call(parentNode, unwrapNodesForInsertion(this, nodes), refNode);
                    } else {
                        adoptNodesIfNeeded(this, nodes);
                    }
                }
                enqueueMutation(this, "childList", {
                    addedNodes: nodes,
                    nextSibling: refWrapper,
                    previousSibling: previousNode
                });
                nodesWereAdded(nodes, this);
                return childWrapper;
            },
            removeChild: function (childWrapper) {
                assertIsNodeWrapper(childWrapper);
                if (childWrapper.parentNode !== this) {
                    var found = false;
                    var childNodes = this.childNodes;
                    for (var ieChild = this.firstChild; ieChild; ieChild = ieChild.nextSibling) {
                        if (ieChild === childWrapper) {
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        throw new Error("NotFoundError");
                    }
                }
                var childNode = unwrap(childWrapper);
                var childWrapperNextSibling = childWrapper.nextSibling;
                var childWrapperPreviousSibling = childWrapper.previousSibling;
                if (this.invalidateShadowRenderer()) {
                    var thisFirstChild = this.firstChild;
                    var thisLastChild = this.lastChild;
                    var parentNode = childNode.parentNode;
                    if (parentNode) removeChildOriginalHelper(parentNode, childNode);
                    if (thisFirstChild === childWrapper) this.firstChild_ = childWrapperNextSibling;
                    if (thisLastChild === childWrapper) this.lastChild_ = childWrapperPreviousSibling;
                    if (childWrapperPreviousSibling) childWrapperPreviousSibling.nextSibling_ = childWrapperNextSibling;
                    if (childWrapperNextSibling) {
                        childWrapperNextSibling.previousSibling_ = childWrapperPreviousSibling;
                    }
                    childWrapper.previousSibling_ = childWrapper.nextSibling_ = childWrapper.parentNode_ = undefined;
                } else {
                    clearChildNodes(this);
                    removeChildOriginalHelper(unsafeUnwrap(this), childNode);
                }
                if (!surpressMutations) {
                    enqueueMutation(this, "childList", {
                        removedNodes: createOneElementNodeList(childWrapper),
                        nextSibling: childWrapperNextSibling,
                        previousSibling: childWrapperPreviousSibling
                    });
                }
                registerTransientObservers(this, childWrapper);
                return childWrapper;
            },
            replaceChild: function (newChildWrapper, oldChildWrapper) {
                assertIsNodeWrapper(newChildWrapper);
                var oldChildNode;
                if (isWrapper(oldChildWrapper)) {
                    oldChildNode = unwrap(oldChildWrapper);
                } else {
                    oldChildNode = oldChildWrapper;
                    oldChildWrapper = wrap(oldChildNode);
                }
                if (oldChildWrapper.parentNode !== this) {
                    throw new Error("NotFoundError");
                }
                var nextNode = oldChildWrapper.nextSibling;
                var previousNode = oldChildWrapper.previousSibling;
                var nodes;
                var useNative = !this.invalidateShadowRenderer() && !invalidateParent(newChildWrapper);
                if (useNative) {
                    nodes = collectNodesNative(newChildWrapper);
                } else {
                    if (nextNode === newChildWrapper) nextNode = newChildWrapper.nextSibling;
                    nodes = collectNodes(newChildWrapper, this, previousNode, nextNode);
                }
                if (!useNative) {
                    if (this.firstChild === oldChildWrapper) this.firstChild_ = nodes[0];
                    if (this.lastChild === oldChildWrapper) this.lastChild_ = nodes[nodes.length - 1];
                    oldChildWrapper.previousSibling_ = oldChildWrapper.nextSibling_ = oldChildWrapper.parentNode_ = undefined;
                    if (oldChildNode.parentNode) {
                        originalReplaceChild.call(oldChildNode.parentNode, unwrapNodesForInsertion(this, nodes), oldChildNode);
                    }
                } else {
                    ensureSameOwnerDocument(this, newChildWrapper);
                    clearChildNodes(this);
                    originalReplaceChild.call(unsafeUnwrap(this), unwrap(newChildWrapper), oldChildNode);
                }
                enqueueMutation(this, "childList", {
                    addedNodes: nodes,
                    removedNodes: createOneElementNodeList(oldChildWrapper),
                    nextSibling: nextNode,
                    previousSibling: previousNode
                });
                nodeWasRemoved(oldChildWrapper);
                nodesWereAdded(nodes, this);
                return oldChildWrapper;
            },
            nodeIsInserted_: function () {
                for (var child = this.firstChild; child; child = child.nextSibling) {
                    child.nodeIsInserted_();
                }
            },
            hasChildNodes: function () {
                return this.firstChild !== null;
            },
            get parentNode() {
                return this.parentNode_ !== undefined ? this.parentNode_ : wrap(unsafeUnwrap(this).parentNode);
            },
            get firstChild() {
                return this.firstChild_ !== undefined ? this.firstChild_ : wrap(unsafeUnwrap(this).firstChild);
            },
            get lastChild() {
                return this.lastChild_ !== undefined ? this.lastChild_ : wrap(unsafeUnwrap(this).lastChild);
            },
            get nextSibling() {
                return this.nextSibling_ !== undefined ? this.nextSibling_ : wrap(unsafeUnwrap(this).nextSibling);
            },
            get previousSibling() {
                return this.previousSibling_ !== undefined ? this.previousSibling_ : wrap(unsafeUnwrap(this).previousSibling);
            },
            get parentElement() {
                var p = this.parentNode;
                while (p && p.nodeType !== Node.ELEMENT_NODE) {
                    p = p.parentNode;
                }
                return p;
            },
            get textContent() {
                var s = "";
                for (var child = this.firstChild; child; child = child.nextSibling) {
                    if (child.nodeType != Node.COMMENT_NODE) {
                        s += child.textContent;
                    }
                }
                return s;
            },
            set textContent(textContent) {
                if (textContent == null) textContent = "";
                var removedNodes = snapshotNodeList(this.childNodes);
                if (this.invalidateShadowRenderer()) {
                    removeAllChildNodes(this);
                    if (textContent !== "") {
                        var textNode = unsafeUnwrap(this).ownerDocument.createTextNode(textContent);
                        this.appendChild(textNode);
                    }
                } else {
                    clearChildNodes(this);
                    unsafeUnwrap(this).textContent = textContent;
                }
                var addedNodes = snapshotNodeList(this.childNodes);
                enqueueMutation(this, "childList", {
                    addedNodes: addedNodes,
                    removedNodes: removedNodes
                });
                nodesWereRemoved(removedNodes);
                nodesWereAdded(addedNodes, this);
            },
            get childNodes() {
                var wrapperList = new NodeList();
                var i = 0;
                for (var child = this.firstChild; child; child = child.nextSibling) {
                    wrapperList[i++] = child;
                }
                wrapperList.length = i;
                return wrapperList;
            },
            cloneNode: function (deep) {
                return cloneNode(this, deep);
            },
            contains: function (child) {
                return contains(this, wrapIfNeeded(child));
            },
            compareDocumentPosition: function (otherNode) {
                return originalCompareDocumentPosition.call(unsafeUnwrap(this), unwrapIfNeeded(otherNode));
            },
            normalize: function () {
                var nodes = snapshotNodeList(this.childNodes);
                var remNodes = [];
                var s = "";
                var modNode;
                for (var i = 0, n; i < nodes.length; i++) {
                    n = nodes[i];
                    if (n.nodeType === Node.TEXT_NODE) {
                        if (!modNode && !n.data.length) this.removeChild(n); else if (!modNode) modNode = n; else {
                            s += n.data;
                            remNodes.push(n);
                        }
                    } else {
                        if (modNode && remNodes.length) {
                            modNode.data += s;
                            cleanupNodes(remNodes);
                        }
                        remNodes = [];
                        s = "";
                        modNode = null;
                        if (n.childNodes.length) n.normalize();
                    }
                }
                if (modNode && remNodes.length) {
                    modNode.data += s;
                    cleanupNodes(remNodes);
                }
            }
        });
        defineWrapGetter(Node, "ownerDocument");
        registerWrapper(OriginalNode, Node, document.createDocumentFragment());
        delete Node.prototype.querySelector;
        delete Node.prototype.querySelectorAll;
        Node.prototype = mixin(Object.create(EventTarget.prototype), Node.prototype);
        scope.cloneNode = cloneNode;
        scope.nodeWasAdded = nodeWasAdded;
        scope.nodeWasRemoved = nodeWasRemoved;
        scope.nodesWereAdded = nodesWereAdded;
        scope.nodesWereRemoved = nodesWereRemoved;
        scope.originalInsertBefore = originalInsertBefore;
        scope.originalRemoveChild = originalRemoveChild;
        scope.snapshotNodeList = snapshotNodeList;
        scope.wrappers.Node = Node;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var HTMLCollection = scope.wrappers.HTMLCollection;
        var NodeList = scope.wrappers.NodeList;
        var getTreeScope = scope.getTreeScope;
        var unsafeUnwrap = scope.unsafeUnwrap;
        var wrap = scope.wrap;
        var originalDocumentQuerySelector = document.querySelector;
        var originalElementQuerySelector = document.documentElement.querySelector;
        var originalDocumentQuerySelectorAll = document.querySelectorAll;
        var originalElementQuerySelectorAll = document.documentElement.querySelectorAll;
        var originalDocumentGetElementsByTagName = document.getElementsByTagName;
        var originalElementGetElementsByTagName = document.documentElement.getElementsByTagName;
        var originalDocumentGetElementsByTagNameNS = document.getElementsByTagNameNS;
        var originalElementGetElementsByTagNameNS = document.documentElement.getElementsByTagNameNS;
        var OriginalElement = window.Element;
        var OriginalDocument = window.HTMLDocument || window.Document;

        function filterNodeList(list, index, result, deep) {
            var wrappedItem = null;
            var root = null;
            for (var i = 0, length = list.length; i < length; i++) {
                wrappedItem = wrap(list[i]);
                if (!deep && (root = getTreeScope(wrappedItem).root)) {
                    if (root instanceof scope.wrappers.ShadowRoot) {
                        continue;
                    }
                }
                result[index++] = wrappedItem;
            }
            return index;
        }

        function shimSelector(selector) {
            return String(selector).replace(/\/deep\/|::shadow/g, " ");
        }

        function shimMatchesSelector(selector) {
            return String(selector).replace(/:host\(([^\s]+)\)/g, "$1").replace(/([^\s]):host/g, "$1").replace(":host", "*").replace(/\^|\/shadow\/|\/shadow-deep\/|::shadow|\/deep\/|::content/g, " ");
        }

        function findOne(node, selector) {
            var m, el = node.firstElementChild;
            while (el) {
                if (el.matches(selector)) return el;
                m = findOne(el, selector);
                if (m) return m;
                el = el.nextElementSibling;
            }
            return null;
        }

        function matchesSelector(el, selector) {
            return el.matches(selector);
        }

        var XHTML_NS = "http://www.w3.org/1999/xhtml";

        function matchesTagName(el, localName, localNameLowerCase) {
            var ln = el.localName;
            return ln === localName || ln === localNameLowerCase && el.namespaceURI === XHTML_NS;
        }

        function matchesEveryThing() {
            return true;
        }

        function matchesLocalNameOnly(el, ns, localName) {
            return el.localName === localName;
        }

        function matchesNameSpace(el, ns) {
            return el.namespaceURI === ns;
        }

        function matchesLocalNameNS(el, ns, localName) {
            return el.namespaceURI === ns && el.localName === localName;
        }

        function findElements(node, index, result, p, arg0, arg1) {
            var el = node.firstElementChild;
            while (el) {
                if (p(el, arg0, arg1)) result[index++] = el;
                index = findElements(el, index, result, p, arg0, arg1);
                el = el.nextElementSibling;
            }
            return index;
        }

        function querySelectorAllFiltered(p, index, result, selector, deep) {
            var target = unsafeUnwrap(this);
            var list;
            var root = getTreeScope(this).root;
            if (root instanceof scope.wrappers.ShadowRoot) {
                return findElements(this, index, result, p, selector, null);
            } else if (target instanceof OriginalElement) {
                list = originalElementQuerySelectorAll.call(target, selector);
            } else if (target instanceof OriginalDocument) {
                list = originalDocumentQuerySelectorAll.call(target, selector);
            } else {
                return findElements(this, index, result, p, selector, null);
            }
            return filterNodeList(list, index, result, deep);
        }

        var SelectorsInterface = {
            querySelector: function (selector) {
                var shimmed = shimSelector(selector);
                var deep = shimmed !== selector;
                selector = shimmed;
                var target = unsafeUnwrap(this);
                var wrappedItem;
                var root = getTreeScope(this).root;
                if (root instanceof scope.wrappers.ShadowRoot) {
                    return findOne(this, selector);
                } else if (target instanceof OriginalElement) {
                    wrappedItem = wrap(originalElementQuerySelector.call(target, selector));
                } else if (target instanceof OriginalDocument) {
                    wrappedItem = wrap(originalDocumentQuerySelector.call(target, selector));
                } else {
                    return findOne(this, selector);
                }
                if (!wrappedItem) {
                    return wrappedItem;
                } else if (!deep && (root = getTreeScope(wrappedItem).root)) {
                    if (root instanceof scope.wrappers.ShadowRoot) {
                        return findOne(this, selector);
                    }
                }
                return wrappedItem;
            },
            querySelectorAll: function (selector) {
                var shimmed = shimSelector(selector);
                var deep = shimmed !== selector;
                selector = shimmed;
                var result = new NodeList();
                result.length = querySelectorAllFiltered.call(this, matchesSelector, 0, result, selector, deep);
                return result;
            }
        };
        var MatchesInterface = {
            matches: function (selector) {
                selector = shimMatchesSelector(selector);
                return scope.originalMatches.call(unsafeUnwrap(this), selector);
            }
        };

        function getElementsByTagNameFiltered(p, index, result, localName, lowercase) {
            var target = unsafeUnwrap(this);
            var list;
            var root = getTreeScope(this).root;
            if (root instanceof scope.wrappers.ShadowRoot) {
                return findElements(this, index, result, p, localName, lowercase);
            } else if (target instanceof OriginalElement) {
                list = originalElementGetElementsByTagName.call(target, localName, lowercase);
            } else if (target instanceof OriginalDocument) {
                list = originalDocumentGetElementsByTagName.call(target, localName, lowercase);
            } else {
                return findElements(this, index, result, p, localName, lowercase);
            }
            return filterNodeList(list, index, result, false);
        }

        function getElementsByTagNameNSFiltered(p, index, result, ns, localName) {
            var target = unsafeUnwrap(this);
            var list;
            var root = getTreeScope(this).root;
            if (root instanceof scope.wrappers.ShadowRoot) {
                return findElements(this, index, result, p, ns, localName);
            } else if (target instanceof OriginalElement) {
                list = originalElementGetElementsByTagNameNS.call(target, ns, localName);
            } else if (target instanceof OriginalDocument) {
                list = originalDocumentGetElementsByTagNameNS.call(target, ns, localName);
            } else {
                return findElements(this, index, result, p, ns, localName);
            }
            return filterNodeList(list, index, result, false);
        }

        var GetElementsByInterface = {
            getElementsByTagName: function (localName) {
                var result = new HTMLCollection();
                var match = localName === "*" ? matchesEveryThing : matchesTagName;
                result.length = getElementsByTagNameFiltered.call(this, match, 0, result, localName, localName.toLowerCase());
                return result;
            },
            getElementsByClassName: function (className) {
                return this.querySelectorAll("." + className);
            },
            getElementsByTagNameNS: function (ns, localName) {
                var result = new HTMLCollection();
                var match = null;
                if (ns === "*") {
                    match = localName === "*" ? matchesEveryThing : matchesLocalNameOnly;
                } else {
                    match = localName === "*" ? matchesNameSpace : matchesLocalNameNS;
                }
                result.length = getElementsByTagNameNSFiltered.call(this, match, 0, result, ns || null, localName);
                return result;
            }
        };
        scope.GetElementsByInterface = GetElementsByInterface;
        scope.SelectorsInterface = SelectorsInterface;
        scope.MatchesInterface = MatchesInterface;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var NodeList = scope.wrappers.NodeList;

        function forwardElement(node) {
            while (node && node.nodeType !== Node.ELEMENT_NODE) {
                node = node.nextSibling;
            }
            return node;
        }

        function backwardsElement(node) {
            while (node && node.nodeType !== Node.ELEMENT_NODE) {
                node = node.previousSibling;
            }
            return node;
        }

        var ParentNodeInterface = {
            get firstElementChild() {
                return forwardElement(this.firstChild);
            },
            get lastElementChild() {
                return backwardsElement(this.lastChild);
            },
            get childElementCount() {
                var count = 0;
                for (var child = this.firstElementChild; child; child = child.nextElementSibling) {
                    count++;
                }
                return count;
            },
            get children() {
                var wrapperList = new NodeList();
                var i = 0;
                for (var child = this.firstElementChild; child; child = child.nextElementSibling) {
                    wrapperList[i++] = child;
                }
                wrapperList.length = i;
                return wrapperList;
            },
            remove: function () {
                var p = this.parentNode;
                if (p) p.removeChild(this);
            }
        };
        var ChildNodeInterface = {
            get nextElementSibling() {
                return forwardElement(this.nextSibling);
            },
            get previousElementSibling() {
                return backwardsElement(this.previousSibling);
            }
        };
        scope.ChildNodeInterface = ChildNodeInterface;
        scope.ParentNodeInterface = ParentNodeInterface;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var ChildNodeInterface = scope.ChildNodeInterface;
        var Node = scope.wrappers.Node;
        var enqueueMutation = scope.enqueueMutation;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var unsafeUnwrap = scope.unsafeUnwrap;
        var OriginalCharacterData = window.CharacterData;

        function CharacterData(node) {
            Node.call(this, node);
        }

        CharacterData.prototype = Object.create(Node.prototype);
        mixin(CharacterData.prototype, {
            get textContent() {
                return this.data;
            },
            set textContent(value) {
                this.data = value;
            },
            get data() {
                return unsafeUnwrap(this).data;
            },
            set data(value) {
                var oldValue = unsafeUnwrap(this).data;
                enqueueMutation(this, "characterData", {
                    oldValue: oldValue
                });
                unsafeUnwrap(this).data = value;
            }
        });
        mixin(CharacterData.prototype, ChildNodeInterface);
        registerWrapper(OriginalCharacterData, CharacterData, document.createTextNode(""));
        scope.wrappers.CharacterData = CharacterData;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var CharacterData = scope.wrappers.CharacterData;
        var enqueueMutation = scope.enqueueMutation;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;

        function toUInt32(x) {
            return x >>> 0;
        }

        var OriginalText = window.Text;

        function Text(node) {
            CharacterData.call(this, node);
        }

        Text.prototype = Object.create(CharacterData.prototype);
        mixin(Text.prototype, {
            splitText: function (offset) {
                offset = toUInt32(offset);
                var s = this.data;
                if (offset > s.length) throw new Error("IndexSizeError");
                var head = s.slice(0, offset);
                var tail = s.slice(offset);
                this.data = head;
                var newTextNode = this.ownerDocument.createTextNode(tail);
                if (this.parentNode) this.parentNode.insertBefore(newTextNode, this.nextSibling);
                return newTextNode;
            }
        });
        registerWrapper(OriginalText, Text, document.createTextNode(""));
        scope.wrappers.Text = Text;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        if (!window.DOMTokenList) {
            console.warn("Missing DOMTokenList prototype, please include a " + "compatible classList polyfill such as http://goo.gl/uTcepH.");
            return;
        }
        var unsafeUnwrap = scope.unsafeUnwrap;
        var enqueueMutation = scope.enqueueMutation;

        function getClass(el) {
            return unsafeUnwrap(el).getAttribute("class");
        }

        function enqueueClassAttributeChange(el, oldValue) {
            enqueueMutation(el, "attributes", {
                name: "class",
                namespace: null,
                oldValue: oldValue
            });
        }

        function invalidateClass(el) {
            scope.invalidateRendererBasedOnAttribute(el, "class");
        }

        function changeClass(tokenList, method, args) {
            var ownerElement = tokenList.ownerElement_;
            if (ownerElement == null) {
                return method.apply(tokenList, args);
            }
            var oldValue = getClass(ownerElement);
            var retv = method.apply(tokenList, args);
            if (getClass(ownerElement) !== oldValue) {
                enqueueClassAttributeChange(ownerElement, oldValue);
                invalidateClass(ownerElement);
            }
            return retv;
        }

        var oldAdd = DOMTokenList.prototype.add;
        DOMTokenList.prototype.add = function () {
            changeClass(this, oldAdd, arguments);
        };
        var oldRemove = DOMTokenList.prototype.remove;
        DOMTokenList.prototype.remove = function () {
            changeClass(this, oldRemove, arguments);
        };
        var oldToggle = DOMTokenList.prototype.toggle;
        DOMTokenList.prototype.toggle = function () {
            return changeClass(this, oldToggle, arguments);
        };
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var ChildNodeInterface = scope.ChildNodeInterface;
        var GetElementsByInterface = scope.GetElementsByInterface;
        var Node = scope.wrappers.Node;
        var ParentNodeInterface = scope.ParentNodeInterface;
        var SelectorsInterface = scope.SelectorsInterface;
        var MatchesInterface = scope.MatchesInterface;
        var addWrapNodeListMethod = scope.addWrapNodeListMethod;
        var enqueueMutation = scope.enqueueMutation;
        var mixin = scope.mixin;
        var oneOf = scope.oneOf;
        var registerWrapper = scope.registerWrapper;
        var unsafeUnwrap = scope.unsafeUnwrap;
        var wrappers = scope.wrappers;
        var OriginalElement = window.Element;
        var matchesNames = ["matches", "mozMatchesSelector", "msMatchesSelector", "webkitMatchesSelector"].filter(function (name) {
            return OriginalElement.prototype[name];
        });
        var matchesName = matchesNames[0];
        var originalMatches = OriginalElement.prototype[matchesName];

        function invalidateRendererBasedOnAttribute(element, name) {
            var p = element.parentNode;
            if (!p || !p.shadowRoot) return;
            var renderer = scope.getRendererForHost(p);
            if (renderer.dependsOnAttribute(name)) renderer.invalidate();
        }

        function enqueAttributeChange(element, name, oldValue) {
            enqueueMutation(element, "attributes", {
                name: name,
                namespace: null,
                oldValue: oldValue
            });
        }

        var classListTable = new WeakMap();

        function Element(node) {
            Node.call(this, node);
        }

        Element.prototype = Object.create(Node.prototype);
        mixin(Element.prototype, {
            createShadowRoot: function () {
                var newShadowRoot = new wrappers.ShadowRoot(this);
                unsafeUnwrap(this).polymerShadowRoot_ = newShadowRoot;
                var renderer = scope.getRendererForHost(this);
                renderer.invalidate();
                return newShadowRoot;
            },
            get shadowRoot() {
                return unsafeUnwrap(this).polymerShadowRoot_ || null;
            },
            setAttribute: function (name, value) {
                var oldValue = unsafeUnwrap(this).getAttribute(name);
                unsafeUnwrap(this).setAttribute(name, value);
                enqueAttributeChange(this, name, oldValue);
                invalidateRendererBasedOnAttribute(this, name);
            },
            removeAttribute: function (name) {
                var oldValue = unsafeUnwrap(this).getAttribute(name);
                unsafeUnwrap(this).removeAttribute(name);
                enqueAttributeChange(this, name, oldValue);
                invalidateRendererBasedOnAttribute(this, name);
            },
            get classList() {
                var list = classListTable.get(this);
                if (!list) {
                    list = unsafeUnwrap(this).classList;
                    if (!list) return;
                    list.ownerElement_ = this;
                    classListTable.set(this, list);
                }
                return list;
            },
            get className() {
                return unsafeUnwrap(this).className;
            },
            set className(v) {
                this.setAttribute("class", v);
            },
            get id() {
                return unsafeUnwrap(this).id;
            },
            set id(v) {
                this.setAttribute("id", v);
            }
        });
        matchesNames.forEach(function (name) {
            if (name !== "matches") {
                Element.prototype[name] = function (selector) {
                    return this.matches(selector);
                };
            }
        });
        if (OriginalElement.prototype.webkitCreateShadowRoot) {
            Element.prototype.webkitCreateShadowRoot = Element.prototype.createShadowRoot;
        }
        mixin(Element.prototype, ChildNodeInterface);
        mixin(Element.prototype, GetElementsByInterface);
        mixin(Element.prototype, ParentNodeInterface);
        mixin(Element.prototype, SelectorsInterface);
        mixin(Element.prototype, MatchesInterface);
        registerWrapper(OriginalElement, Element, document.createElementNS(null, "x"));
        scope.invalidateRendererBasedOnAttribute = invalidateRendererBasedOnAttribute;
        scope.matchesNames = matchesNames;
        scope.originalMatches = originalMatches;
        scope.wrappers.Element = Element;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var Element = scope.wrappers.Element;
        var defineGetter = scope.defineGetter;
        var enqueueMutation = scope.enqueueMutation;
        var mixin = scope.mixin;
        var nodesWereAdded = scope.nodesWereAdded;
        var nodesWereRemoved = scope.nodesWereRemoved;
        var registerWrapper = scope.registerWrapper;
        var snapshotNodeList = scope.snapshotNodeList;
        var unsafeUnwrap = scope.unsafeUnwrap;
        var unwrap = scope.unwrap;
        var wrap = scope.wrap;
        var wrappers = scope.wrappers;
        var escapeAttrRegExp = /[&\u00A0"]/g;
        var escapeDataRegExp = /[&\u00A0<>]/g;

        function escapeReplace(c) {
            switch (c) {
                case "&":
                    return "&";

                case "<":
                    return "<";

                case ">":
                    return ">";

                case '"':
                    return """;

                case " ":
                    return " ";
            }
        }

        function escapeAttr(s) {
            return s.replace(escapeAttrRegExp, escapeReplace);
        }

        function escapeData(s) {
            return s.replace(escapeDataRegExp, escapeReplace);
        }

        function makeSet(arr) {
            var set = {};
            for (var i = 0; i < arr.length; i++) {
                set[arr[i]] = true;
            }
            return set;
        }

        var voidElements = makeSet(["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr"]);
        var plaintextParents = makeSet(["style", "script", "xmp", "iframe", "noembed", "noframes", "plaintext", "noscript"]);

        function getOuterHTML(node, parentNode) {
            switch (node.nodeType) {
                case Node.ELEMENT_NODE:
                    var tagName = node.tagName.toLowerCase();
                    var s = "<" + tagName;
                    var attrs = node.attributes;
                    for (var i = 0, attr; attr = attrs[i]; i++) {
                        s += " " + attr.name + '="' + escapeAttr(attr.value) + '"';
                    }
                    s += ">";
                    if (voidElements[tagName]) return s;
                    return s + getInnerHTML(node) + "</" + tagName + ">";

                case Node.TEXT_NODE:
                    var data = node.data;
                    if (parentNode && plaintextParents[parentNode.localName]) return data;
                    return escapeData(data);

                case Node.COMMENT_NODE:
                    return "<!--" + node.data + "-->";

                default:
                    console.error(node);
                    throw new Error("not implemented");
            }
        }

        function getInnerHTML(node) {
            if (node instanceof wrappers.HTMLTemplateElement) node = node.content;
            var s = "";
            for (var child = node.firstChild; child; child = child.nextSibling) {
                s += getOuterHTML(child, node);
            }
            return s;
        }

        function setInnerHTML(node, value, opt_tagName) {
            var tagName = opt_tagName || "div";
            node.textContent = "";
            var tempElement = unwrap(node.ownerDocument.createElement(tagName));
            tempElement.innerHTML = value;
            var firstChild;
            while (firstChild = tempElement.firstChild) {
                node.appendChild(wrap(firstChild));
            }
        }

        var oldIe = /MSIE/.test(navigator.userAgent);
        var OriginalHTMLElement = window.HTMLElement;
        var OriginalHTMLTemplateElement = window.HTMLTemplateElement;

        function HTMLElement(node) {
            Element.call(this, node);
        }

        HTMLElement.prototype = Object.create(Element.prototype);
        mixin(HTMLElement.prototype, {
            get innerHTML() {
                return getInnerHTML(this);
            },
            set innerHTML(value) {
                if (oldIe && plaintextParents[this.localName]) {
                    this.textContent = value;
                    return;
                }
                var removedNodes = snapshotNodeList(this.childNodes);
                if (this.invalidateShadowRenderer()) {
                    if (this instanceof wrappers.HTMLTemplateElement) setInnerHTML(this.content, value); else setInnerHTML(this, value, this.tagName);
                } else if (!OriginalHTMLTemplateElement && this instanceof wrappers.HTMLTemplateElement) {
                    setInnerHTML(this.content, value);
                } else {
                    unsafeUnwrap(this).innerHTML = value;
                }
                var addedNodes = snapshotNodeList(this.childNodes);
                enqueueMutation(this, "childList", {
                    addedNodes: addedNodes,
                    removedNodes: removedNodes
                });
                nodesWereRemoved(removedNodes);
                nodesWereAdded(addedNodes, this);
            },
            get outerHTML() {
                return getOuterHTML(this, this.parentNode);
            },
            set outerHTML(value) {
                var p = this.parentNode;
                if (p) {
                    p.invalidateShadowRenderer();
                    var df = frag(p, value);
                    p.replaceChild(df, this);
                }
            },
            insertAdjacentHTML: function (position, text) {
                var contextElement, refNode;
                switch (String(position).toLowerCase()) {
                    case "beforebegin":
                        contextElement = this.parentNode;
                        refNode = this;
                        break;

                    case "afterend":
                        contextElement = this.parentNode;
                        refNode = this.nextSibling;
                        break;

                    case "afterbegin":
                        contextElement = this;
                        refNode = this.firstChild;
                        break;

                    case "beforeend":
                        contextElement = this;
                        refNode = null;
                        break;

                    default:
                        return;
                }
                var df = frag(contextElement, text);
                contextElement.insertBefore(df, refNode);
            },
            get hidden() {
                return this.hasAttribute("hidden");
            },
            set hidden(v) {
                if (v) {
                    this.setAttribute("hidden", "");
                } else {
                    this.removeAttribute("hidden");
                }
            }
        });
        function frag(contextElement, html) {
            var p = unwrap(contextElement.cloneNode(false));
            p.innerHTML = html;
            var df = unwrap(document.createDocumentFragment());
            var c;
            while (c = p.firstChild) {
                df.appendChild(c);
            }
            return wrap(df);
        }

        function getter(name) {
            return function () {
                scope.renderAllPending();
                return unsafeUnwrap(this)[name];
            };
        }

        function getterRequiresRendering(name) {
            defineGetter(HTMLElement, name, getter(name));
        }

        ["clientHeight", "clientLeft", "clientTop", "clientWidth", "offsetHeight", "offsetLeft", "offsetTop", "offsetWidth", "scrollHeight", "scrollWidth"].forEach(getterRequiresRendering);
        function getterAndSetterRequiresRendering(name) {
            Object.defineProperty(HTMLElement.prototype, name, {
                get: getter(name),
                set: function (v) {
                    scope.renderAllPending();
                    unsafeUnwrap(this)[name] = v;
                },
                configurable: true,
                enumerable: true
            });
        }

        ["scrollLeft", "scrollTop"].forEach(getterAndSetterRequiresRendering);
        function methodRequiresRendering(name) {
            Object.defineProperty(HTMLElement.prototype, name, {
                value: function () {
                    scope.renderAllPending();
                    return unsafeUnwrap(this)[name].apply(unsafeUnwrap(this), arguments);
                },
                configurable: true,
                enumerable: true
            });
        }

        ["getBoundingClientRect", "getClientRects", "scrollIntoView"].forEach(methodRequiresRendering);
        registerWrapper(OriginalHTMLElement, HTMLElement, document.createElement("b"));
        scope.wrappers.HTMLElement = HTMLElement;
        scope.getInnerHTML = getInnerHTML;
        scope.setInnerHTML = setInnerHTML;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var HTMLElement = scope.wrappers.HTMLElement;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var unsafeUnwrap = scope.unsafeUnwrap;
        var wrap = scope.wrap;
        var OriginalHTMLCanvasElement = window.HTMLCanvasElement;

        function HTMLCanvasElement(node) {
            HTMLElement.call(this, node);
        }

        HTMLCanvasElement.prototype = Object.create(HTMLElement.prototype);
        mixin(HTMLCanvasElement.prototype, {
            getContext: function () {
                var context = unsafeUnwrap(this).getContext.apply(unsafeUnwrap(this), arguments);
                return context && wrap(context);
            }
        });
        registerWrapper(OriginalHTMLCanvasElement, HTMLCanvasElement, document.createElement("canvas"));
        scope.wrappers.HTMLCanvasElement = HTMLCanvasElement;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var HTMLElement = scope.wrappers.HTMLElement;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var OriginalHTMLContentElement = window.HTMLContentElement;

        function HTMLContentElement(node) {
            HTMLElement.call(this, node);
        }

        HTMLContentElement.prototype = Object.create(HTMLElement.prototype);
        mixin(HTMLContentElement.prototype, {
            constructor: HTMLContentElement,
            get select() {
                return this.getAttribute("select");
            },
            set select(value) {
                this.setAttribute("select", value);
            },
            setAttribute: function (n, v) {
                HTMLElement.prototype.setAttribute.call(this, n, v);
                if (String(n).toLowerCase() === "select") this.invalidateShadowRenderer(true);
            }
        });
        if (OriginalHTMLContentElement) registerWrapper(OriginalHTMLContentElement, HTMLContentElement);
        scope.wrappers.HTMLContentElement = HTMLContentElement;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var HTMLElement = scope.wrappers.HTMLElement;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var wrapHTMLCollection = scope.wrapHTMLCollection;
        var unwrap = scope.unwrap;
        var OriginalHTMLFormElement = window.HTMLFormElement;

        function HTMLFormElement(node) {
            HTMLElement.call(this, node);
        }

        HTMLFormElement.prototype = Object.create(HTMLElement.prototype);
        mixin(HTMLFormElement.prototype, {
            get elements() {
                return wrapHTMLCollection(unwrap(this).elements);
            }
        });
        registerWrapper(OriginalHTMLFormElement, HTMLFormElement, document.createElement("form"));
        scope.wrappers.HTMLFormElement = HTMLFormElement;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var HTMLElement = scope.wrappers.HTMLElement;
        var registerWrapper = scope.registerWrapper;
        var unwrap = scope.unwrap;
        var rewrap = scope.rewrap;
        var OriginalHTMLImageElement = window.HTMLImageElement;

        function HTMLImageElement(node) {
            HTMLElement.call(this, node);
        }

        HTMLImageElement.prototype = Object.create(HTMLElement.prototype);
        registerWrapper(OriginalHTMLImageElement, HTMLImageElement, document.createElement("img"));
        function Image(width, height) {
            if (!(this instanceof Image)) {
                throw new TypeError("DOM object constructor cannot be called as a function.");
            }
            var node = unwrap(document.createElement("img"));
            HTMLElement.call(this, node);
            rewrap(node, this);
            if (width !== undefined) node.width = width;
            if (height !== undefined) node.height = height;
        }

        Image.prototype = HTMLImageElement.prototype;
        scope.wrappers.HTMLImageElement = HTMLImageElement;
        scope.wrappers.Image = Image;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var HTMLElement = scope.wrappers.HTMLElement;
        var mixin = scope.mixin;
        var NodeList = scope.wrappers.NodeList;
        var registerWrapper = scope.registerWrapper;
        var OriginalHTMLShadowElement = window.HTMLShadowElement;

        function HTMLShadowElement(node) {
            HTMLElement.call(this, node);
        }

        HTMLShadowElement.prototype = Object.create(HTMLElement.prototype);
        HTMLShadowElement.prototype.constructor = HTMLShadowElement;
        if (OriginalHTMLShadowElement) registerWrapper(OriginalHTMLShadowElement, HTMLShadowElement);
        scope.wrappers.HTMLShadowElement = HTMLShadowElement;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var HTMLElement = scope.wrappers.HTMLElement;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var unsafeUnwrap = scope.unsafeUnwrap;
        var unwrap = scope.unwrap;
        var wrap = scope.wrap;
        var contentTable = new WeakMap();
        var templateContentsOwnerTable = new WeakMap();

        function getTemplateContentsOwner(doc) {
            if (!doc.defaultView) return doc;
            var d = templateContentsOwnerTable.get(doc);
            if (!d) {
                d = doc.implementation.createHTMLDocument("");
                while (d.lastChild) {
                    d.removeChild(d.lastChild);
                }
                templateContentsOwnerTable.set(doc, d);
            }
            return d;
        }

        function extractContent(templateElement) {
            var doc = getTemplateContentsOwner(templateElement.ownerDocument);
            var df = unwrap(doc.createDocumentFragment());
            var child;
            while (child = templateElement.firstChild) {
                df.appendChild(child);
            }
            return df;
        }

        var OriginalHTMLTemplateElement = window.HTMLTemplateElement;

        function HTMLTemplateElement(node) {
            HTMLElement.call(this, node);
            if (!OriginalHTMLTemplateElement) {
                var content = extractContent(node);
                contentTable.set(this, wrap(content));
            }
        }

        HTMLTemplateElement.prototype = Object.create(HTMLElement.prototype);
        mixin(HTMLTemplateElement.prototype, {
            constructor: HTMLTemplateElement,
            get content() {
                if (OriginalHTMLTemplateElement) return wrap(unsafeUnwrap(this).content);
                return contentTable.get(this);
            }
        });
        if (OriginalHTMLTemplateElement) registerWrapper(OriginalHTMLTemplateElement, HTMLTemplateElement);
        scope.wrappers.HTMLTemplateElement = HTMLTemplateElement;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var HTMLElement = scope.wrappers.HTMLElement;
        var registerWrapper = scope.registerWrapper;
        var OriginalHTMLMediaElement = window.HTMLMediaElement;
        if (!OriginalHTMLMediaElement) return;
        function HTMLMediaElement(node) {
            HTMLElement.call(this, node);
        }

        HTMLMediaElement.prototype = Object.create(HTMLElement.prototype);
        registerWrapper(OriginalHTMLMediaElement, HTMLMediaElement, document.createElement("audio"));
        scope.wrappers.HTMLMediaElement = HTMLMediaElement;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var HTMLMediaElement = scope.wrappers.HTMLMediaElement;
        var registerWrapper = scope.registerWrapper;
        var unwrap = scope.unwrap;
        var rewrap = scope.rewrap;
        var OriginalHTMLAudioElement = window.HTMLAudioElement;
        if (!OriginalHTMLAudioElement) return;
        function HTMLAudioElement(node) {
            HTMLMediaElement.call(this, node);
        }

        HTMLAudioElement.prototype = Object.create(HTMLMediaElement.prototype);
        registerWrapper(OriginalHTMLAudioElement, HTMLAudioElement, document.createElement("audio"));
        function Audio(src) {
            if (!(this instanceof Audio)) {
                throw new TypeError("DOM object constructor cannot be called as a function.");
            }
            var node = unwrap(document.createElement("audio"));
            HTMLMediaElement.call(this, node);
            rewrap(node, this);
            node.setAttribute("preload", "auto");
            if (src !== undefined) node.setAttribute("src", src);
        }

        Audio.prototype = HTMLAudioElement.prototype;
        scope.wrappers.HTMLAudioElement = HTMLAudioElement;
        scope.wrappers.Audio = Audio;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var HTMLElement = scope.wrappers.HTMLElement;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var rewrap = scope.rewrap;
        var unwrap = scope.unwrap;
        var wrap = scope.wrap;
        var OriginalHTMLOptionElement = window.HTMLOptionElement;

        function trimText(s) {
            return s.replace(/\s+/g, " ").trim();
        }

        function HTMLOptionElement(node) {
            HTMLElement.call(this, node);
        }

        HTMLOptionElement.prototype = Object.create(HTMLElement.prototype);
        mixin(HTMLOptionElement.prototype, {
            get text() {
                return trimText(this.textContent);
            },
            set text(value) {
                this.textContent = trimText(String(value));
            },
            get form() {
                return wrap(unwrap(this).form);
            }
        });
        registerWrapper(OriginalHTMLOptionElement, HTMLOptionElement, document.createElement("option"));
        function Option(text, value, defaultSelected, selected) {
            if (!(this instanceof Option)) {
                throw new TypeError("DOM object constructor cannot be called as a function.");
            }
            var node = unwrap(document.createElement("option"));
            HTMLElement.call(this, node);
            rewrap(node, this);
            if (text !== undefined) node.text = text;
            if (value !== undefined) node.setAttribute("value", value);
            if (defaultSelected === true) node.setAttribute("selected", "");
            node.selected = selected === true;
        }

        Option.prototype = HTMLOptionElement.prototype;
        scope.wrappers.HTMLOptionElement = HTMLOptionElement;
        scope.wrappers.Option = Option;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var HTMLElement = scope.wrappers.HTMLElement;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var unwrap = scope.unwrap;
        var wrap = scope.wrap;
        var OriginalHTMLSelectElement = window.HTMLSelectElement;

        function HTMLSelectElement(node) {
            HTMLElement.call(this, node);
        }

        HTMLSelectElement.prototype = Object.create(HTMLElement.prototype);
        mixin(HTMLSelectElement.prototype, {
            add: function (element, before) {
                if (typeof before === "object") before = unwrap(before);
                unwrap(this).add(unwrap(element), before);
            },
            remove: function (indexOrNode) {
                if (indexOrNode === undefined) {
                    HTMLElement.prototype.remove.call(this);
                    return;
                }
                if (typeof indexOrNode === "object") indexOrNode = unwrap(indexOrNode);
                unwrap(this).remove(indexOrNode);
            },
            get form() {
                return wrap(unwrap(this).form);
            }
        });
        registerWrapper(OriginalHTMLSelectElement, HTMLSelectElement, document.createElement("select"));
        scope.wrappers.HTMLSelectElement = HTMLSelectElement;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var HTMLElement = scope.wrappers.HTMLElement;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var unwrap = scope.unwrap;
        var wrap = scope.wrap;
        var wrapHTMLCollection = scope.wrapHTMLCollection;
        var OriginalHTMLTableElement = window.HTMLTableElement;

        function HTMLTableElement(node) {
            HTMLElement.call(this, node);
        }

        HTMLTableElement.prototype = Object.create(HTMLElement.prototype);
        mixin(HTMLTableElement.prototype, {
            get caption() {
                return wrap(unwrap(this).caption);
            },
            createCaption: function () {
                return wrap(unwrap(this).createCaption());
            },
            get tHead() {
                return wrap(unwrap(this).tHead);
            },
            createTHead: function () {
                return wrap(unwrap(this).createTHead());
            },
            createTFoot: function () {
                return wrap(unwrap(this).createTFoot());
            },
            get tFoot() {
                return wrap(unwrap(this).tFoot);
            },
            get tBodies() {
                return wrapHTMLCollection(unwrap(this).tBodies);
            },
            createTBody: function () {
                return wrap(unwrap(this).createTBody());
            },
            get rows() {
                return wrapHTMLCollection(unwrap(this).rows);
            },
            insertRow: function (index) {
                return wrap(unwrap(this).insertRow(index));
            }
        });
        registerWrapper(OriginalHTMLTableElement, HTMLTableElement, document.createElement("table"));
        scope.wrappers.HTMLTableElement = HTMLTableElement;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var HTMLElement = scope.wrappers.HTMLElement;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var wrapHTMLCollection = scope.wrapHTMLCollection;
        var unwrap = scope.unwrap;
        var wrap = scope.wrap;
        var OriginalHTMLTableSectionElement = window.HTMLTableSectionElement;

        function HTMLTableSectionElement(node) {
            HTMLElement.call(this, node);
        }

        HTMLTableSectionElement.prototype = Object.create(HTMLElement.prototype);
        mixin(HTMLTableSectionElement.prototype, {
            constructor: HTMLTableSectionElement,
            get rows() {
                return wrapHTMLCollection(unwrap(this).rows);
            },
            insertRow: function (index) {
                return wrap(unwrap(this).insertRow(index));
            }
        });
        registerWrapper(OriginalHTMLTableSectionElement, HTMLTableSectionElement, document.createElement("thead"));
        scope.wrappers.HTMLTableSectionElement = HTMLTableSectionElement;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var HTMLElement = scope.wrappers.HTMLElement;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var wrapHTMLCollection = scope.wrapHTMLCollection;
        var unwrap = scope.unwrap;
        var wrap = scope.wrap;
        var OriginalHTMLTableRowElement = window.HTMLTableRowElement;

        function HTMLTableRowElement(node) {
            HTMLElement.call(this, node);
        }

        HTMLTableRowElement.prototype = Object.create(HTMLElement.prototype);
        mixin(HTMLTableRowElement.prototype, {
            get cells() {
                return wrapHTMLCollection(unwrap(this).cells);
            },
            insertCell: function (index) {
                return wrap(unwrap(this).insertCell(index));
            }
        });
        registerWrapper(OriginalHTMLTableRowElement, HTMLTableRowElement, document.createElement("tr"));
        scope.wrappers.HTMLTableRowElement = HTMLTableRowElement;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var HTMLContentElement = scope.wrappers.HTMLContentElement;
        var HTMLElement = scope.wrappers.HTMLElement;
        var HTMLShadowElement = scope.wrappers.HTMLShadowElement;
        var HTMLTemplateElement = scope.wrappers.HTMLTemplateElement;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var OriginalHTMLUnknownElement = window.HTMLUnknownElement;

        function HTMLUnknownElement(node) {
            switch (node.localName) {
                case "content":
                    return new HTMLContentElement(node);

                case "shadow":
                    return new HTMLShadowElement(node);

                case "template":
                    return new HTMLTemplateElement(node);
            }
            HTMLElement.call(this, node);
        }

        HTMLUnknownElement.prototype = Object.create(HTMLElement.prototype);
        registerWrapper(OriginalHTMLUnknownElement, HTMLUnknownElement);
        scope.wrappers.HTMLUnknownElement = HTMLUnknownElement;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var Element = scope.wrappers.Element;
        var HTMLElement = scope.wrappers.HTMLElement;
        var registerObject = scope.registerObject;
        var defineWrapGetter = scope.defineWrapGetter;
        var SVG_NS = "http://www.w3.org/2000/svg";
        var svgTitleElement = document.createElementNS(SVG_NS, "title");
        var SVGTitleElement = registerObject(svgTitleElement);
        var SVGElement = Object.getPrototypeOf(SVGTitleElement.prototype).constructor;
        if (!("classList" in svgTitleElement)) {
            var descr = Object.getOwnPropertyDescriptor(Element.prototype, "classList");
            Object.defineProperty(HTMLElement.prototype, "classList", descr);
            delete Element.prototype.classList;
        }
        defineWrapGetter(SVGElement, "ownerSVGElement");
        scope.wrappers.SVGElement = SVGElement;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var unwrap = scope.unwrap;
        var wrap = scope.wrap;
        var OriginalSVGUseElement = window.SVGUseElement;
        var SVG_NS = "http://www.w3.org/2000/svg";
        var gWrapper = wrap(document.createElementNS(SVG_NS, "g"));
        var useElement = document.createElementNS(SVG_NS, "use");
        var SVGGElement = gWrapper.constructor;
        var parentInterfacePrototype = Object.getPrototypeOf(SVGGElement.prototype);
        var parentInterface = parentInterfacePrototype.constructor;

        function SVGUseElement(impl) {
            parentInterface.call(this, impl);
        }

        SVGUseElement.prototype = Object.create(parentInterfacePrototype);
        if ("instanceRoot" in useElement) {
            mixin(SVGUseElement.prototype, {
                get instanceRoot() {
                    return wrap(unwrap(this).instanceRoot);
                },
                get animatedInstanceRoot() {
                    return wrap(unwrap(this).animatedInstanceRoot);
                }
            });
        }
        registerWrapper(OriginalSVGUseElement, SVGUseElement, useElement);
        scope.wrappers.SVGUseElement = SVGUseElement;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var EventTarget = scope.wrappers.EventTarget;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var unsafeUnwrap = scope.unsafeUnwrap;
        var wrap = scope.wrap;
        var OriginalSVGElementInstance = window.SVGElementInstance;
        if (!OriginalSVGElementInstance) return;
        function SVGElementInstance(impl) {
            EventTarget.call(this, impl);
        }

        SVGElementInstance.prototype = Object.create(EventTarget.prototype);
        mixin(SVGElementInstance.prototype, {
            get correspondingElement() {
                return wrap(unsafeUnwrap(this).correspondingElement);
            },
            get correspondingUseElement() {
                return wrap(unsafeUnwrap(this).correspondingUseElement);
            },
            get parentNode() {
                return wrap(unsafeUnwrap(this).parentNode);
            },
            get childNodes() {
                throw new Error("Not implemented");
            },
            get firstChild() {
                return wrap(unsafeUnwrap(this).firstChild);
            },
            get lastChild() {
                return wrap(unsafeUnwrap(this).lastChild);
            },
            get previousSibling() {
                return wrap(unsafeUnwrap(this).previousSibling);
            },
            get nextSibling() {
                return wrap(unsafeUnwrap(this).nextSibling);
            }
        });
        registerWrapper(OriginalSVGElementInstance, SVGElementInstance);
        scope.wrappers.SVGElementInstance = SVGElementInstance;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var setWrapper = scope.setWrapper;
        var unsafeUnwrap = scope.unsafeUnwrap;
        var unwrap = scope.unwrap;
        var unwrapIfNeeded = scope.unwrapIfNeeded;
        var wrap = scope.wrap;
        var OriginalCanvasRenderingContext2D = window.CanvasRenderingContext2D;

        function CanvasRenderingContext2D(impl) {
            setWrapper(impl, this);
        }

        mixin(CanvasRenderingContext2D.prototype, {
            get canvas() {
                return wrap(unsafeUnwrap(this).canvas);
            },
            drawImage: function () {
                arguments[0] = unwrapIfNeeded(arguments[0]);
                unsafeUnwrap(this).drawImage.apply(unsafeUnwrap(this), arguments);
            },
            createPattern: function () {
                arguments[0] = unwrap(arguments[0]);
                return unsafeUnwrap(this).createPattern.apply(unsafeUnwrap(this), arguments);
            }
        });
        registerWrapper(OriginalCanvasRenderingContext2D, CanvasRenderingContext2D, document.createElement("canvas").getContext("2d"));
        scope.wrappers.CanvasRenderingContext2D = CanvasRenderingContext2D;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var setWrapper = scope.setWrapper;
        var unsafeUnwrap = scope.unsafeUnwrap;
        var unwrapIfNeeded = scope.unwrapIfNeeded;
        var wrap = scope.wrap;
        var OriginalWebGLRenderingContext = window.WebGLRenderingContext;
        if (!OriginalWebGLRenderingContext) return;
        function WebGLRenderingContext(impl) {
            setWrapper(impl, this);
        }

        mixin(WebGLRenderingContext.prototype, {
            get canvas() {
                return wrap(unsafeUnwrap(this).canvas);
            },
            texImage2D: function () {
                arguments[5] = unwrapIfNeeded(arguments[5]);
                unsafeUnwrap(this).texImage2D.apply(unsafeUnwrap(this), arguments);
            },
            texSubImage2D: function () {
                arguments[6] = unwrapIfNeeded(arguments[6]);
                unsafeUnwrap(this).texSubImage2D.apply(unsafeUnwrap(this), arguments);
            }
        });
        var instanceProperties = /WebKit/.test(navigator.userAgent) ? {
            drawingBufferHeight: null,
            drawingBufferWidth: null
        } : {};
        registerWrapper(OriginalWebGLRenderingContext, WebGLRenderingContext, instanceProperties);
        scope.wrappers.WebGLRenderingContext = WebGLRenderingContext;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var registerWrapper = scope.registerWrapper;
        var setWrapper = scope.setWrapper;
        var unsafeUnwrap = scope.unsafeUnwrap;
        var unwrap = scope.unwrap;
        var unwrapIfNeeded = scope.unwrapIfNeeded;
        var wrap = scope.wrap;
        var OriginalRange = window.Range;

        function Range(impl) {
            setWrapper(impl, this);
        }

        Range.prototype = {
            get startContainer() {
                return wrap(unsafeUnwrap(this).startContainer);
            },
            get endContainer() {
                return wrap(unsafeUnwrap(this).endContainer);
            },
            get commonAncestorContainer() {
                return wrap(unsafeUnwrap(this).commonAncestorContainer);
            },
            setStart: function (refNode, offset) {
                unsafeUnwrap(this).setStart(unwrapIfNeeded(refNode), offset);
            },
            setEnd: function (refNode, offset) {
                unsafeUnwrap(this).setEnd(unwrapIfNeeded(refNode), offset);
            },
            setStartBefore: function (refNode) {
                unsafeUnwrap(this).setStartBefore(unwrapIfNeeded(refNode));
            },
            setStartAfter: function (refNode) {
                unsafeUnwrap(this).setStartAfter(unwrapIfNeeded(refNode));
            },
            setEndBefore: function (refNode) {
                unsafeUnwrap(this).setEndBefore(unwrapIfNeeded(refNode));
            },
            setEndAfter: function (refNode) {
                unsafeUnwrap(this).setEndAfter(unwrapIfNeeded(refNode));
            },
            selectNode: function (refNode) {
                unsafeUnwrap(this).selectNode(unwrapIfNeeded(refNode));
            },
            selectNodeContents: function (refNode) {
                unsafeUnwrap(this).selectNodeContents(unwrapIfNeeded(refNode));
            },
            compareBoundaryPoints: function (how, sourceRange) {
                return unsafeUnwrap(this).compareBoundaryPoints(how, unwrap(sourceRange));
            },
            extractContents: function () {
                return wrap(unsafeUnwrap(this).extractContents());
            },
            cloneContents: function () {
                return wrap(unsafeUnwrap(this).cloneContents());
            },
            insertNode: function (node) {
                unsafeUnwrap(this).insertNode(unwrapIfNeeded(node));
            },
            surroundContents: function (newParent) {
                unsafeUnwrap(this).surroundContents(unwrapIfNeeded(newParent));
            },
            cloneRange: function () {
                return wrap(unsafeUnwrap(this).cloneRange());
            },
            isPointInRange: function (node, offset) {
                return unsafeUnwrap(this).isPointInRange(unwrapIfNeeded(node), offset);
            },
            comparePoint: function (node, offset) {
                return unsafeUnwrap(this).comparePoint(unwrapIfNeeded(node), offset);
            },
            intersectsNode: function (node) {
                return unsafeUnwrap(this).intersectsNode(unwrapIfNeeded(node));
            },
            toString: function () {
                return unsafeUnwrap(this).toString();
            }
        };
        if (OriginalRange.prototype.createContextualFragment) {
            Range.prototype.createContextualFragment = function (html) {
                return wrap(unsafeUnwrap(this).createContextualFragment(html));
            };
        }
        registerWrapper(window.Range, Range, document.createRange());
        scope.wrappers.Range = Range;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var GetElementsByInterface = scope.GetElementsByInterface;
        var ParentNodeInterface = scope.ParentNodeInterface;
        var SelectorsInterface = scope.SelectorsInterface;
        var mixin = scope.mixin;
        var registerObject = scope.registerObject;
        var DocumentFragment = registerObject(document.createDocumentFragment());
        mixin(DocumentFragment.prototype, ParentNodeInterface);
        mixin(DocumentFragment.prototype, SelectorsInterface);
        mixin(DocumentFragment.prototype, GetElementsByInterface);
        var Comment = registerObject(document.createComment(""));
        scope.wrappers.Comment = Comment;
        scope.wrappers.DocumentFragment = DocumentFragment;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var DocumentFragment = scope.wrappers.DocumentFragment;
        var TreeScope = scope.TreeScope;
        var elementFromPoint = scope.elementFromPoint;
        var getInnerHTML = scope.getInnerHTML;
        var getTreeScope = scope.getTreeScope;
        var mixin = scope.mixin;
        var rewrap = scope.rewrap;
        var setInnerHTML = scope.setInnerHTML;
        var unsafeUnwrap = scope.unsafeUnwrap;
        var unwrap = scope.unwrap;
        var shadowHostTable = new WeakMap();
        var nextOlderShadowTreeTable = new WeakMap();
        var spaceCharRe = /[ \t\n\r\f]/;

        function ShadowRoot(hostWrapper) {
            var node = unwrap(unsafeUnwrap(hostWrapper).ownerDocument.createDocumentFragment());
            DocumentFragment.call(this, node);
            rewrap(node, this);
            var oldShadowRoot = hostWrapper.shadowRoot;
            nextOlderShadowTreeTable.set(this, oldShadowRoot);
            this.treeScope_ = new TreeScope(this, getTreeScope(oldShadowRoot || hostWrapper));
            shadowHostTable.set(this, hostWrapper);
        }

        ShadowRoot.prototype = Object.create(DocumentFragment.prototype);
        mixin(ShadowRoot.prototype, {
            constructor: ShadowRoot,
            get innerHTML() {
                return getInnerHTML(this);
            },
            set innerHTML(value) {
                setInnerHTML(this, value);
                this.invalidateShadowRenderer();
            },
            get olderShadowRoot() {
                return nextOlderShadowTreeTable.get(this) || null;
            },
            get host() {
                return shadowHostTable.get(this) || null;
            },
            invalidateShadowRenderer: function () {
                return shadowHostTable.get(this).invalidateShadowRenderer();
            },
            elementFromPoint: function (x, y) {
                return elementFromPoint(this, this.ownerDocument, x, y);
            },
            getElementById: function (id) {
                if (spaceCharRe.test(id)) return null;
                return this.querySelector('[id="' + id + '"]');
            }
        });
        scope.wrappers.ShadowRoot = ShadowRoot;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var Element = scope.wrappers.Element;
        var HTMLContentElement = scope.wrappers.HTMLContentElement;
        var HTMLShadowElement = scope.wrappers.HTMLShadowElement;
        var Node = scope.wrappers.Node;
        var ShadowRoot = scope.wrappers.ShadowRoot;
        var assert = scope.assert;
        var getTreeScope = scope.getTreeScope;
        var mixin = scope.mixin;
        var oneOf = scope.oneOf;
        var unsafeUnwrap = scope.unsafeUnwrap;
        var unwrap = scope.unwrap;
        var wrap = scope.wrap;
        var ArraySplice = scope.ArraySplice;

        function updateWrapperUpAndSideways(wrapper) {
            wrapper.previousSibling_ = wrapper.previousSibling;
            wrapper.nextSibling_ = wrapper.nextSibling;
            wrapper.parentNode_ = wrapper.parentNode;
        }

        function updateWrapperDown(wrapper) {
            wrapper.firstChild_ = wrapper.firstChild;
            wrapper.lastChild_ = wrapper.lastChild;
        }

        function updateAllChildNodes(parentNodeWrapper) {
            assert(parentNodeWrapper instanceof Node);
            for (var childWrapper = parentNodeWrapper.firstChild; childWrapper; childWrapper = childWrapper.nextSibling) {
                updateWrapperUpAndSideways(childWrapper);
            }
            updateWrapperDown(parentNodeWrapper);
        }

        function insertBefore(parentNodeWrapper, newChildWrapper, refChildWrapper) {
            var parentNode = unwrap(parentNodeWrapper);
            var newChild = unwrap(newChildWrapper);
            var refChild = refChildWrapper ? unwrap(refChildWrapper) : null;
            remove(newChildWrapper);
            updateWrapperUpAndSideways(newChildWrapper);
            if (!refChildWrapper) {
                parentNodeWrapper.lastChild_ = parentNodeWrapper.lastChild;
                if (parentNodeWrapper.lastChild === parentNodeWrapper.firstChild) parentNodeWrapper.firstChild_ = parentNodeWrapper.firstChild;
                var lastChildWrapper = wrap(parentNode.lastChild);
                if (lastChildWrapper) lastChildWrapper.nextSibling_ = lastChildWrapper.nextSibling;
            } else {
                if (parentNodeWrapper.firstChild === refChildWrapper) parentNodeWrapper.firstChild_ = refChildWrapper;
                refChildWrapper.previousSibling_ = refChildWrapper.previousSibling;
            }
            scope.originalInsertBefore.call(parentNode, newChild, refChild);
        }

        function remove(nodeWrapper) {
            var node = unwrap(nodeWrapper);
            var parentNode = node.parentNode;
            if (!parentNode) return;
            var parentNodeWrapper = wrap(parentNode);
            updateWrapperUpAndSideways(nodeWrapper);
            if (nodeWrapper.previousSibling) nodeWrapper.previousSibling.nextSibling_ = nodeWrapper;
            if (nodeWrapper.nextSibling) nodeWrapper.nextSibling.previousSibling_ = nodeWrapper;
            if (parentNodeWrapper.lastChild === nodeWrapper) parentNodeWrapper.lastChild_ = nodeWrapper;
            if (parentNodeWrapper.firstChild === nodeWrapper) parentNodeWrapper.firstChild_ = nodeWrapper;
            scope.originalRemoveChild.call(parentNode, node);
        }

        var distributedNodesTable = new WeakMap();
        var destinationInsertionPointsTable = new WeakMap();
        var rendererForHostTable = new WeakMap();

        function resetDistributedNodes(insertionPoint) {
            distributedNodesTable.set(insertionPoint, []);
        }

        function getDistributedNodes(insertionPoint) {
            var rv = distributedNodesTable.get(insertionPoint);
            if (!rv) distributedNodesTable.set(insertionPoint, rv = []);
            return rv;
        }

        function getChildNodesSnapshot(node) {
            var result = [], i = 0;
            for (var child = node.firstChild; child; child = child.nextSibling) {
                result[i++] = child;
            }
            return result;
        }

        var request = oneOf(window, ["requestAnimationFrame", "mozRequestAnimationFrame", "webkitRequestAnimationFrame", "setTimeout"]);
        var pendingDirtyRenderers = [];
        var renderTimer;

        function renderAllPending() {
            for (var i = 0; i < pendingDirtyRenderers.length; i++) {
                var renderer = pendingDirtyRenderers[i];
                var parentRenderer = renderer.parentRenderer;
                if (parentRenderer && parentRenderer.dirty) continue;
                renderer.render();
            }
            pendingDirtyRenderers = [];
        }

        function handleRequestAnimationFrame() {
            renderTimer = null;
            renderAllPending();
        }

        function getRendererForHost(host) {
            var renderer = rendererForHostTable.get(host);
            if (!renderer) {
                renderer = new ShadowRenderer(host);
                rendererForHostTable.set(host, renderer);
            }
            return renderer;
        }

        function getShadowRootAncestor(node) {
            var root = getTreeScope(node).root;
            if (root instanceof ShadowRoot) return root;
            return null;
        }

        function getRendererForShadowRoot(shadowRoot) {
            return getRendererForHost(shadowRoot.host);
        }

        var spliceDiff = new ArraySplice();
        spliceDiff.equals = function (renderNode, rawNode) {
            return unwrap(renderNode.node) === rawNode;
        };
        function RenderNode(node) {
            this.skip = false;
            this.node = node;
            this.childNodes = [];
        }

        RenderNode.prototype = {
            append: function (node) {
                var rv = new RenderNode(node);
                this.childNodes.push(rv);
                return rv;
            },
            sync: function (opt_added) {
                if (this.skip) return;
                var nodeWrapper = this.node;
                var newChildren = this.childNodes;
                var oldChildren = getChildNodesSnapshot(unwrap(nodeWrapper));
                var added = opt_added || new WeakMap();
                var splices = spliceDiff.calculateSplices(newChildren, oldChildren);
                var newIndex = 0, oldIndex = 0;
                var lastIndex = 0;
                for (var i = 0; i < splices.length; i++) {
                    var splice = splices[i];
                    for (; lastIndex < splice.index; lastIndex++) {
                        oldIndex++;
                        newChildren[newIndex++].sync(added);
                    }
                    var removedCount = splice.removed.length;
                    for (var j = 0; j < removedCount; j++) {
                        var wrapper = wrap(oldChildren[oldIndex++]);
                        if (!added.get(wrapper)) remove(wrapper);
                    }
                    var addedCount = splice.addedCount;
                    var refNode = oldChildren[oldIndex] && wrap(oldChildren[oldIndex]);
                    for (var j = 0; j < addedCount; j++) {
                        var newChildRenderNode = newChildren[newIndex++];
                        var newChildWrapper = newChildRenderNode.node;
                        insertBefore(nodeWrapper, newChildWrapper, refNode);
                        added.set(newChildWrapper, true);
                        newChildRenderNode.sync(added);
                    }
                    lastIndex += addedCount;
                }
                for (var i = lastIndex; i < newChildren.length; i++) {
                    newChildren[i].sync(added);
                }
            }
        };
        function ShadowRenderer(host) {
            this.host = host;
            this.dirty = false;
            this.invalidateAttributes();
            this.associateNode(host);
        }

        ShadowRenderer.prototype = {
            render: function (opt_renderNode) {
                if (!this.dirty) return;
                this.invalidateAttributes();
                var host = this.host;
                this.distribution(host);
                var renderNode = opt_renderNode || new RenderNode(host);
                this.buildRenderTree(renderNode, host);
                var topMostRenderer = !opt_renderNode;
                if (topMostRenderer) renderNode.sync();
                this.dirty = false;
            },
            get parentRenderer() {
                return getTreeScope(this.host).renderer;
            },
            invalidate: function () {
                if (!this.dirty) {
                    this.dirty = true;
                    var parentRenderer = this.parentRenderer;
                    if (parentRenderer) parentRenderer.invalidate();
                    pendingDirtyRenderers.push(this);
                    if (renderTimer) return;
                    renderTimer = window[request](handleRequestAnimationFrame, 0);
                }
            },
            distribution: function (root) {
                this.resetAllSubtrees(root);
                this.distributionResolution(root);
            },
            resetAll: function (node) {
                if (isInsertionPoint(node)) resetDistributedNodes(node); else resetDestinationInsertionPoints(node);
                this.resetAllSubtrees(node);
            },
            resetAllSubtrees: function (node) {
                for (var child = node.firstChild; child; child = child.nextSibling) {
                    this.resetAll(child);
                }
                if (node.shadowRoot) this.resetAll(node.shadowRoot);
                if (node.olderShadowRoot) this.resetAll(node.olderShadowRoot);
            },
            distributionResolution: function (node) {
                if (isShadowHost(node)) {
                    var shadowHost = node;
                    var pool = poolPopulation(shadowHost);
                    var shadowTrees = getShadowTrees(shadowHost);
                    for (var i = 0; i < shadowTrees.length; i++) {
                        this.poolDistribution(shadowTrees[i], pool);
                    }
                    for (var i = shadowTrees.length - 1; i >= 0; i--) {
                        var shadowTree = shadowTrees[i];
                        var shadow = getShadowInsertionPoint(shadowTree);
                        if (shadow) {
                            var olderShadowRoot = shadowTree.olderShadowRoot;
                            if (olderShadowRoot) {
                                pool = poolPopulation(olderShadowRoot);
                            }
                            for (var j = 0; j < pool.length; j++) {
                                destributeNodeInto(pool[j], shadow);
                            }
                        }
                        this.distributionResolution(shadowTree);
                    }
                }
                for (var child = node.firstChild; child; child = child.nextSibling) {
                    this.distributionResolution(child);
                }
            },
            poolDistribution: function (node, pool) {
                if (node instanceof HTMLShadowElement) return;
                if (node instanceof HTMLContentElement) {
                    var content = node;
                    this.updateDependentAttributes(content.getAttribute("select"));
                    var anyDistributed = false;
                    for (var i = 0; i < pool.length; i++) {
                        var node = pool[i];
                        if (!node) continue;
                        if (matches(node, content)) {
                            destributeNodeInto(node, content);
                            pool[i] = undefined;
                            anyDistributed = true;
                        }
                    }
                    if (!anyDistributed) {
                        for (var child = content.firstChild; child; child = child.nextSibling) {
                            destributeNodeInto(child, content);
                        }
                    }
                    return;
                }
                for (var child = node.firstChild; child; child = child.nextSibling) {
                    this.poolDistribution(child, pool);
                }
            },
            buildRenderTree: function (renderNode, node) {
                var children = this.compose(node);
                for (var i = 0; i < children.length; i++) {
                    var child = children[i];
                    var childRenderNode = renderNode.append(child);
                    this.buildRenderTree(childRenderNode, child);
                }
                if (isShadowHost(node)) {
                    var renderer = getRendererForHost(node);
                    renderer.dirty = false;
                }
            },
            compose: function (node) {
                var children = [];
                var p = node.shadowRoot || node;
                for (var child = p.firstChild; child; child = child.nextSibling) {
                    if (isInsertionPoint(child)) {
                        this.associateNode(p);
                        var distributedNodes = getDistributedNodes(child);
                        for (var j = 0; j < distributedNodes.length; j++) {
                            var distributedNode = distributedNodes[j];
                            if (isFinalDestination(child, distributedNode)) children.push(distributedNode);
                        }
                    } else {
                        children.push(child);
                    }
                }
                return children;
            },
            invalidateAttributes: function () {
                this.attributes = Object.create(null);
            },
            updateDependentAttributes: function (selector) {
                if (!selector) return;
                var attributes = this.attributes;
                if (/\.\w+/.test(selector)) attributes["class"] = true;
                if (/#\w+/.test(selector)) attributes["id"] = true;
                selector.replace(/\[\s*([^\s=\|~\]]+)/g, function (_, name) {
                    attributes[name] = true;
                });
            },
            dependsOnAttribute: function (name) {
                return this.attributes[name];
            },
            associateNode: function (node) {
                unsafeUnwrap(node).polymerShadowRenderer_ = this;
            }
        };
        function poolPopulation(node) {
            var pool = [];
            for (var child = node.firstChild; child; child = child.nextSibling) {
                if (isInsertionPoint(child)) {
                    pool.push.apply(pool, getDistributedNodes(child));
                } else {
                    pool.push(child);
                }
            }
            return pool;
        }

        function getShadowInsertionPoint(node) {
            if (node instanceof HTMLShadowElement) return node;
            if (node instanceof HTMLContentElement) return null;
            for (var child = node.firstChild; child; child = child.nextSibling) {
                var res = getShadowInsertionPoint(child);
                if (res) return res;
            }
            return null;
        }

        function destributeNodeInto(child, insertionPoint) {
            getDistributedNodes(insertionPoint).push(child);
            var points = destinationInsertionPointsTable.get(child);
            if (!points) destinationInsertionPointsTable.set(child, [insertionPoint]); else points.push(insertionPoint);
        }

        function getDestinationInsertionPoints(node) {
            return destinationInsertionPointsTable.get(node);
        }

        function resetDestinationInsertionPoints(node) {
            destinationInsertionPointsTable.set(node, undefined);
        }

        var selectorStartCharRe = /^(:not\()?[*.#[a-zA-Z_|]/;

        function matches(node, contentElement) {
            var select = contentElement.getAttribute("select");
            if (!select) return true;
            select = select.trim();
            if (!select) return true;
            if (!(node instanceof Element)) return false;
            if (!selectorStartCharRe.test(select)) return false;
            try {
                return node.matches(select);
            } catch (ex) {
                return false;
            }
        }

        function isFinalDestination(insertionPoint, node) {
            var points = getDestinationInsertionPoints(node);
            return points && points[points.length - 1] === insertionPoint;
        }

        function isInsertionPoint(node) {
            return node instanceof HTMLContentElement || node instanceof HTMLShadowElement;
        }

        function isShadowHost(shadowHost) {
            return shadowHost.shadowRoot;
        }

        function getShadowTrees(host) {
            var trees = [];
            for (var tree = host.shadowRoot; tree; tree = tree.olderShadowRoot) {
                trees.push(tree);
            }
            return trees;
        }

        function render(host) {
            new ShadowRenderer(host).render();
        }

        Node.prototype.invalidateShadowRenderer = function (force) {
            var renderer = unsafeUnwrap(this).polymerShadowRenderer_;
            if (renderer) {
                renderer.invalidate();
                return true;
            }
            return false;
        };
        HTMLContentElement.prototype.getDistributedNodes = HTMLShadowElement.prototype.getDistributedNodes = function () {
            renderAllPending();
            return getDistributedNodes(this);
        };
        Element.prototype.getDestinationInsertionPoints = function () {
            renderAllPending();
            return getDestinationInsertionPoints(this) || [];
        };
        HTMLContentElement.prototype.nodeIsInserted_ = HTMLShadowElement.prototype.nodeIsInserted_ = function () {
            this.invalidateShadowRenderer();
            var shadowRoot = getShadowRootAncestor(this);
            var renderer;
            if (shadowRoot) renderer = getRendererForShadowRoot(shadowRoot);
            unsafeUnwrap(this).polymerShadowRenderer_ = renderer;
            if (renderer) renderer.invalidate();
        };
        scope.getRendererForHost = getRendererForHost;
        scope.getShadowTrees = getShadowTrees;
        scope.renderAllPending = renderAllPending;
        scope.getDestinationInsertionPoints = getDestinationInsertionPoints;
        scope.visual = {
            insertBefore: insertBefore,
            remove: remove
        };
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var HTMLElement = scope.wrappers.HTMLElement;
        var assert = scope.assert;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var unwrap = scope.unwrap;
        var wrap = scope.wrap;
        var elementsWithFormProperty = ["HTMLButtonElement", "HTMLFieldSetElement", "HTMLInputElement", "HTMLKeygenElement", "HTMLLabelElement", "HTMLLegendElement", "HTMLObjectElement", "HTMLOutputElement", "HTMLTextAreaElement"];

        function createWrapperConstructor(name) {
            if (!window[name]) return;
            assert(!scope.wrappers[name]);
            var GeneratedWrapper = function (node) {
                HTMLElement.call(this, node);
            };
            GeneratedWrapper.prototype = Object.create(HTMLElement.prototype);
            mixin(GeneratedWrapper.prototype, {
                get form() {
                    return wrap(unwrap(this).form);
                }
            });
            registerWrapper(window[name], GeneratedWrapper, document.createElement(name.slice(4, -7)));
            scope.wrappers[name] = GeneratedWrapper;
        }

        elementsWithFormProperty.forEach(createWrapperConstructor);
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var registerWrapper = scope.registerWrapper;
        var setWrapper = scope.setWrapper;
        var unsafeUnwrap = scope.unsafeUnwrap;
        var unwrap = scope.unwrap;
        var unwrapIfNeeded = scope.unwrapIfNeeded;
        var wrap = scope.wrap;
        var OriginalSelection = window.Selection;

        function Selection(impl) {
            setWrapper(impl, this);
        }

        Selection.prototype = {
            get anchorNode() {
                return wrap(unsafeUnwrap(this).anchorNode);
            },
            get focusNode() {
                return wrap(unsafeUnwrap(this).focusNode);
            },
            addRange: function (range) {
                unsafeUnwrap(this).addRange(unwrap(range));
            },
            collapse: function (node, index) {
                unsafeUnwrap(this).collapse(unwrapIfNeeded(node), index);
            },
            containsNode: function (node, allowPartial) {
                return unsafeUnwrap(this).containsNode(unwrapIfNeeded(node), allowPartial);
            },
            extend: function (node, offset) {
                unsafeUnwrap(this).extend(unwrapIfNeeded(node), offset);
            },
            getRangeAt: function (index) {
                return wrap(unsafeUnwrap(this).getRangeAt(index));
            },
            removeRange: function (range) {
                unsafeUnwrap(this).removeRange(unwrap(range));
            },
            selectAllChildren: function (node) {
                unsafeUnwrap(this).selectAllChildren(unwrapIfNeeded(node));
            },
            toString: function () {
                return unsafeUnwrap(this).toString();
            }
        };
        registerWrapper(window.Selection, Selection, window.getSelection());
        scope.wrappers.Selection = Selection;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var GetElementsByInterface = scope.GetElementsByInterface;
        var Node = scope.wrappers.Node;
        var ParentNodeInterface = scope.ParentNodeInterface;
        var Selection = scope.wrappers.Selection;
        var SelectorsInterface = scope.SelectorsInterface;
        var ShadowRoot = scope.wrappers.ShadowRoot;
        var TreeScope = scope.TreeScope;
        var cloneNode = scope.cloneNode;
        var defineWrapGetter = scope.defineWrapGetter;
        var elementFromPoint = scope.elementFromPoint;
        var forwardMethodsToWrapper = scope.forwardMethodsToWrapper;
        var matchesNames = scope.matchesNames;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var renderAllPending = scope.renderAllPending;
        var rewrap = scope.rewrap;
        var setWrapper = scope.setWrapper;
        var unsafeUnwrap = scope.unsafeUnwrap;
        var unwrap = scope.unwrap;
        var wrap = scope.wrap;
        var wrapEventTargetMethods = scope.wrapEventTargetMethods;
        var wrapNodeList = scope.wrapNodeList;
        var implementationTable = new WeakMap();

        function Document(node) {
            Node.call(this, node);
            this.treeScope_ = new TreeScope(this, null);
        }

        Document.prototype = Object.create(Node.prototype);
        defineWrapGetter(Document, "documentElement");
        defineWrapGetter(Document, "body");
        defineWrapGetter(Document, "head");
        function wrapMethod(name) {
            var original = document[name];
            Document.prototype[name] = function () {
                return wrap(original.apply(unsafeUnwrap(this), arguments));
            };
        }

        ["createComment", "createDocumentFragment", "createElement", "createElementNS", "createEvent", "createEventNS", "createRange", "createTextNode", "getElementById"].forEach(wrapMethod);
        var originalAdoptNode = document.adoptNode;

        function adoptNodeNoRemove(node, doc) {
            originalAdoptNode.call(unsafeUnwrap(doc), unwrap(node));
            adoptSubtree(node, doc);
        }

        function adoptSubtree(node, doc) {
            if (node.shadowRoot) doc.adoptNode(node.shadowRoot);
            if (node instanceof ShadowRoot) adoptOlderShadowRoots(node, doc);
            for (var child = node.firstChild; child; child = child.nextSibling) {
                adoptSubtree(child, doc);
            }
        }

        function adoptOlderShadowRoots(shadowRoot, doc) {
            var oldShadowRoot = shadowRoot.olderShadowRoot;
            if (oldShadowRoot) doc.adoptNode(oldShadowRoot);
        }

        var originalGetSelection = document.getSelection;
        mixin(Document.prototype, {
            adoptNode: function (node) {
                if (node.parentNode) node.parentNode.removeChild(node);
                adoptNodeNoRemove(node, this);
                return node;
            },
            elementFromPoint: function (x, y) {
                return elementFromPoint(this, this, x, y);
            },
            importNode: function (node, deep) {
                return cloneNode(node, deep, unsafeUnwrap(this));
            },
            getSelection: function () {
                renderAllPending();
                return new Selection(originalGetSelection.call(unwrap(this)));
            },
            getElementsByName: function (name) {
                return SelectorsInterface.querySelectorAll.call(this, "[name=" + JSON.stringify(String(name)) + "]");
            }
        });
        if (document.registerElement) {
            var originalRegisterElement = document.registerElement;
            Document.prototype.registerElement = function (tagName, object) {
                var prototype, extendsOption;
                if (object !== undefined) {
                    prototype = object.prototype;
                    extendsOption = object.extends;
                }
                if (!prototype) prototype = Object.create(HTMLElement.prototype);
                if (scope.nativePrototypeTable.get(prototype)) {
                    throw new Error("NotSupportedError");
                }
                var proto = Object.getPrototypeOf(prototype);
                var nativePrototype;
                var prototypes = [];
                while (proto) {
                    nativePrototype = scope.nativePrototypeTable.get(proto);
                    if (nativePrototype) break;
                    prototypes.push(proto);
                    proto = Object.getPrototypeOf(proto);
                }
                if (!nativePrototype) {
                    throw new Error("NotSupportedError");
                }
                var newPrototype = Object.create(nativePrototype);
                for (var i = prototypes.length - 1; i >= 0; i--) {
                    newPrototype = Object.create(newPrototype);
                }
                ["createdCallback", "attachedCallback", "detachedCallback", "attributeChangedCallback"].forEach(function (name) {
                    var f = prototype[name];
                    if (!f) return;
                    newPrototype[name] = function () {
                        if (!(wrap(this) instanceof CustomElementConstructor)) {
                            rewrap(this);
                        }
                        f.apply(wrap(this), arguments);
                    };
                });
                var p = {
                    prototype: newPrototype
                };
                if (extendsOption) p.extends = extendsOption;
                function CustomElementConstructor(node) {
                    if (!node) {
                        if (extendsOption) {
                            return document.createElement(extendsOption, tagName);
                        } else {
                            return document.createElement(tagName);
                        }
                    }
                    setWrapper(node, this);
                }

                CustomElementConstructor.prototype = prototype;
                CustomElementConstructor.prototype.constructor = CustomElementConstructor;
                scope.constructorTable.set(newPrototype, CustomElementConstructor);
                scope.nativePrototypeTable.set(prototype, newPrototype);
                var nativeConstructor = originalRegisterElement.call(unwrap(this), tagName, p);
                return CustomElementConstructor;
            };
            forwardMethodsToWrapper([window.HTMLDocument || window.Document], ["registerElement"]);
        }
        forwardMethodsToWrapper([window.HTMLBodyElement, window.HTMLDocument || window.Document, window.HTMLHeadElement, window.HTMLHtmlElement], ["appendChild", "compareDocumentPosition", "contains", "getElementsByClassName", "getElementsByTagName", "getElementsByTagNameNS", "insertBefore", "querySelector", "querySelectorAll", "removeChild", "replaceChild"]);
        forwardMethodsToWrapper([window.HTMLBodyElement, window.HTMLHeadElement, window.HTMLHtmlElement], matchesNames);
        forwardMethodsToWrapper([window.HTMLDocument || window.Document], ["adoptNode", "importNode", "contains", "createComment", "createDocumentFragment", "createElement", "createElementNS", "createEvent", "createEventNS", "createRange", "createTextNode", "elementFromPoint", "getElementById", "getElementsByName", "getSelection"]);
        mixin(Document.prototype, GetElementsByInterface);
        mixin(Document.prototype, ParentNodeInterface);
        mixin(Document.prototype, SelectorsInterface);
        mixin(Document.prototype, {
            get implementation() {
                var implementation = implementationTable.get(this);
                if (implementation) return implementation;
                implementation = new DOMImplementation(unwrap(this).implementation);
                implementationTable.set(this, implementation);
                return implementation;
            },
            get defaultView() {
                return wrap(unwrap(this).defaultView);
            }
        });
        registerWrapper(window.Document, Document, document.implementation.createHTMLDocument(""));
        if (window.HTMLDocument) registerWrapper(window.HTMLDocument, Document);
        wrapEventTargetMethods([window.HTMLBodyElement, window.HTMLDocument || window.Document, window.HTMLHeadElement]);
        function DOMImplementation(impl) {
            setWrapper(impl, this);
        }

        function wrapImplMethod(constructor, name) {
            var original = document.implementation[name];
            constructor.prototype[name] = function () {
                return wrap(original.apply(unsafeUnwrap(this), arguments));
            };
        }

        function forwardImplMethod(constructor, name) {
            var original = document.implementation[name];
            constructor.prototype[name] = function () {
                return original.apply(unsafeUnwrap(this), arguments);
            };
        }

        wrapImplMethod(DOMImplementation, "createDocumentType");
        wrapImplMethod(DOMImplementation, "createDocument");
        wrapImplMethod(DOMImplementation, "createHTMLDocument");
        forwardImplMethod(DOMImplementation, "hasFeature");
        registerWrapper(window.DOMImplementation, DOMImplementation);
        forwardMethodsToWrapper([window.DOMImplementation], ["createDocumentType", "createDocument", "createHTMLDocument", "hasFeature"]);
        scope.adoptNodeNoRemove = adoptNodeNoRemove;
        scope.wrappers.DOMImplementation = DOMImplementation;
        scope.wrappers.Document = Document;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var EventTarget = scope.wrappers.EventTarget;
        var Selection = scope.wrappers.Selection;
        var mixin = scope.mixin;
        var registerWrapper = scope.registerWrapper;
        var renderAllPending = scope.renderAllPending;
        var unwrap = scope.unwrap;
        var unwrapIfNeeded = scope.unwrapIfNeeded;
        var wrap = scope.wrap;
        var OriginalWindow = window.Window;
        var originalGetComputedStyle = window.getComputedStyle;
        var originalGetDefaultComputedStyle = window.getDefaultComputedStyle;
        var originalGetSelection = window.getSelection;

        function Window(impl) {
            EventTarget.call(this, impl);
        }

        Window.prototype = Object.create(EventTarget.prototype);
        OriginalWindow.prototype.getComputedStyle = function (el, pseudo) {
            return wrap(this || window).getComputedStyle(unwrapIfNeeded(el), pseudo);
        };
        if (originalGetDefaultComputedStyle) {
            OriginalWindow.prototype.getDefaultComputedStyle = function (el, pseudo) {
                return wrap(this || window).getDefaultComputedStyle(unwrapIfNeeded(el), pseudo);
            };
        }
        OriginalWindow.prototype.getSelection = function () {
            return wrap(this || window).getSelection();
        };
        delete window.getComputedStyle;
        delete window.getDefaultComputedStyle;
        delete window.getSelection;
        ["addEventListener", "removeEventListener", "dispatchEvent"].forEach(function (name) {
            OriginalWindow.prototype[name] = function () {
                var w = wrap(this || window);
                return w[name].apply(w, arguments);
            };
            delete window[name];
        });
        mixin(Window.prototype, {
            getComputedStyle: function (el, pseudo) {
                renderAllPending();
                return originalGetComputedStyle.call(unwrap(this), unwrapIfNeeded(el), pseudo);
            },
            getSelection: function () {
                renderAllPending();
                return new Selection(originalGetSelection.call(unwrap(this)));
            },
            get document() {
                return wrap(unwrap(this).document);
            }
        });
        if (originalGetDefaultComputedStyle) {
            Window.prototype.getDefaultComputedStyle = function (el, pseudo) {
                renderAllPending();
                return originalGetDefaultComputedStyle.call(unwrap(this), unwrapIfNeeded(el), pseudo);
            };
        }
        registerWrapper(OriginalWindow, Window, window);
        scope.wrappers.Window = Window;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var unwrap = scope.unwrap;
        var OriginalDataTransfer = window.DataTransfer || window.Clipboard;
        var OriginalDataTransferSetDragImage = OriginalDataTransfer.prototype.setDragImage;
        if (OriginalDataTransferSetDragImage) {
            OriginalDataTransfer.prototype.setDragImage = function (image, x, y) {
                OriginalDataTransferSetDragImage.call(this, unwrap(image), x, y);
            };
        }
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var registerWrapper = scope.registerWrapper;
        var setWrapper = scope.setWrapper;
        var unwrap = scope.unwrap;
        var OriginalFormData = window.FormData;
        if (!OriginalFormData) return;
        function FormData(formElement) {
            var impl;
            if (formElement instanceof OriginalFormData) {
                impl = formElement;
            } else {
                impl = new OriginalFormData(formElement && unwrap(formElement));
            }
            setWrapper(impl, this);
        }

        registerWrapper(OriginalFormData, FormData, new OriginalFormData());
        scope.wrappers.FormData = FormData;
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var unwrapIfNeeded = scope.unwrapIfNeeded;
        var originalSend = XMLHttpRequest.prototype.send;
        XMLHttpRequest.prototype.send = function (obj) {
            return originalSend.call(this, unwrapIfNeeded(obj));
        };
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        "use strict";
        var isWrapperFor = scope.isWrapperFor;
        var elements = {
            a: "HTMLAnchorElement",
            area: "HTMLAreaElement",
            audio: "HTMLAudioElement",
            base: "HTMLBaseElement",
            body: "HTMLBodyElement",
            br: "HTMLBRElement",
            button: "HTMLButtonElement",
            canvas: "HTMLCanvasElement",
            caption: "HTMLTableCaptionElement",
            col: "HTMLTableColElement",
            content: "HTMLContentElement",
            data: "HTMLDataElement",
            datalist: "HTMLDataListElement",
            del: "HTMLModElement",
            dir: "HTMLDirectoryElement",
            div: "HTMLDivElement",
            dl: "HTMLDListElement",
            embed: "HTMLEmbedElement",
            fieldset: "HTMLFieldSetElement",
            font: "HTMLFontElement",
            form: "HTMLFormElement",
            frame: "HTMLFrameElement",
            frameset: "HTMLFrameSetElement",
            h1: "HTMLHeadingElement",
            head: "HTMLHeadElement",
            hr: "HTMLHRElement",
            html: "HTMLHtmlElement",
            iframe: "HTMLIFrameElement",
            img: "HTMLImageElement",
            input: "HTMLInputElement",
            keygen: "HTMLKeygenElement",
            label: "HTMLLabelElement",
            legend: "HTMLLegendElement",
            li: "HTMLLIElement",
            link: "HTMLLinkElement",
            map: "HTMLMapElement",
            marquee: "HTMLMarqueeElement",
            menu: "HTMLMenuElement",
            menuitem: "HTMLMenuItemElement",
            meta: "HTMLMetaElement",
            meter: "HTMLMeterElement",
            object: "HTMLObjectElement",
            ol: "HTMLOListElement",
            optgroup: "HTMLOptGroupElement",
            option: "HTMLOptionElement",
            output: "HTMLOutputElement",
            p: "HTMLParagraphElement",
            param: "HTMLParamElement",
            pre: "HTMLPreElement",
            progress: "HTMLProgressElement",
            q: "HTMLQuoteElement",
            script: "HTMLScriptElement",
            select: "HTMLSelectElement",
            shadow: "HTMLShadowElement",
            source: "HTMLSourceElement",
            span: "HTMLSpanElement",
            style: "HTMLStyleElement",
            table: "HTMLTableElement",
            tbody: "HTMLTableSectionElement",
            template: "HTMLTemplateElement",
            textarea: "HTMLTextAreaElement",
            thead: "HTMLTableSectionElement",
            time: "HTMLTimeElement",
            title: "HTMLTitleElement",
            tr: "HTMLTableRowElement",
            track: "HTMLTrackElement",
            ul: "HTMLUListElement",
            video: "HTMLVideoElement"
        };

        function overrideConstructor(tagName) {
            var nativeConstructorName = elements[tagName];
            var nativeConstructor = window[nativeConstructorName];
            if (!nativeConstructor) return;
            var element = document.createElement(tagName);
            var wrapperConstructor = element.constructor;
            window[nativeConstructorName] = wrapperConstructor;
        }

        Object.keys(elements).forEach(overrideConstructor);
        Object.getOwnPropertyNames(scope.wrappers).forEach(function (name) {
            window[name] = scope.wrappers[name];
        });
    })(window.ShadowDOMPolyfill);
    (function (scope) {
        var ShadowCSS = {
            strictStyling: false,
            registry: {},
            shimStyling: function (root, name, extendsName) {
                var scopeStyles = this.prepareRoot(root, name, extendsName);
                var typeExtension = this.isTypeExtension(extendsName);
                var scopeSelector = this.makeScopeSelector(name, typeExtension);
                var cssText = stylesToCssText(scopeStyles, true);
                cssText = this.scopeCssText(cssText, scopeSelector);
                if (root) {
                    root.shimmedStyle = cssText;
                }
                this.addCssToDocument(cssText, name);
            },
            shimStyle: function (style, selector) {
                return this.shimCssText(style.textContent, selector);
            },
            shimCssText: function (cssText, selector) {
                cssText = this.insertDirectives(cssText);
                return this.scopeCssText(cssText, selector);
            },
            makeScopeSelector: function (name, typeExtension) {
                if (name) {
                    return typeExtension ? "[is=" + name + "]" : name;
                }
                return "";
            },
            isTypeExtension: function (extendsName) {
                return extendsName && extendsName.indexOf("-") < 0;
            },
            prepareRoot: function (root, name, extendsName) {
                var def = this.registerRoot(root, name, extendsName);
                this.replaceTextInStyles(def.rootStyles, this.insertDirectives);
                this.removeStyles(root, def.rootStyles);
                if (this.strictStyling) {
                    this.applyScopeToContent(root, name);
                }
                return def.scopeStyles;
            },
            removeStyles: function (root, styles) {
                for (var i = 0, l = styles.length, s; i < l && (s = styles[i]); i++) {
                    s.parentNode.removeChild(s);
                }
            },
            registerRoot: function (root, name, extendsName) {
                var def = this.registry[name] = {
                    root: root,
                    name: name,
                    extendsName: extendsName
                };
                var styles = this.findStyles(root);
                def.rootStyles = styles;
                def.scopeStyles = def.rootStyles;
                var extendee = this.registry[def.extendsName];
                if (extendee) {
                    def.scopeStyles = extendee.scopeStyles.concat(def.scopeStyles);
                }
                return def;
            },
            findStyles: function (root) {
                if (!root) {
                    return [];
                }
                var styles = root.querySelectorAll("style");
                return Array.prototype.filter.call(styles, function (s) {
                    return !s.hasAttribute(NO_SHIM_ATTRIBUTE);
                });
            },
            applyScopeToContent: function (root, name) {
                if (root) {
                    Array.prototype.forEach.call(root.querySelectorAll("*"), function (node) {
                        node.setAttribute(name, "");
                    });
                    Array.prototype.forEach.call(root.querySelectorAll("template"), function (template) {
                        this.applyScopeToContent(template.content, name);
                    }, this);
                }
            },
            insertDirectives: function (cssText) {
                cssText = this.insertPolyfillDirectivesInCssText(cssText);
                return this.insertPolyfillRulesInCssText(cssText);
            },
            insertPolyfillDirectivesInCssText: function (cssText) {
                cssText = cssText.replace(cssCommentNextSelectorRe, function (match, p1) {
                    return p1.slice(0, -2) + "{";
                });
                return cssText.replace(cssContentNextSelectorRe, function (match, p1) {
                    return p1 + " {";
                });
            },
            insertPolyfillRulesInCssText: function (cssText) {
                cssText = cssText.replace(cssCommentRuleRe, function (match, p1) {
                    return p1.slice(0, -1);
                });
                return cssText.replace(cssContentRuleRe, function (match, p1, p2, p3) {
                    var rule = match.replace(p1, "").replace(p2, "");
                    return p3 + rule;
                });
            },
            scopeCssText: function (cssText, scopeSelector) {
                var unscoped = this.extractUnscopedRulesFromCssText(cssText);
                cssText = this.insertPolyfillHostInCssText(cssText);
                cssText = this.convertColonHost(cssText);
                cssText = this.convertColonHostContext(cssText);
                cssText = this.convertShadowDOMSelectors(cssText);
                if (scopeSelector) {
                    var self = this, cssText;
                    withCssRules(cssText, function (rules) {
                        cssText = self.scopeRules(rules, scopeSelector);
                    });
                }
                cssText = cssText + "\n" + unscoped;
                return cssText.trim();
            },
            extractUnscopedRulesFromCssText: function (cssText) {
                var r = "", m;
                while (m = cssCommentUnscopedRuleRe.exec(cssText)) {
                    r += m[1].slice(0, -1) + "\n\n";
                }
                while (m = cssContentUnscopedRuleRe.exec(cssText)) {
                    r += m[0].replace(m[2], "").replace(m[1], m[3]) + "\n\n";
                }
                return r;
            },
            convertColonHost: function (cssText) {
                return this.convertColonRule(cssText, cssColonHostRe, this.colonHostPartReplacer);
            },
            convertColonHostContext: function (cssText) {
                return this.convertColonRule(cssText, cssColonHostContextRe, this.colonHostContextPartReplacer);
            },
            convertColonRule: function (cssText, regExp, partReplacer) {
                return cssText.replace(regExp, function (m, p1, p2, p3) {
                    p1 = polyfillHostNoCombinator;
                    if (p2) {
                        var parts = p2.split(","), r = [];
                        for (var i = 0, l = parts.length, p; i < l && (p = parts[i]); i++) {
                            p = p.trim();
                            r.push(partReplacer(p1, p, p3));
                        }
                        return r.join(",");
                    } else {
                        return p1 + p3;
                    }
                });
            },
            colonHostContextPartReplacer: function (host, part, suffix) {
                if (part.match(polyfillHost)) {
                    return this.colonHostPartReplacer(host, part, suffix);
                } else {
                    return host + part + suffix + ", " + part + " " + host + suffix;
                }
            },
            colonHostPartReplacer: function (host, part, suffix) {
                return host + part.replace(polyfillHost, "") + suffix;
            },
            convertShadowDOMSelectors: function (cssText) {
                for (var i = 0; i < shadowDOMSelectorsRe.length; i++) {
                    cssText = cssText.replace(shadowDOMSelectorsRe[i], " ");
                }
                return cssText;
            },
            scopeRules: function (cssRules, scopeSelector) {
                var cssText = "";
                if (cssRules) {
                    Array.prototype.forEach.call(cssRules, function (rule) {
                        if (rule.selectorText && (rule.style && rule.style.cssText !== undefined)) {
                            cssText += this.scopeSelector(rule.selectorText, scopeSelector, this.strictStyling) + " {\n	";
                            cssText += this.propertiesFromRule(rule) + "\n}\n\n";
                        } else if (rule.type === CSSRule.MEDIA_RULE) {
                            cssText += "@media " + rule.media.mediaText + " {\n";
                            cssText += this.scopeRules(rule.cssRules, scopeSelector);
                            cssText += "\n}\n\n";
                        } else {
                            try {
                                if (rule.cssText) {
                                    cssText += rule.cssText + "\n\n";
                                }
                            } catch (x) {
                                if (rule.type === CSSRule.KEYFRAMES_RULE && rule.cssRules) {
                                    cssText += this.ieSafeCssTextFromKeyFrameRule(rule);
                                }
                            }
                        }
                    }, this);
                }
                return cssText;
            },
            ieSafeCssTextFromKeyFrameRule: function (rule) {
                var cssText = "@keyframes " + rule.name + " {";
                Array.prototype.forEach.call(rule.cssRules, function (rule) {
                    cssText += " " + rule.keyText + " {" + rule.style.cssText + "}";
                });
                cssText += " }";
                return cssText;
            },
            scopeSelector: function (selector, scopeSelector, strict) {
                var r = [], parts = selector.split(",");
                parts.forEach(function (p) {
                    p = p.trim();
                    if (this.selectorNeedsScoping(p, scopeSelector)) {
                        p = strict && !p.match(polyfillHostNoCombinator) ? this.applyStrictSelectorScope(p, scopeSelector) : this.applySelectorScope(p, scopeSelector);
                    }
                    r.push(p);
                }, this);
                return r.join(", ");
            },
            selectorNeedsScoping: function (selector, scopeSelector) {
                if (Array.isArray(scopeSelector)) {
                    return true;
                }
                var re = this.makeScopeMatcher(scopeSelector);
                return !selector.match(re);
            },
            makeScopeMatcher: function (scopeSelector) {
                scopeSelector = scopeSelector.replace(/\[/g, "\\[").replace(/\]/g, "\\]");
                return new RegExp("^(" + scopeSelector + ")" + selectorReSuffix, "m");
            },
            applySelectorScope: function (selector, selectorScope) {
                return Array.isArray(selectorScope) ? this.applySelectorScopeList(selector, selectorScope) : this.applySimpleSelectorScope(selector, selectorScope);
            },
            applySelectorScopeList: function (selector, scopeSelectorList) {
                var r = [];
                for (var i = 0, s; s = scopeSelectorList[i]; i++) {
                    r.push(this.applySimpleSelectorScope(selector, s));
                }
                return r.join(", ");
            },
            applySimpleSelectorScope: function (selector, scopeSelector) {
                if (selector.match(polyfillHostRe)) {
                    selector = selector.replace(polyfillHostNoCombinator, scopeSelector);
                    return selector.replace(polyfillHostRe, scopeSelector + " ");
                } else {
                    return scopeSelector + " " + selector;
                }
            },
            applyStrictSelectorScope: function (selector, scopeSelector) {
                scopeSelector = scopeSelector.replace(/\[is=([^\]]*)\]/g, "$1");
                var splits = [" ", ">", "+", "~"], scoped = selector, attrName = "[" + scopeSelector + "]";
                splits.forEach(function (sep) {
                    var parts = scoped.split(sep);
                    scoped = parts.map(function (p) {
                        var t = p.trim().replace(polyfillHostRe, "");
                        if (t && splits.indexOf(t) < 0 && t.indexOf(attrName) < 0) {
                            p = t.replace(/([^:]*)(:*)(.*)/, "$1" + attrName + "$2$3");
                        }
                        return p;
                    }).join(sep);
                });
                return scoped;
            },
            insertPolyfillHostInCssText: function (selector) {
                return selector.replace(colonHostContextRe, polyfillHostContext).replace(colonHostRe, polyfillHost);
            },
            propertiesFromRule: function (rule) {
                var cssText = rule.style.cssText;
                if (rule.style.content && !rule.style.content.match(/['"]+|attr/)) {
                    cssText = cssText.replace(/content:[^;]*;/g, "content: '" + rule.style.content + "';");
                }
                var style = rule.style;
                for (var i in style) {
                    if (style[i] === "initial") {
                        cssText += i + ": initial; ";
                    }
                }
                return cssText;
            },
            replaceTextInStyles: function (styles, action) {
                if (styles && action) {
                    if (!(styles instanceof Array)) {
                        styles = [styles];
                    }
                    Array.prototype.forEach.call(styles, function (s) {
                        s.textContent = action.call(this, s.textContent);
                    }, this);
                }
            },
            addCssToDocument: function (cssText, name) {
                if (cssText.match("@import")) {
                    addOwnSheet(cssText, name);
                } else {
                    addCssToDocument(cssText);
                }
            }
        };
        var selectorRe = /([^{]*)({[\s\S]*?})/gim, cssCommentRe = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim, cssCommentNextSelectorRe = /\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim, cssContentNextSelectorRe = /polyfill-next-selector[^}]*content\:[\s]*?['"](.*?)['"][;\s]*}([^{]*?){/gim, cssCommentRuleRe = /\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim, cssContentRuleRe = /(polyfill-rule)[^}]*(content\:[\s]*['"](.*?)['"])[;\s]*[^}]*}/gim, cssCommentUnscopedRuleRe = /\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim, cssContentUnscopedRuleRe = /(polyfill-unscoped-rule)[^}]*(content\:[\s]*['"](.*?)['"])[;\s]*[^}]*}/gim, cssPseudoRe = /::(x-[^\s{,(]*)/gim, cssPartRe = /::part\(([^)]*)\)/gim, polyfillHost = "-shadowcsshost", polyfillHostContext = "-shadowcsscontext", parenSuffix = ")(?:\\((" + "(?:\\([^)(]*\\)|[^)(]*)+?" + ")\\))?([^,{]*)";
        var cssColonHostRe = new RegExp("(" + polyfillHost + parenSuffix, "gim"), cssColonHostContextRe = new RegExp("(" + polyfillHostContext + parenSuffix, "gim"), selectorReSuffix = "([>\\s~+[.,{:][\\s\\S]*)?$", colonHostRe = /\:host/gim, colonHostContextRe = /\:host-context/gim, polyfillHostNoCombinator = polyfillHost + "-no-combinator", polyfillHostRe = new RegExp(polyfillHost, "gim"), polyfillHostContextRe = new RegExp(polyfillHostContext, "gim"), shadowDOMSelectorsRe = [/\^\^/g, /\^/g, /\/shadow\//g, /\/shadow-deep\//g, /::shadow/g, /\/deep\//g, /::content/g];

        function stylesToCssText(styles, preserveComments) {
            var cssText = "";
            Array.prototype.forEach.call(styles, function (s) {
                cssText += s.textContent + "\n\n";
            });
            if (!preserveComments) {
                cssText = cssText.replace(cssCommentRe, "");
            }
            return cssText;
        }

        function cssTextToStyle(cssText) {
            var style = document.createElement("style");
            style.textContent = cssText;
            return style;
        }

        function cssToRules(cssText) {
            var style = cssTextToStyle(cssText);
            document.head.appendChild(style);
            var rules = [];
            if (style.sheet) {
                try {
                    rules = style.sheet.cssRules;
                } catch (e) {
                }
            } else {
                console.warn("sheet not found", style);
            }
            style.parentNode.removeChild(style);
            return rules;
        }

        var frame = document.createElement("iframe");
        frame.style.display = "none";
        function initFrame() {
            frame.initialized = true;
            document.body.appendChild(frame);
            var doc = frame.contentDocument;
            var base = doc.createElement("base");
            base.href = document.baseURI;
            doc.head.appendChild(base);
        }

        function inFrame(fn) {
            if (!frame.initialized) {
                initFrame();
            }
            document.body.appendChild(frame);
            fn(frame.contentDocument);
            document.body.removeChild(frame);
        }

        var isChrome = navigator.userAgent.match("Chrome");

        function withCssRules(cssText, callback) {
            if (!callback) {
                return;
            }
            var rules;
            if (cssText.match("@import") && isChrome) {
                var style = cssTextToStyle(cssText);
                inFrame(function (doc) {
                    doc.head.appendChild(style.impl);
                    rules = Array.prototype.slice.call(style.sheet.cssRules, 0);
                    callback(rules);
                });
            } else {
                rules = cssToRules(cssText);
                callback(rules);
            }
        }

        function rulesToCss(cssRules) {
            for (var i = 0, css = []; i < cssRules.length; i++) {
                css.push(cssRules[i].cssText);
            }
            return css.join("\n\n");
        }

        function addCssToDocument(cssText) {
            if (cssText) {
                getSheet().appendChild(document.createTextNode(cssText));
            }
        }

        function addOwnSheet(cssText, name) {
            var style = cssTextToStyle(cssText);
            style.setAttribute(name, "");
            style.setAttribute(SHIMMED_ATTRIBUTE, "");
            document.head.appendChild(style);
        }

        var SHIM_ATTRIBUTE = "shim-shadowdom";
        var SHIMMED_ATTRIBUTE = "shim-shadowdom-css";
        var NO_SHIM_ATTRIBUTE = "no-shim";
        var sheet;

        function getSheet() {
            if (!sheet) {
                sheet = document.createElement("style");
                sheet.setAttribute(SHIMMED_ATTRIBUTE, "");
                sheet[SHIMMED_ATTRIBUTE] = true;
            }
            return sheet;
        }

        if (window.ShadowDOMPolyfill) {
            addCssToDocument("style { display: none !important; }\n");
            var doc = ShadowDOMPolyfill.wrap(document);
            var head = doc.querySelector("head");
            head.insertBefore(getSheet(), head.childNodes[0]);
            document.addEventListener("DOMContentLoaded", function () {
                var urlResolver = scope.urlResolver;
                if (window.HTMLImports && !HTMLImports.useNative) {
                    var SHIM_SHEET_SELECTOR = "link[rel=stylesheet]" + "[" + SHIM_ATTRIBUTE + "]";
                    var SHIM_STYLE_SELECTOR = "style[" + SHIM_ATTRIBUTE + "]";
                    HTMLImports.importer.documentPreloadSelectors += "," + SHIM_SHEET_SELECTOR;
                    HTMLImports.importer.importsPreloadSelectors += "," + SHIM_SHEET_SELECTOR;
                    HTMLImports.parser.documentSelectors = [HTMLImports.parser.documentSelectors, SHIM_SHEET_SELECTOR, SHIM_STYLE_SELECTOR].join(",");
                    var originalParseGeneric = HTMLImports.parser.parseGeneric;
                    HTMLImports.parser.parseGeneric = function (elt) {
                        if (elt[SHIMMED_ATTRIBUTE]) {
                            return;
                        }
                        var style = elt.__importElement || elt;
                        if (!style.hasAttribute(SHIM_ATTRIBUTE)) {
                            originalParseGeneric.call(this, elt);
                            return;
                        }
                        if (elt.__resource) {
                            style = elt.ownerDocument.createElement("style");
                            style.textContent = elt.__resource;
                        }
                        HTMLImports.path.resolveUrlsInStyle(style);
                        style.textContent = ShadowCSS.shimStyle(style);
                        style.removeAttribute(SHIM_ATTRIBUTE, "");
                        style.setAttribute(SHIMMED_ATTRIBUTE, "");
                        style[SHIMMED_ATTRIBUTE] = true;
                        if (style.parentNode !== head) {
                            if (elt.parentNode === head) {
                                head.replaceChild(style, elt);
                            } else {
                                this.addElementToDocument(style);
                            }
                        }
                        style.__importParsed = true;
                        this.markParsingComplete(elt);
                        this.parseNext();
                    };
                    var hasResource = HTMLImports.parser.hasResource;
                    HTMLImports.parser.hasResource = function (node) {
                        if (node.localName === "link" && node.rel === "stylesheet" && node.hasAttribute(SHIM_ATTRIBUTE)) {
                            return node.__resource;
                        } else {
                            return hasResource.call(this, node);
                        }
                    };
                }
            });
        }
        scope.ShadowCSS = ShadowCSS;
    })(window.WebComponents);
}

(function (scope) {
    if (window.ShadowDOMPolyfill) {
        window.wrap = ShadowDOMPolyfill.wrapIfNeeded;
        window.unwrap = ShadowDOMPolyfill.unwrapIfNeeded;
    } else {
        window.wrap = window.unwrap = function (n) {
            return n;
        };
    }
})(window.WebComponents);

window.HTMLImports = window.HTMLImports || {
        flags: {}
    };

(function (scope) {
    var IMPORT_LINK_TYPE = "import";
    var useNative = Boolean(IMPORT_LINK_TYPE in document.createElement("link"));
    var hasShadowDOMPolyfill = Boolean(window.ShadowDOMPolyfill);
    var wrap = function (node) {
        return hasShadowDOMPolyfill ? ShadowDOMPolyfill.wrapIfNeeded(node) : node;
    };
    var rootDocument = wrap(document);
    var currentScriptDescriptor = {
        get: function () {
            var script = HTMLImports.currentScript || document.currentScript || (document.readyState !== "complete" ? document.scripts[document.scripts.length - 1] : null);
            return wrap(script);
        },
        configurable: true
    };
    Object.defineProperty(document, "_currentScript", currentScriptDescriptor);
    Object.defineProperty(rootDocument, "_currentScript", currentScriptDescriptor);
    var isIE = /Trident|Edge/.test(navigator.userAgent);

    function whenReady(callback, doc) {
        doc = doc || rootDocument;
        whenDocumentReady(function () {
            watchImportsLoad(callback, doc);
        }, doc);
    }

    var requiredReadyState = isIE ? "complete" : "interactive";
    var READY_EVENT = "readystatechange";

    function isDocumentReady(doc) {
        return doc.readyState === "complete" || doc.readyState === requiredReadyState;
    }

    function whenDocumentReady(callback, doc) {
        if (!isDocumentReady(doc)) {
            var checkReady = function () {
                if (doc.readyState === "complete" || doc.readyState === requiredReadyState) {
                    doc.removeEventListener(READY_EVENT, checkReady);
                    whenDocumentReady(callback, doc);
                }
            };
            doc.addEventListener(READY_EVENT, checkReady);
        } else if (callback) {
            callback();
        }
    }

    function markTargetLoaded(event) {
        event.target.__loaded = true;
    }

    function watchImportsLoad(callback, doc) {
        var imports = doc.querySelectorAll("link[rel=import]");
        var loaded = 0, l = imports.length;

        function checkDone(d) {
            if (loaded == l && callback) {
                callback();
            }
        }

        function loadedImport(e) {
            markTargetLoaded(e);
            loaded++;
            checkDone();
        }

        if (l) {
            for (var i = 0, imp; i < l && (imp = imports[i]); i++) {
                if (isImportLoaded(imp)) {
                    loadedImport.call(imp, {
                        target: imp
                    });
                } else {
                    imp.addEventListener("load", loadedImport);
                    imp.addEventListener("error", loadedImport);
                }
            }
        } else {
            checkDone();
        }
    }

    function isImportLoaded(link) {
        return useNative ? link.__loaded || link.import && link.import.readyState !== "loading" : link.__importParsed;
    }

    if (useNative) {
        new MutationObserver(function (mxns) {
            for (var i = 0, l = mxns.length, m; i < l && (m = mxns[i]); i++) {
                if (m.addedNodes) {
                    handleImports(m.addedNodes);
                }
            }
        }).observe(document.head, {
                childList: true
            });
        function handleImports(nodes) {
            for (var i = 0, l = nodes.length, n; i < l && (n = nodes[i]); i++) {
                if (isImport(n)) {
                    handleImport(n);
                }
            }
        }

        function isImport(element) {
            return element.localName === "link" && element.rel === "import";
        }

        function handleImport(element) {
            var loaded = element.import;
            if (loaded) {
                markTargetLoaded({
                    target: element
                });
            } else {
                element.addEventListener("load", markTargetLoaded);
                element.addEventListener("error", markTargetLoaded);
            }
        }

        (function () {
            if (document.readyState === "loading") {
                var imports = document.querySelectorAll("link[rel=import]");
                for (var i = 0, l = imports.length, imp; i < l && (imp = imports[i]); i++) {
                    handleImport(imp);
                }
            }
        })();
    }
    whenReady(function () {
        HTMLImports.ready = true;
        HTMLImports.readyTime = new Date().getTime();
        var evt = rootDocument.createEvent("CustomEvent");
        evt.initCustomEvent("HTMLImportsLoaded", true, true, {});
        rootDocument.dispatchEvent(evt);
    });
    scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE;
    scope.useNative = useNative;
    scope.rootDocument = rootDocument;
    scope.whenReady = whenReady;
    scope.isIE = isIE;
})(HTMLImports);

(function (scope) {
    var modules = [];
    var addModule = function (module) {
        modules.push(module);
    };
    var initializeModules = function () {
        modules.forEach(function (module) {
            module(scope);
        });
    };
    scope.addModule = addModule;
    scope.initializeModules = initializeModules;
})(HTMLImports);

HTMLImports.addModule(function (scope) {
    var CSS_URL_REGEXP = /(url\()([^)]*)(\))/g;
    var CSS_IMPORT_REGEXP = /(@import[\s]+(?!url\())([^;]*)(;)/g;
    var path = {
        resolveUrlsInStyle: function (style) {
            var doc = style.ownerDocument;
            var resolver = doc.createElement("a");
            style.textContent = this.resolveUrlsInCssText(style.textContent, resolver);
            return style;
        },
        resolveUrlsInCssText: function (cssText, urlObj) {
            var r = this.replaceUrls(cssText, urlObj, CSS_URL_REGEXP);
            r = this.replaceUrls(r, urlObj, CSS_IMPORT_REGEXP);
            return r;
        },
        replaceUrls: function (text, urlObj, regexp) {
            return text.replace(regexp, function (m, pre, url, post) {
                var urlPath = url.replace(/["']/g, "");
                urlObj.href = urlPath;
                urlPath = urlObj.href;
                return pre + "'" + urlPath + "'" + post;
            });
        }
    };
    scope.path = path;
});

HTMLImports.addModule(function (scope) {
    var xhr = {
        async: true,
        ok: function (request) {
            return request.status >= 200 && request.status < 300 || request.status === 304 || request.status === 0;
        },
        load: function (url, next, nextContext) {
            var request = new XMLHttpRequest();
            if (scope.flags.debug || scope.flags.bust) {
                url += "?" + Math.random();
            }
            request.open("GET", url, xhr.async);
            request.addEventListener("readystatechange", function (e) {
                if (request.readyState === 4) {
                    var locationHeader = request.getResponseHeader("Location");
                    var redirectedUrl = null;
                    if (locationHeader) {
                        var redirectedUrl = locationHeader.substr(0, 1) === "/" ? location.origin + locationHeader : locationHeader;
                    }
                    next.call(nextContext, !xhr.ok(request) && request, request.response || request.responseText, redirectedUrl);
                }
            });
            request.send();
            return request;
        },
        loadDocument: function (url, next, nextContext) {
            this.load(url, next, nextContext).responseType = "document";
        }
    };
    scope.xhr = xhr;
});

HTMLImports.addModule(function (scope) {
    var xhr = scope.xhr;
    var flags = scope.flags;
    var Loader = function (onLoad, onComplete) {
        this.cache = {};
        this.onload = onLoad;
        this.oncomplete = onComplete;
        this.inflight = 0;
        this.pending = {};
    };
    Loader.prototype = {
        addNodes: function (nodes) {
            this.inflight += nodes.length;
            for (var i = 0, l = nodes.length, n; i < l && (n = nodes[i]); i++) {
                this.require(n);
            }
            this.checkDone();
        },
        addNode: function (node) {
            this.inflight++;
            this.require(node);
            this.checkDone();
        },
        require: function (elt) {
            var url = elt.src || elt.href;
            elt.__nodeUrl = url;
            if (!this.dedupe(url, elt)) {
                this.fetch(url, elt);
            }
        },
        dedupe: function (url, elt) {
            if (this.pending[url]) {
                this.pending[url].push(elt);
                return true;
            }
            var resource;
            if (this.cache[url]) {
                this.onload(url, elt, this.cache[url]);
                this.tail();
                return true;
            }
            this.pending[url] = [elt];
            return false;
        },
        fetch: function (url, elt) {
            flags.load && console.log("fetch", url, elt);
            if (!url) {
                setTimeout(function () {
                    this.receive(url, elt, {
                        error: "href must be specified"
                    }, null);
                }.bind(this), 0);
            } else if (url.match(/^data:/)) {
                var pieces = url.split(",");
                var header = pieces[0];
                var body = pieces[1];
                if (header.indexOf(";base64") > -1) {
                    body = atob(body);
                } else {
                    body = decodeURIComponent(body);
                }
                setTimeout(function () {
                    this.receive(url, elt, null, body);
                }.bind(this), 0);
            } else {
                var receiveXhr = function (err, resource, redirectedUrl) {
                    this.receive(url, elt, err, resource, redirectedUrl);
                }.bind(this);
                xhr.load(url, receiveXhr);
            }
        },
        receive: function (url, elt, err, resource, redirectedUrl) {
            this.cache[url] = resource;
            var $p = this.pending[url];
            for (var i = 0, l = $p.length, p; i < l && (p = $p[i]); i++) {
                this.onload(url, p, resource, err, redirectedUrl);
                this.tail();
            }
            this.pending[url] = null;
        },
        tail: function () {
            --this.inflight;
            this.checkDone();
        },
        checkDone: function () {
            if (!this.inflight) {
                this.oncomplete();
            }
        }
    };
    scope.Loader = Loader;
});

HTMLImports.addModule(function (scope) {
    var Observer = function (addCallback) {
        this.addCallback = addCallback;
        this.mo = new MutationObserver(this.handler.bind(this));
    };
    Observer.prototype = {
        handler: function (mutations) {
            for (var i = 0, l = mutations.length, m; i < l && (m = mutations[i]); i++) {
                if (m.type === "childList" && m.addedNodes.length) {
                    this.addedNodes(m.addedNodes);
                }
            }
        },
        addedNodes: function (nodes) {
            if (this.addCallback) {
                this.addCallback(nodes);
            }
            for (var i = 0, l = nodes.length, n, loading; i < l && (n = nodes[i]); i++) {
                if (n.children && n.children.length) {
                    this.addedNodes(n.children);
                }
            }
        },
        observe: function (root) {
            this.mo.observe(root, {
                childList: true,
                subtree: true
            });
        }
    };
    scope.Observer = Observer;
});

HTMLImports.addModule(function (scope) {
    var path = scope.path;
    var rootDocument = scope.rootDocument;
    var flags = scope.flags;
    var isIE = scope.isIE;
    var IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;
    var IMPORT_SELECTOR = "link[rel=" + IMPORT_LINK_TYPE + "]";
    var importParser = {
        documentSelectors: IMPORT_SELECTOR,
        importsSelectors: [IMPORT_SELECTOR, "link[rel=stylesheet]", "style", "script:not([type])", 'script[type="text/javascript"]'].join(","),
        map: {
            link: "parseLink",
            script: "parseScript",
            style: "parseStyle"
        },
        dynamicElements: [],
        parseNext: function () {
            var next = this.nextToParse();
            if (next) {
                this.parse(next);
            }
        },
        parse: function (elt) {
            if (this.isParsed(elt)) {
                flags.parse && console.log("[%s] is already parsed", elt.localName);
                return;
            }
            var fn = this[this.map[elt.localName]];
            if (fn) {
                this.markParsing(elt);
                fn.call(this, elt);
            }
        },
        parseDynamic: function (elt, quiet) {
            this.dynamicElements.push(elt);
            if (!quiet) {
                this.parseNext();
            }
        },
        markParsing: function (elt) {
            flags.parse && console.log("parsing", elt);
            this.parsingElement = elt;
        },
        markParsingComplete: function (elt) {
            elt.__importParsed = true;
            this.markDynamicParsingComplete(elt);
            if (elt.__importElement) {
                elt.__importElement.__importParsed = true;
                this.markDynamicParsingComplete(elt.__importElement);
            }
            this.parsingElement = null;
            flags.parse && console.log("completed", elt);
        },
        markDynamicParsingComplete: function (elt) {
            var i = this.dynamicElements.indexOf(elt);
            if (i >= 0) {
                this.dynamicElements.splice(i, 1);
            }
        },
        parseImport: function (elt) {
            if (HTMLImports.__importsParsingHook) {
                HTMLImports.__importsParsingHook(elt);
            }
            if (elt.import) {
                elt.import.__importParsed = true;
            }
            this.markParsingComplete(elt);
            if (elt.__resource && !elt.__error) {
                elt.dispatchEvent(new CustomEvent("load", {
                    bubbles: false
                }));
            } else {
                elt.dispatchEvent(new CustomEvent("error", {
                    bubbles: false
                }));
            }
            if (elt.__pending) {
                var fn;
                while (elt.__pending.length) {
                    fn = elt.__pending.shift();
                    if (fn) {
                        fn({
                            target: elt
                        });
                    }
                }
            }
            this.parseNext();
        },
        parseLink: function (linkElt) {
            if (nodeIsImport(linkElt)) {
                this.parseImport(linkElt);
            } else {
                linkElt.href = linkElt.href;
                this.parseGeneric(linkElt);
            }
        },
        parseStyle: function (elt) {
            var src = elt;
            elt = cloneStyle(elt);
            elt.__importElement = src;
            this.parseGeneric(elt);
        },
        parseGeneric: function (elt) {
            this.trackElement(elt);
            this.addElementToDocument(elt);
        },
        rootImportForElement: function (elt) {
            var n = elt;
            while (n.ownerDocument.__importLink) {
                n = n.ownerDocument.__importLink;
            }
            return n;
        },
        addElementToDocument: function (elt) {
            var port = this.rootImportForElement(elt.__importElement || elt);
            port.parentNode.insertBefore(elt, port);
        },
        trackElement: function (elt, callback) {
            var self = this;
            var done = function (e) {
                if (callback) {
                    callback(e);
                }
                self.markParsingComplete(elt);
                self.parseNext();
            };
            elt.addEventListener("load", done);
            elt.addEventListener("error", done);
            if (isIE && elt.localName === "style") {
                var fakeLoad = false;
                if (elt.textContent.indexOf("@import") == -1) {
                    fakeLoad = true;
                } else if (elt.sheet) {
                    fakeLoad = true;
                    var csr = elt.sheet.cssRules;
                    var len = csr ? csr.length : 0;
                    for (var i = 0, r; i < len && (r = csr[i]); i++) {
                        if (r.type === CSSRule.IMPORT_RULE) {
                            fakeLoad = fakeLoad && Boolean(r.styleSheet);
                        }
                    }
                }
                if (fakeLoad) {
                    elt.dispatchEvent(new CustomEvent("load", {
                        bubbles: false
                    }));
                }
            }
        },
        parseScript: function (scriptElt) {
            var script = document.createElement("script");
            script.__importElement = scriptElt;
            script.src = scriptElt.src ? scriptElt.src : generateScriptDataUrl(scriptElt);
            scope.currentScript = scriptElt;
            this.trackElement(script, function (e) {
                script.parentNode.removeChild(script);
                scope.currentScript = null;
            });
            this.addElementToDocument(script);
        },
        nextToParse: function () {
            this._mayParse = [];
            return !this.parsingElement && (this.nextToParseInDoc(rootDocument) || this.nextToParseDynamic());
        },
        nextToParseInDoc: function (doc, link) {
            if (doc && this._mayParse.indexOf(doc) < 0) {
                this._mayParse.push(doc);
                var nodes = doc.querySelectorAll(this.parseSelectorsForNode(doc));
                for (var i = 0, l = nodes.length, p = 0, n; i < l && (n = nodes[i]); i++) {
                    if (!this.isParsed(n)) {
                        if (this.hasResource(n)) {
                            return nodeIsImport(n) ? this.nextToParseInDoc(n.import, n) : n;
                        } else {
                            return;
                        }
                    }
                }
            }
            return link;
        },
        nextToParseDynamic: function () {
            return this.dynamicElements[0];
        },
        parseSelectorsForNode: function (node) {
            var doc = node.ownerDocument || node;
            return doc === rootDocument ? this.documentSelectors : this.importsSelectors;
        },
        isParsed: function (node) {
            return node.__importParsed;
        },
        needsDynamicParsing: function (elt) {
            return this.dynamicElements.indexOf(elt) >= 0;
        },
        hasResource: function (node) {
            if (nodeIsImport(node) && node.import === undefined) {
                return false;
            }
            return true;
        }
    };

    function nodeIsImport(elt) {
        return elt.localName === "link" && elt.rel === IMPORT_LINK_TYPE;
    }

    function generateScriptDataUrl(script) {
        var scriptContent = generateScriptContent(script);
        return "data:text/javascript;charset=utf-8," + encodeURIComponent(scriptContent);
    }

    function generateScriptContent(script) {
        return script.textContent + generateSourceMapHint(script);
    }

    function generateSourceMapHint(script) {
        var owner = script.ownerDocument;
        owner.__importedScripts = owner.__importedScripts || 0;
        var moniker = script.ownerDocument.baseURI;
        var num = owner.__importedScripts ? "-" + owner.__importedScripts : "";
        owner.__importedScripts++;
        return "\n//# sourceURL=" + moniker + num + ".js\n";
    }

    function cloneStyle(style) {
        var clone = style.ownerDocument.createElement("style");
        clone.textContent = style.textContent;
        path.resolveUrlsInStyle(clone);
        return clone;
    }

    scope.parser = importParser;
    scope.IMPORT_SELECTOR = IMPORT_SELECTOR;
});

HTMLImports.addModule(function (scope) {
    var flags = scope.flags;
    var IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;
    var IMPORT_SELECTOR = scope.IMPORT_SELECTOR;
    var rootDocument = scope.rootDocument;
    var Loader = scope.Loader;
    var Observer = scope.Observer;
    var parser = scope.parser;
    var importer = {
        documents: {},
        documentPreloadSelectors: IMPORT_SELECTOR,
        importsPreloadSelectors: [IMPORT_SELECTOR].join(","),
        loadNode: function (node) {
            importLoader.addNode(node);
        },
        loadSubtree: function (parent) {
            var nodes = this.marshalNodes(parent);
            importLoader.addNodes(nodes);
        },
        marshalNodes: function (parent) {
            return parent.querySelectorAll(this.loadSelectorsForNode(parent));
        },
        loadSelectorsForNode: function (node) {
            var doc = node.ownerDocument || node;
            return doc === rootDocument ? this.documentPreloadSelectors : this.importsPreloadSelectors;
        },
        loaded: function (url, elt, resource, err, redirectedUrl) {
            flags.load && console.log("loaded", url, elt);
            elt.__resource = resource;
            elt.__error = err;
            if (isImportLink(elt)) {
                var doc = this.documents[url];
                if (doc === undefined) {
                    doc = err ? null : makeDocument(resource, redirectedUrl || url);
                    if (doc) {
                        doc.__importLink = elt;
                        this.bootDocument(doc);
                    }
                    this.documents[url] = doc;
                }
                elt.import = doc;
            }
            parser.parseNext();
        },
        bootDocument: function (doc) {
            this.loadSubtree(doc);
            this.observer.observe(doc);
            parser.parseNext();
        },
        loadedAll: function () {
            parser.parseNext();
        }
    };
    var importLoader = new Loader(importer.loaded.bind(importer), importer.loadedAll.bind(importer));
    importer.observer = new Observer();
    function isImportLink(elt) {
        return isLinkRel(elt, IMPORT_LINK_TYPE);
    }

    function isLinkRel(elt, rel) {
        return elt.localName === "link" && elt.getAttribute("rel") === rel;
    }

    function hasBaseURIAccessor(doc) {
        return !!Object.getOwnPropertyDescriptor(doc, "baseURI");
    }

    function makeDocument(resource, url) {
        var doc = document.implementation.createHTMLDocument(IMPORT_LINK_TYPE);
        doc._URL = url;
        var base = doc.createElement("base");
        base.setAttribute("href", url);
        if (!doc.baseURI && !hasBaseURIAccessor(doc)) {
            Object.defineProperty(doc, "baseURI", {
                value: url
            });
        }
        var meta = doc.createElement("meta");
        meta.setAttribute("charset", "utf-8");
        doc.head.appendChild(meta);
        doc.head.appendChild(base);
        doc.body.innerHTML = resource;
        if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) {
            HTMLTemplateElement.bootstrap(doc);
        }
        return doc;
    }

    if (!document.baseURI) {
        var baseURIDescriptor = {
            get: function () {
                var base = document.querySelector("base");
                return base ? base.href : window.location.href;
            },
            configurable: true
        };
        Object.defineProperty(document, "baseURI", baseURIDescriptor);
        Object.defineProperty(rootDocument, "baseURI", baseURIDescriptor);
    }
    scope.importer = importer;
    scope.importLoader = importLoader;
});

HTMLImports.addModule(function (scope) {
    var parser = scope.parser;
    var importer = scope.importer;
    var dynamic = {
        added: function (nodes) {
            var owner, parsed, loading;
            for (var i = 0, l = nodes.length, n; i < l && (n = nodes[i]); i++) {
                if (!owner) {
                    owner = n.ownerDocument;
                    parsed = parser.isParsed(owner);
                }
                loading = this.shouldLoadNode(n);
                if (loading) {
                    importer.loadNode(n);
                }
                if (this.shouldParseNode(n) && parsed) {
                    parser.parseDynamic(n, loading);
                }
            }
        },
        shouldLoadNode: function (node) {
            return node.nodeType === 1 && matches.call(node, importer.loadSelectorsForNode(node));
        },
        shouldParseNode: function (node) {
            return node.nodeType === 1 && matches.call(node, parser.parseSelectorsForNode(node));
        }
    };
    importer.observer.addCallback = dynamic.added.bind(dynamic);
    var matches = HTMLElement.prototype.matches || HTMLElement.prototype.matchesSelector || HTMLElement.prototype.webkitMatchesSelector || HTMLElement.prototype.mozMatchesSelector || HTMLElement.prototype.msMatchesSelector;
});

(function (scope) {
    var initializeModules = scope.initializeModules;
    var isIE = scope.isIE;
    if (scope.useNative) {
        return;
    }
    if (isIE && typeof window.CustomEvent !== "function") {
        window.CustomEvent = function (inType, params) {
            params = params || {};
            var e = document.createEvent("CustomEvent");
            e.initCustomEvent(inType, Boolean(params.bubbles), Boolean(params.cancelable), params.detail);
            return e;
        };
        window.CustomEvent.prototype = window.Event.prototype;
    }
    initializeModules();
    var rootDocument = scope.rootDocument;

    function bootstrap() {
        HTMLImports.importer.bootDocument(rootDocument);
    }

    if (document.readyState === "complete" || document.readyState === "interactive" && !window.attachEvent) {
        bootstrap();
    } else {
        document.addEventListener("DOMContentLoaded", bootstrap);
    }
})(HTMLImports);

window.CustomElements = window.CustomElements || {
        flags: {}
    };

(function (scope) {
    var flags = scope.flags;
    var modules = [];
    var addModule = function (module) {
        modules.push(module);
    };
    var initializeModules = function () {
        modules.forEach(function (module) {
            module(scope);
        });
    };
    scope.addModule = addModule;
    scope.initializeModules = initializeModules;
    scope.hasNative = Boolean(document.registerElement);
    scope.useNative = !flags.register && scope.hasNative && !window.ShadowDOMPolyfill && (!window.HTMLImports || HTMLImports.useNative);
})(CustomElements);

CustomElements.addModule(function (scope) {
    var IMPORT_LINK_TYPE = window.HTMLImports ? HTMLImports.IMPORT_LINK_TYPE : "none";

    function forSubtree(node, cb) {
        findAllElements(node, function (e) {
            if (cb(e)) {
                return true;
            }
            forRoots(e, cb);
        });
        forRoots(node, cb);
    }

    function findAllElements(node, find, data) {
        var e = node.firstElementChild;
        if (!e) {
            e = node.firstChild;
            while (e && e.nodeType !== Node.ELEMENT_NODE) {
                e = e.nextSibling;
            }
        }
        while (e) {
            if (find(e, data) !== true) {
                findAllElements(e, find, data);
            }
            e = e.nextElementSibling;
        }
        return null;
    }

    function forRoots(node, cb) {
        var root = node.shadowRoot;
        while (root) {
            forSubtree(root, cb);
            root = root.olderShadowRoot;
        }
    }

    var processingDocuments;

    function forDocumentTree(doc, cb) {
        processingDocuments = [];
        _forDocumentTree(doc, cb);
        processingDocuments = null;
    }

    function _forDocumentTree(doc, cb) {
        doc = wrap(doc);
        if (processingDocuments.indexOf(doc) >= 0) {
            return;
        }
        processingDocuments.push(doc);
        var imports = doc.querySelectorAll("link[rel=" + IMPORT_LINK_TYPE + "]");
        for (var i = 0, l = imports.length, n; i < l && (n = imports[i]); i++) {
            if (n.import) {
                _forDocumentTree(n.import, cb);
            }
        }
        cb(doc);
    }

    scope.forDocumentTree = forDocumentTree;
    scope.forSubtree = forSubtree;
});

CustomElements.addModule(function (scope) {
    var flags = scope.flags;
    var forSubtree = scope.forSubtree;
    var forDocumentTree = scope.forDocumentTree;

    function addedNode(node) {
        return added(node) || addedSubtree(node);
    }

    function added(node) {
        if (scope.upgrade(node)) {
            return true;
        }
        attached(node);
    }

    function addedSubtree(node) {
        forSubtree(node, function (e) {
            if (added(e)) {
                return true;
            }
        });
    }

    function attachedNode(node) {
        attached(node);
        if (inDocument(node)) {
            forSubtree(node, function (e) {
                attached(e);
            });
        }
    }

    var hasPolyfillMutations = !window.MutationObserver || window.MutationObserver === window.JsMutationObserver;
    scope.hasPolyfillMutations = hasPolyfillMutations;
    var isPendingMutations = false;
    var pendingMutations = [];

    function deferMutation(fn) {
        pendingMutations.push(fn);
        if (!isPendingMutations) {
            isPendingMutations = true;
            setTimeout(takeMutations);
        }
    }

    function takeMutations() {
        isPendingMutations = false;
        var $p = pendingMutations;
        for (var i = 0, l = $p.length, p; i < l && (p = $p[i]); i++) {
            p();
        }
        pendingMutations = [];
    }

    function attached(element) {
        if (hasPolyfillMutations) {
            deferMutation(function () {
                _attached(element);
            });
        } else {
            _attached(element);
        }
    }

    function _attached(element) {
        if (element.__upgraded__ && (element.attachedCallback || element.detachedCallback)) {
            if (!element.__attached && inDocument(element)) {
                element.__attached = true;
                if (element.attachedCallback) {
                    element.attachedCallback();
                }
            }
        }
    }

    function detachedNode(node) {
        detached(node);
        forSubtree(node, function (e) {
            detached(e);
        });
    }

    function detached(element) {
        if (hasPolyfillMutations) {
            deferMutation(function () {
                _detached(element);
            });
        } else {
            _detached(element);
        }
    }

    function _detached(element) {
        if (element.__upgraded__ && (element.attachedCallback || element.detachedCallback)) {
            if (element.__attached && !inDocument(element)) {
                element.__attached = false;
                if (element.detachedCallback) {
                    element.detachedCallback();
                }
            }
        }
    }

    function inDocument(element) {
        var p = element;
        var doc = wrap(document);
        while (p) {
            if (p == doc) {
                return true;
            }
            p = p.parentNode || p.host;
        }
    }

    function watchShadow(node) {
        if (node.shadowRoot && !node.shadowRoot.__watched) {
            flags.dom && console.log("watching shadow-root for: ", node.localName);
            var root = node.shadowRoot;
            while (root) {
                observe(root);
                root = root.olderShadowRoot;
            }
        }
    }

    function handler(mutations) {
        if (flags.dom) {
            var mx = mutations[0];
            if (mx && mx.type === "childList" && mx.addedNodes) {
                if (mx.addedNodes) {
                    var d = mx.addedNodes[0];
                    while (d && d !== document && !d.host) {
                        d = d.parentNode;
                    }
                    var u = d && (d.URL || d._URL || d.host && d.host.localName) || "";
                    u = u.split("/?").shift().split("/").pop();
                }
            }
            console.group("mutations (%d) [%s]", mutations.length, u || "");
        }
        mutations.forEach(function (mx) {
            if (mx.type === "childList") {
                forEach(mx.addedNodes, function (n) {
                    if (!n.localName) {
                        return;
                    }
                    addedNode(n);
                });
                forEach(mx.removedNodes, function (n) {
                    if (!n.localName) {
                        return;
                    }
                    detachedNode(n);
                });
            }
        });
        flags.dom && console.groupEnd();
    }

    function takeRecords(node) {
        node = wrap(node);
        if (!node) {
            node = wrap(document);
        }
        while (node.parentNode) {
            node = node.parentNode;
        }
        var observer = node.__observer;
        if (observer) {
            handler(observer.takeRecords());
            takeMutations();
        }
    }

    var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);

    function observe(inRoot) {
        if (inRoot.__observer) {
            return;
        }
        var observer = new MutationObserver(handler);
        observer.observe(inRoot, {
            childList: true,
            subtree: true
        });
        inRoot.__observer = observer;
    }

    function upgradeDocument(doc) {
        doc = wrap(doc);
        flags.dom && console.group("upgradeDocument: ", doc.baseURI.split("/").pop());
        addedNode(doc);
        observe(doc);
        flags.dom && console.groupEnd();
    }

    function upgradeDocumentTree(doc) {
        forDocumentTree(doc, upgradeDocument);
    }

    var originalCreateShadowRoot = Element.prototype.createShadowRoot;
    if (originalCreateShadowRoot) {
        Element.prototype.createShadowRoot = function () {
            var root = originalCreateShadowRoot.call(this);
            CustomElements.watchShadow(this);
            return root;
        };
    }
    scope.watchShadow = watchShadow;
    scope.upgradeDocumentTree = upgradeDocumentTree;
    scope.upgradeSubtree = addedSubtree;
    scope.upgradeAll = addedNode;
    scope.attachedNode = attachedNode;
    scope.takeRecords = takeRecords;
});

CustomElements.addModule(function (scope) {
    var flags = scope.flags;

    function upgrade(node) {
        if (!node.__upgraded__ && node.nodeType === Node.ELEMENT_NODE) {
            var is = node.getAttribute("is");
            var definition = scope.getRegisteredDefinition(is || node.localName);
            if (definition) {
                if (is && definition.tag == node.localName) {
                    return upgradeWithDefinition(node, definition);
                } else if (!is && !definition.extends) {
                    return upgradeWithDefinition(node, definition);
                }
            }
        }
    }

    function upgradeWithDefinition(element, definition) {
        flags.upgrade && console.group("upgrade:", element.localName);
        if (definition.is) {
            element.setAttribute("is", definition.is);
        }
        implementPrototype(element, definition);
        element.__upgraded__ = true;
        created(element);
        scope.attachedNode(element);
        scope.upgradeSubtree(element);
        flags.upgrade && console.groupEnd();
        return element;
    }

    function implementPrototype(element, definition) {
        if (Object.__proto__) {
            element.__proto__ = definition.prototype;
        } else {
            customMixin(element, definition.prototype, definition.native);
            element.__proto__ = definition.prototype;
        }
    }

    function customMixin(inTarget, inSrc, inNative) {
        var used = {};
        var p = inSrc;
        while (p !== inNative && p !== HTMLElement.prototype) {
            var keys = Object.getOwnPropertyNames(p);
            for (var i = 0, k; k = keys[i]; i++) {
                if (!used[k]) {
                    Object.defineProperty(inTarget, k, Object.getOwnPropertyDescriptor(p, k));
                    used[k] = 1;
                }
            }
            p = Object.getPrototypeOf(p);
        }
    }

    function created(element) {
        if (element.createdCallback) {
            element.createdCallback();
        }
    }

    scope.upgrade = upgrade;
    scope.upgradeWithDefinition = upgradeWithDefinition;
    scope.implementPrototype = implementPrototype;
});

CustomElements.addModule(function (scope) {
    var upgradeDocumentTree = scope.upgradeDocumentTree;
    var upgrade = scope.upgrade;
    var upgradeWithDefinition = scope.upgradeWithDefinition;
    var implementPrototype = scope.implementPrototype;
    var useNative = scope.useNative;

    function register(name, options) {
        var definition = options || {};
        if (!name) {
            throw new Error("document.registerElement: first argument `name` must not be empty");
        }
        if (name.indexOf("-") < 0) {
            throw new Error("document.registerElement: first argument ('name') must contain a dash ('-'). Argument provided was '" + String(name) + "'.");
        }
        if (isReservedTag(name)) {
            throw new Error("Failed to execute 'registerElement' on 'Document': Registration failed for type '" + String(name) + "'. The type name is invalid.");
        }
        if (getRegisteredDefinition(name)) {
            throw new Error("DuplicateDefinitionError: a type with name '" + String(name) + "' is already registered");
        }
        if (!definition.prototype) {
            definition.prototype = Object.create(HTMLElement.prototype);
        }
        definition.__name = name.toLowerCase();
        definition.lifecycle = definition.lifecycle || {};
        definition.ancestry = ancestry(definition.extends);
        resolveTagName(definition);
        resolvePrototypeChain(definition);
        overrideAttributeApi(definition.prototype);
        registerDefinition(definition.__name, definition);
        definition.ctor = generateConstructor(definition);
        definition.ctor.prototype = definition.prototype;
        definition.prototype.constructor = definition.ctor;
        if (scope.ready) {
            upgradeDocumentTree(document);
        }
        return definition.ctor;
    }

    function overrideAttributeApi(prototype) {
        if (prototype.setAttribute._polyfilled) {
            return;
        }
        var setAttribute = prototype.setAttribute;
        prototype.setAttribute = function (name, value) {
            changeAttribute.call(this, name, value, setAttribute);
        };
        var removeAttribute = prototype.removeAttribute;
        prototype.removeAttribute = function (name) {
            changeAttribute.call(this, name, null, removeAttribute);
        };
        prototype.setAttribute._polyfilled = true;
    }

    function changeAttribute(name, value, operation) {
        name = name.toLowerCase();
        var oldValue = this.getAttribute(name);
        operation.apply(this, arguments);
        var newValue = this.getAttribute(name);
        if (this.attributeChangedCallback && newValue !== oldValue) {
            this.attributeChangedCallback(name, oldValue, newValue);
        }
    }

    function isReservedTag(name) {
        for (var i = 0; i < reservedTagList.length; i++) {
            if (name === reservedTagList[i]) {
                return true;
            }
        }
    }

    var reservedTagList = ["annotation-xml", "color-profile", "font-face", "font-face-src", "font-face-uri", "font-face-format", "font-face-name", "missing-glyph"];

    function ancestry(extnds) {
        var extendee = getRegisteredDefinition(extnds);
        if (extendee) {
            return ancestry(extendee.extends).concat([extendee]);
        }
        return [];
    }

    function resolveTagName(definition) {
        var baseTag = definition.extends;
        for (var i = 0, a; a = definition.ancestry[i]; i++) {
            baseTag = a.is && a.tag;
        }
        definition.tag = baseTag || definition.__name;
        if (baseTag) {
            definition.is = definition.__name;
        }
    }

    function resolvePrototypeChain(definition) {
        if (!Object.__proto__) {
            var nativePrototype = HTMLElement.prototype;
            if (definition.is) {
                var inst = document.createElement(definition.tag);
                var expectedPrototype = Object.getPrototypeOf(inst);
                if (expectedPrototype === definition.prototype) {
                    nativePrototype = expectedPrototype;
                }
            }
            var proto = definition.prototype, ancestor;
            while (proto && proto !== nativePrototype) {
                ancestor = Object.getPrototypeOf(proto);
                proto.__proto__ = ancestor;
                proto = ancestor;
            }
            definition.native = nativePrototype;
        }
    }

    function instantiate(definition) {
        return upgradeWithDefinition(domCreateElement(definition.tag), definition);
    }

    var registry = {};

    function getRegisteredDefinition(name) {
        if (name) {
            return registry[name.toLowerCase()];
        }
    }

    function registerDefinition(name, definition) {
        registry[name] = definition;
    }

    function generateConstructor(definition) {
        return function () {
            return instantiate(definition);
        };
    }

    var HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";

    function createElementNS(namespace, tag, typeExtension) {
        if (namespace === HTML_NAMESPACE) {
            return createElement(tag, typeExtension);
        } else {
            return domCreateElementNS(namespace, tag);
        }
    }

    function createElement(tag, typeExtension) {
        var definition = getRegisteredDefinition(typeExtension || tag);
        if (definition) {
            if (tag == definition.tag && typeExtension == definition.is) {
                return new definition.ctor();
            }
            if (!typeExtension && !definition.is) {
                return new definition.ctor();
            }
        }
        var element;
        if (typeExtension) {
            element = createElement(tag);
            element.setAttribute("is", typeExtension);
            return element;
        }
        element = domCreateElement(tag);
        if (tag.indexOf("-") >= 0) {
            implementPrototype(element, HTMLElement);
        }
        return element;
    }

    function cloneNode(deep) {
        var n = domCloneNode.call(this, deep);
        upgrade(n);
        return n;
    }

    var domCreateElement = document.createElement.bind(document);
    var domCreateElementNS = document.createElementNS.bind(document);
    var domCloneNode = Node.prototype.cloneNode;
    var isInstance;
    if (!Object.__proto__ && !useNative) {
        isInstance = function (obj, ctor) {
            var p = obj;
            while (p) {
                if (p === ctor.prototype) {
                    return true;
                }
                p = p.__proto__;
            }
            return false;
        };
    } else {
        isInstance = function (obj, base) {
            return obj instanceof base;
        };
    }
    document.registerElement = register;
    document.createElement = createElement;
    document.createElementNS = createElementNS;
    Node.prototype.cloneNode = cloneNode;
    scope.registry = registry;
    scope.instanceof = isInstance;
    scope.reservedTagList = reservedTagList;
    scope.getRegisteredDefinition = getRegisteredDefinition;
    document.register = document.registerElement;
});

(function (scope) {
    var useNative = scope.useNative;
    var initializeModules = scope.initializeModules;
    var isIE11OrOlder = /Trident/.test(navigator.userAgent);
    if (useNative) {
        var nop = function () {
        };
        scope.watchShadow = nop;
        scope.upgrade = nop;
        scope.upgradeAll = nop;
        scope.upgradeDocumentTree = nop;
        scope.upgradeSubtree = nop;
        scope.takeRecords = nop;
        scope.instanceof = function (obj, base) {
            return obj instanceof base;
        };
    } else {
        initializeModules();
    }
    var upgradeDocumentTree = scope.upgradeDocumentTree;
    if (!window.wrap) {
        if (window.ShadowDOMPolyfill) {
            window.wrap = ShadowDOMPolyfill.wrapIfNeeded;
            window.unwrap = ShadowDOMPolyfill.unwrapIfNeeded;
        } else {
            window.wrap = window.unwrap = function (node) {
                return node;
            };
        }
    }
    function bootstrap() {
        upgradeDocumentTree(wrap(document));
        if (window.HTMLImports) {
            HTMLImports.__importsParsingHook = function (elt) {
                upgradeDocumentTree(wrap(elt.import));
            };
        }
        CustomElements.ready = true;
        setTimeout(function () {
            CustomElements.readyTime = Date.now();
            if (window.HTMLImports) {
                CustomElements.elapsed = CustomElements.readyTime - HTMLImports.readyTime;
            }
            document.dispatchEvent(new CustomEvent("WebComponentsReady", {
                bubbles: true
            }));
        });
    }

    if (isIE11OrOlder && typeof window.CustomEvent !== "function") {
        window.CustomEvent = function (inType, params) {
            params = params || {};
            var e = document.createEvent("CustomEvent");
            e.initCustomEvent(inType, Boolean(params.bubbles), Boolean(params.cancelable), params.detail);
            return e;
        };
        window.CustomEvent.prototype = window.Event.prototype;
    }
    if (document.readyState === "complete" || scope.flags.eager) {
        bootstrap();
    } else if (document.readyState === "interactive" && !window.attachEvent && (!window.HTMLImports || window.HTMLImports.ready)) {
        bootstrap();
    } else {
        var loadEvent = window.HTMLImports && !HTMLImports.ready ? "HTMLImportsLoaded" : "DOMContentLoaded";
        window.addEventListener(loadEvent, bootstrap);
    }
})(window.CustomElements);

(function (scope) {
    if (!Function.prototype.bind) {
        Function.prototype.bind = function (scope) {
            var self = this;
            var args = Array.prototype.slice.call(arguments, 1);
            return function () {
                var args2 = args.slice();
                args2.push.apply(args2, arguments);
                return self.apply(scope, args2);
            };
        };
    }
})(window.WebComponents);

(function (scope) {
    "use strict";
    if (!window.performance) {
        var start = Date.now();
        window.performance = {
            now: function () {
                return Date.now() - start;
            }
        };
    }
    if (!window.requestAnimationFrame) {
        window.requestAnimationFrame = function () {
            var nativeRaf = window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
            return nativeRaf ? function (callback) {
                return nativeRaf(function () {
                    callback(performance.now());
                });
            } : function (callback) {
                return window.setTimeout(callback, 1e3 / 60);
            };
        }();
    }
    if (!window.cancelAnimationFrame) {
        window.cancelAnimationFrame = function () {
            return window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || function (id) {
                    clearTimeout(id);
                };
        }();
    }
    var elementDeclarations = [];
    var polymerStub = function (name, dictionary) {
        if (typeof name !== "string" && arguments.length === 1) {
            Array.prototype.push.call(arguments, document._currentScript);
        }
        elementDeclarations.push(arguments);
    };
    window.Polymer = polymerStub;
    scope.consumeDeclarations = function (callback) {
        scope.consumeDeclarations = function () {
            throw "Possible attempt to load Polymer twice";
        };
        if (callback) {
            callback(elementDeclarations);
        }
        elementDeclarations = null;
    };
    function installPolymerWarning() {
        if (window.Polymer === polymerStub) {
            window.Polymer = function () {
                throw new Error("You tried to use polymer without loading it first. To " + 'load polymer, <link rel="import" href="' + 'components/polymer/polymer.html">');
            };
        }
    }

    if (HTMLImports.useNative) {
        installPolymerWarning();
    } else {
        addEventListener("DOMContentLoaded", installPolymerWarning);
    }
})(window.WebComponents);

(function (scope) {
    var style = document.createElement("style");
    style.textContent = "" + "body {" + "transition: opacity ease-in 0.2s;" + " } \n" + "body[unresolved] {" + "opacity: 0; display: block; overflow: hidden; position: relative;" + " } \n";
    var head = document.querySelector("head");
    head.insertBefore(style, head.firstChild);
})(window.WebComponents);

(function (scope) {
    window.Platform = scope;
})(window.WebComponents);