Index: frontend/node_modules/cssom/LICENSE.txt
===================================================================
--- frontend/node_modules/cssom/LICENSE.txt	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/LICENSE.txt	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,20 @@
+Copyright (c) Nikita Vasilyev
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Index: frontend/node_modules/cssom/README.mdown
===================================================================
--- frontend/node_modules/cssom/README.mdown	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/README.mdown	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,67 @@
+# CSSOM
+
+CSSOM.js is a CSS parser written in pure JavaScript. It is also a partial implementation of [CSS Object Model](http://dev.w3.org/csswg/cssom/). 
+
+    CSSOM.parse("body {color: black}")
+    -> {
+      cssRules: [
+        {
+          selectorText: "body",
+          style: {
+            0: "color",
+            color: "black",
+            length: 1
+          }
+        }
+      ]
+    }
+
+
+## [Parser demo](http://nv.github.com/CSSOM/docs/parse.html)
+
+Works well in Google Chrome 6+, Safari 5+, Firefox 3.6+, Opera 10.63+.
+Doesn't work in IE < 9 because of unsupported getters/setters.
+
+To use CSSOM.js in the browser you might want to build a one-file version that exposes a single `CSSOM` global variable:
+
+    ➤ git clone https://github.com/NV/CSSOM.git
+    ➤ cd CSSOM
+    ➤ node build.js
+    build/CSSOM.js is done
+
+To use it with Node.js or any other CommonJS loader:
+
+    ➤ npm install cssom
+
+## Don’t use it if...
+
+You parse CSS to mungle, minify or reformat code like this:
+
+```css
+div {
+  background: gray;
+  background: linear-gradient(to bottom, white 0%, black 100%);
+}
+```
+
+This pattern is often used to give browsers that don’t understand linear gradients a fallback solution (e.g. gray color in the example).
+In CSSOM, `background: gray` [gets overwritten](http://nv.github.io/CSSOM/docs/parse.html#css=div%20%7B%0A%20%20%20%20%20%20background%3A%20gray%3B%0A%20%20%20%20background%3A%20linear-gradient(to%20bottom%2C%20white%200%25%2C%20black%20100%25)%3B%0A%7D).
+It doesn't get preserved.
+
+If you do CSS mungling, minification, image inlining, and such, CSSOM.js is no good for you, considere using one of the following:
+
+  * [postcss](https://github.com/postcss/postcss)
+  * [reworkcss/css](https://github.com/reworkcss/css)
+  * [csso](https://github.com/css/csso)
+  * [mensch](https://github.com/brettstimmerman/mensch)
+
+
+## [Tests](http://nv.github.com/CSSOM/spec/)
+
+To run tests locally:
+
+    ➤ git submodule init
+    ➤ git submodule update
+
+
+## [Who uses CSSOM.js](https://github.com/NV/CSSOM/wiki/Who-uses-CSSOM.js)
Index: frontend/node_modules/cssom/lib/CSSDocumentRule.js
===================================================================
--- frontend/node_modules/cssom/lib/CSSDocumentRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/CSSDocumentRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,39 @@
+//.CommonJS
+var CSSOM = {
+    CSSRule: require("./CSSRule").CSSRule,
+    MatcherList: require("./MatcherList").MatcherList
+};
+///CommonJS
+
+
+/**
+ * @constructor
+ * @see https://developer.mozilla.org/en/CSS/@-moz-document
+ */
+CSSOM.CSSDocumentRule = function CSSDocumentRule() {
+    CSSOM.CSSRule.call(this);
+    this.matcher = new CSSOM.MatcherList();
+    this.cssRules = [];
+};
+
+CSSOM.CSSDocumentRule.prototype = new CSSOM.CSSRule();
+CSSOM.CSSDocumentRule.prototype.constructor = CSSOM.CSSDocumentRule;
+CSSOM.CSSDocumentRule.prototype.type = 10;
+//FIXME
+//CSSOM.CSSDocumentRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
+//CSSOM.CSSDocumentRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
+
+Object.defineProperty(CSSOM.CSSDocumentRule.prototype, "cssText", {
+  get: function() {
+    var cssTexts = [];
+    for (var i=0, length=this.cssRules.length; i < length; i++) {
+        cssTexts.push(this.cssRules[i].cssText);
+    }
+    return "@-moz-document " + this.matcher.matcherText + " {" + cssTexts.join("") + "}";
+  }
+});
+
+
+//.CommonJS
+exports.CSSDocumentRule = CSSOM.CSSDocumentRule;
+///CommonJS
Index: frontend/node_modules/cssom/lib/CSSFontFaceRule.js
===================================================================
--- frontend/node_modules/cssom/lib/CSSFontFaceRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/CSSFontFaceRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,36 @@
+//.CommonJS
+var CSSOM = {
+	CSSStyleDeclaration: require("./CSSStyleDeclaration").CSSStyleDeclaration,
+	CSSRule: require("./CSSRule").CSSRule
+};
+///CommonJS
+
+
+/**
+ * @constructor
+ * @see http://dev.w3.org/csswg/cssom/#css-font-face-rule
+ */
+CSSOM.CSSFontFaceRule = function CSSFontFaceRule() {
+	CSSOM.CSSRule.call(this);
+	this.style = new CSSOM.CSSStyleDeclaration();
+	this.style.parentRule = this;
+};
+
+CSSOM.CSSFontFaceRule.prototype = new CSSOM.CSSRule();
+CSSOM.CSSFontFaceRule.prototype.constructor = CSSOM.CSSFontFaceRule;
+CSSOM.CSSFontFaceRule.prototype.type = 5;
+//FIXME
+//CSSOM.CSSFontFaceRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
+//CSSOM.CSSFontFaceRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
+
+// http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSFontFaceRule.cpp
+Object.defineProperty(CSSOM.CSSFontFaceRule.prototype, "cssText", {
+  get: function() {
+    return "@font-face {" + this.style.cssText + "}";
+  }
+});
+
+
+//.CommonJS
+exports.CSSFontFaceRule = CSSOM.CSSFontFaceRule;
+///CommonJS
Index: frontend/node_modules/cssom/lib/CSSHostRule.js
===================================================================
--- frontend/node_modules/cssom/lib/CSSHostRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/CSSHostRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,37 @@
+//.CommonJS
+var CSSOM = {
+	CSSRule: require("./CSSRule").CSSRule
+};
+///CommonJS
+
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/shadow-dom/#host-at-rule
+ */
+CSSOM.CSSHostRule = function CSSHostRule() {
+	CSSOM.CSSRule.call(this);
+	this.cssRules = [];
+};
+
+CSSOM.CSSHostRule.prototype = new CSSOM.CSSRule();
+CSSOM.CSSHostRule.prototype.constructor = CSSOM.CSSHostRule;
+CSSOM.CSSHostRule.prototype.type = 1001;
+//FIXME
+//CSSOM.CSSHostRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
+//CSSOM.CSSHostRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
+
+Object.defineProperty(CSSOM.CSSHostRule.prototype, "cssText", {
+	get: function() {
+		var cssTexts = [];
+		for (var i=0, length=this.cssRules.length; i < length; i++) {
+			cssTexts.push(this.cssRules[i].cssText);
+		}
+		return "@host {" + cssTexts.join("") + "}";
+	}
+});
+
+
+//.CommonJS
+exports.CSSHostRule = CSSOM.CSSHostRule;
+///CommonJS
Index: frontend/node_modules/cssom/lib/CSSImportRule.js
===================================================================
--- frontend/node_modules/cssom/lib/CSSImportRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/CSSImportRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,132 @@
+//.CommonJS
+var CSSOM = {
+	CSSRule: require("./CSSRule").CSSRule,
+	CSSStyleSheet: require("./CSSStyleSheet").CSSStyleSheet,
+	MediaList: require("./MediaList").MediaList
+};
+///CommonJS
+
+
+/**
+ * @constructor
+ * @see http://dev.w3.org/csswg/cssom/#cssimportrule
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSImportRule
+ */
+CSSOM.CSSImportRule = function CSSImportRule() {
+	CSSOM.CSSRule.call(this);
+	this.href = "";
+	this.media = new CSSOM.MediaList();
+	this.styleSheet = new CSSOM.CSSStyleSheet();
+};
+
+CSSOM.CSSImportRule.prototype = new CSSOM.CSSRule();
+CSSOM.CSSImportRule.prototype.constructor = CSSOM.CSSImportRule;
+CSSOM.CSSImportRule.prototype.type = 3;
+
+Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", {
+  get: function() {
+    var mediaText = this.media.mediaText;
+    return "@import url(" + this.href + ")" + (mediaText ? " " + mediaText : "") + ";";
+  },
+  set: function(cssText) {
+    var i = 0;
+
+    /**
+     * @import url(partial.css) screen, handheld;
+     *        ||               |
+     *        after-import     media
+     *         |
+     *         url
+     */
+    var state = '';
+
+    var buffer = '';
+    var index;
+    for (var character; (character = cssText.charAt(i)); i++) {
+
+      switch (character) {
+        case ' ':
+        case '\t':
+        case '\r':
+        case '\n':
+        case '\f':
+          if (state === 'after-import') {
+            state = 'url';
+          } else {
+            buffer += character;
+          }
+          break;
+
+        case '@':
+          if (!state && cssText.indexOf('@import', i) === i) {
+            state = 'after-import';
+            i += 'import'.length;
+            buffer = '';
+          }
+          break;
+
+        case 'u':
+          if (state === 'url' && cssText.indexOf('url(', i) === i) {
+            index = cssText.indexOf(')', i + 1);
+            if (index === -1) {
+              throw i + ': ")" not found';
+            }
+            i += 'url('.length;
+            var url = cssText.slice(i, index);
+            if (url[0] === url[url.length - 1]) {
+              if (url[0] === '"' || url[0] === "'") {
+                url = url.slice(1, -1);
+              }
+            }
+            this.href = url;
+            i = index;
+            state = 'media';
+          }
+          break;
+
+        case '"':
+          if (state === 'url') {
+            index = cssText.indexOf('"', i + 1);
+            if (!index) {
+              throw i + ": '\"' not found";
+            }
+            this.href = cssText.slice(i + 1, index);
+            i = index;
+            state = 'media';
+          }
+          break;
+
+        case "'":
+          if (state === 'url') {
+            index = cssText.indexOf("'", i + 1);
+            if (!index) {
+              throw i + ': "\'" not found';
+            }
+            this.href = cssText.slice(i + 1, index);
+            i = index;
+            state = 'media';
+          }
+          break;
+
+        case ';':
+          if (state === 'media') {
+            if (buffer) {
+              this.media.mediaText = buffer.trim();
+            }
+          }
+          break;
+
+        default:
+          if (state === 'media') {
+            buffer += character;
+          }
+          break;
+      }
+    }
+  }
+});
+
+
+//.CommonJS
+exports.CSSImportRule = CSSOM.CSSImportRule;
+///CommonJS
Index: frontend/node_modules/cssom/lib/CSSKeyframeRule.js
===================================================================
--- frontend/node_modules/cssom/lib/CSSKeyframeRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/CSSKeyframeRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,37 @@
+//.CommonJS
+var CSSOM = {
+	CSSRule: require("./CSSRule").CSSRule,
+	CSSStyleDeclaration: require('./CSSStyleDeclaration').CSSStyleDeclaration
+};
+///CommonJS
+
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/css3-animations/#DOM-CSSKeyframeRule
+ */
+CSSOM.CSSKeyframeRule = function CSSKeyframeRule() {
+	CSSOM.CSSRule.call(this);
+	this.keyText = '';
+	this.style = new CSSOM.CSSStyleDeclaration();
+	this.style.parentRule = this;
+};
+
+CSSOM.CSSKeyframeRule.prototype = new CSSOM.CSSRule();
+CSSOM.CSSKeyframeRule.prototype.constructor = CSSOM.CSSKeyframeRule;
+CSSOM.CSSKeyframeRule.prototype.type = 8;
+//FIXME
+//CSSOM.CSSKeyframeRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
+//CSSOM.CSSKeyframeRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
+
+// http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSKeyframeRule.cpp
+Object.defineProperty(CSSOM.CSSKeyframeRule.prototype, "cssText", {
+  get: function() {
+    return this.keyText + " {" + this.style.cssText + "} ";
+  }
+});
+
+
+//.CommonJS
+exports.CSSKeyframeRule = CSSOM.CSSKeyframeRule;
+///CommonJS
Index: frontend/node_modules/cssom/lib/CSSKeyframesRule.js
===================================================================
--- frontend/node_modules/cssom/lib/CSSKeyframesRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/CSSKeyframesRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,39 @@
+//.CommonJS
+var CSSOM = {
+	CSSRule: require("./CSSRule").CSSRule
+};
+///CommonJS
+
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/css3-animations/#DOM-CSSKeyframesRule
+ */
+CSSOM.CSSKeyframesRule = function CSSKeyframesRule() {
+	CSSOM.CSSRule.call(this);
+	this.name = '';
+	this.cssRules = [];
+};
+
+CSSOM.CSSKeyframesRule.prototype = new CSSOM.CSSRule();
+CSSOM.CSSKeyframesRule.prototype.constructor = CSSOM.CSSKeyframesRule;
+CSSOM.CSSKeyframesRule.prototype.type = 7;
+//FIXME
+//CSSOM.CSSKeyframesRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
+//CSSOM.CSSKeyframesRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
+
+// http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSKeyframesRule.cpp
+Object.defineProperty(CSSOM.CSSKeyframesRule.prototype, "cssText", {
+  get: function() {
+    var cssTexts = [];
+    for (var i=0, length=this.cssRules.length; i < length; i++) {
+      cssTexts.push("  " + this.cssRules[i].cssText);
+    }
+    return "@" + (this._vendorPrefix || '') + "keyframes " + this.name + " { \n" + cssTexts.join("\n") + "\n}";
+  }
+});
+
+
+//.CommonJS
+exports.CSSKeyframesRule = CSSOM.CSSKeyframesRule;
+///CommonJS
Index: frontend/node_modules/cssom/lib/CSSMediaRule.js
===================================================================
--- frontend/node_modules/cssom/lib/CSSMediaRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/CSSMediaRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,41 @@
+//.CommonJS
+var CSSOM = {
+	CSSRule: require("./CSSRule").CSSRule,
+	MediaList: require("./MediaList").MediaList
+};
+///CommonJS
+
+
+/**
+ * @constructor
+ * @see http://dev.w3.org/csswg/cssom/#cssmediarule
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSMediaRule
+ */
+CSSOM.CSSMediaRule = function CSSMediaRule() {
+	CSSOM.CSSRule.call(this);
+	this.media = new CSSOM.MediaList();
+	this.cssRules = [];
+};
+
+CSSOM.CSSMediaRule.prototype = new CSSOM.CSSRule();
+CSSOM.CSSMediaRule.prototype.constructor = CSSOM.CSSMediaRule;
+CSSOM.CSSMediaRule.prototype.type = 4;
+//FIXME
+//CSSOM.CSSMediaRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
+//CSSOM.CSSMediaRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
+
+// http://opensource.apple.com/source/WebCore/WebCore-658.28/css/CSSMediaRule.cpp
+Object.defineProperty(CSSOM.CSSMediaRule.prototype, "cssText", {
+  get: function() {
+    var cssTexts = [];
+    for (var i=0, length=this.cssRules.length; i < length; i++) {
+      cssTexts.push(this.cssRules[i].cssText);
+    }
+    return "@media " + this.media.mediaText + " {" + cssTexts.join("") + "}";
+  }
+});
+
+
+//.CommonJS
+exports.CSSMediaRule = CSSOM.CSSMediaRule;
+///CommonJS
Index: frontend/node_modules/cssom/lib/CSSOM.js
===================================================================
--- frontend/node_modules/cssom/lib/CSSOM.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/CSSOM.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,3 @@
+var CSSOM = {};
+
+
Index: frontend/node_modules/cssom/lib/CSSRule.js
===================================================================
--- frontend/node_modules/cssom/lib/CSSRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/CSSRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,43 @@
+//.CommonJS
+var CSSOM = {};
+///CommonJS
+
+
+/**
+ * @constructor
+ * @see http://dev.w3.org/csswg/cssom/#the-cssrule-interface
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule
+ */
+CSSOM.CSSRule = function CSSRule() {
+	this.parentRule = null;
+	this.parentStyleSheet = null;
+};
+
+CSSOM.CSSRule.UNKNOWN_RULE = 0;                 // obsolete
+CSSOM.CSSRule.STYLE_RULE = 1;
+CSSOM.CSSRule.CHARSET_RULE = 2;                 // obsolete
+CSSOM.CSSRule.IMPORT_RULE = 3;
+CSSOM.CSSRule.MEDIA_RULE = 4;
+CSSOM.CSSRule.FONT_FACE_RULE = 5;
+CSSOM.CSSRule.PAGE_RULE = 6;
+CSSOM.CSSRule.KEYFRAMES_RULE = 7;
+CSSOM.CSSRule.KEYFRAME_RULE = 8;
+CSSOM.CSSRule.MARGIN_RULE = 9;
+CSSOM.CSSRule.NAMESPACE_RULE = 10;
+CSSOM.CSSRule.COUNTER_STYLE_RULE = 11;
+CSSOM.CSSRule.SUPPORTS_RULE = 12;
+CSSOM.CSSRule.DOCUMENT_RULE = 13;
+CSSOM.CSSRule.FONT_FEATURE_VALUES_RULE = 14;
+CSSOM.CSSRule.VIEWPORT_RULE = 15;
+CSSOM.CSSRule.REGION_STYLE_RULE = 16;
+
+
+CSSOM.CSSRule.prototype = {
+	constructor: CSSOM.CSSRule
+	//FIXME
+};
+
+
+//.CommonJS
+exports.CSSRule = CSSOM.CSSRule;
+///CommonJS
Index: frontend/node_modules/cssom/lib/CSSStyleDeclaration.js
===================================================================
--- frontend/node_modules/cssom/lib/CSSStyleDeclaration.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/CSSStyleDeclaration.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,148 @@
+//.CommonJS
+var CSSOM = {};
+///CommonJS
+
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration
+ */
+CSSOM.CSSStyleDeclaration = function CSSStyleDeclaration(){
+	this.length = 0;
+	this.parentRule = null;
+
+	// NON-STANDARD
+	this._importants = {};
+};
+
+
+CSSOM.CSSStyleDeclaration.prototype = {
+
+	constructor: CSSOM.CSSStyleDeclaration,
+
+	/**
+	 *
+	 * @param {string} name
+	 * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-getPropertyValue
+	 * @return {string} the value of the property if it has been explicitly set for this declaration block.
+	 * Returns the empty string if the property has not been set.
+	 */
+	getPropertyValue: function(name) {
+		return this[name] || "";
+	},
+
+	/**
+	 *
+	 * @param {string} name
+	 * @param {string} value
+	 * @param {string} [priority=null] "important" or null
+	 * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-setProperty
+	 */
+	setProperty: function(name, value, priority) {
+		if (this[name]) {
+			// Property already exist. Overwrite it.
+			var index = Array.prototype.indexOf.call(this, name);
+			if (index < 0) {
+				this[this.length] = name;
+				this.length++;
+			}
+		} else {
+			// New property.
+			this[this.length] = name;
+			this.length++;
+		}
+		this[name] = value + "";
+		this._importants[name] = priority;
+	},
+
+	/**
+	 *
+	 * @param {string} name
+	 * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-removeProperty
+	 * @return {string} the value of the property if it has been explicitly set for this declaration block.
+	 * Returns the empty string if the property has not been set or the property name does not correspond to a known CSS property.
+	 */
+	removeProperty: function(name) {
+		if (!(name in this)) {
+			return "";
+		}
+		var index = Array.prototype.indexOf.call(this, name);
+		if (index < 0) {
+			return "";
+		}
+		var prevValue = this[name];
+		this[name] = "";
+
+		// That's what WebKit and Opera do
+		Array.prototype.splice.call(this, index, 1);
+
+		// That's what Firefox does
+		//this[index] = ""
+
+		return prevValue;
+	},
+
+	getPropertyCSSValue: function() {
+		//FIXME
+	},
+
+	/**
+	 *
+	 * @param {String} name
+	 */
+	getPropertyPriority: function(name) {
+		return this._importants[name] || "";
+	},
+
+
+	/**
+	 *   element.style.overflow = "auto"
+	 *   element.style.getPropertyShorthand("overflow-x")
+	 *   -> "overflow"
+	 */
+	getPropertyShorthand: function() {
+		//FIXME
+	},
+
+	isPropertyImplicit: function() {
+		//FIXME
+	},
+
+	// Doesn't work in IE < 9
+	get cssText(){
+		var properties = [];
+		for (var i=0, length=this.length; i < length; ++i) {
+			var name = this[i];
+			var value = this.getPropertyValue(name);
+			var priority = this.getPropertyPriority(name);
+			if (priority) {
+				priority = " !" + priority;
+			}
+			properties[i] = name + ": " + value + priority + ";";
+		}
+		return properties.join(" ");
+	},
+
+	set cssText(text){
+		var i, name;
+		for (i = this.length; i--;) {
+			name = this[i];
+			this[name] = "";
+		}
+		Array.prototype.splice.call(this, 0, this.length);
+		this._importants = {};
+
+		var dummyRule = CSSOM.parse('#bogus{' + text + '}').cssRules[0].style;
+		var length = dummyRule.length;
+		for (i = 0; i < length; ++i) {
+			name = dummyRule[i];
+			this.setProperty(dummyRule[i], dummyRule.getPropertyValue(name), dummyRule.getPropertyPriority(name));
+		}
+	}
+};
+
+
+//.CommonJS
+exports.CSSStyleDeclaration = CSSOM.CSSStyleDeclaration;
+CSSOM.parse = require('./parse').parse; // Cannot be included sooner due to the mutual dependency between parse.js and CSSStyleDeclaration.js
+///CommonJS
Index: frontend/node_modules/cssom/lib/CSSStyleRule.js
===================================================================
--- frontend/node_modules/cssom/lib/CSSStyleRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/CSSStyleRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,190 @@
+//.CommonJS
+var CSSOM = {
+	CSSStyleDeclaration: require("./CSSStyleDeclaration").CSSStyleDeclaration,
+	CSSRule: require("./CSSRule").CSSRule
+};
+///CommonJS
+
+
+/**
+ * @constructor
+ * @see http://dev.w3.org/csswg/cssom/#cssstylerule
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleRule
+ */
+CSSOM.CSSStyleRule = function CSSStyleRule() {
+	CSSOM.CSSRule.call(this);
+	this.selectorText = "";
+	this.style = new CSSOM.CSSStyleDeclaration();
+	this.style.parentRule = this;
+};
+
+CSSOM.CSSStyleRule.prototype = new CSSOM.CSSRule();
+CSSOM.CSSStyleRule.prototype.constructor = CSSOM.CSSStyleRule;
+CSSOM.CSSStyleRule.prototype.type = 1;
+
+Object.defineProperty(CSSOM.CSSStyleRule.prototype, "cssText", {
+	get: function() {
+		var text;
+		if (this.selectorText) {
+			text = this.selectorText + " {" + this.style.cssText + "}";
+		} else {
+			text = "";
+		}
+		return text;
+	},
+	set: function(cssText) {
+		var rule = CSSOM.CSSStyleRule.parse(cssText);
+		this.style = rule.style;
+		this.selectorText = rule.selectorText;
+	}
+});
+
+
+/**
+ * NON-STANDARD
+ * lightweight version of parse.js.
+ * @param {string} ruleText
+ * @return CSSStyleRule
+ */
+CSSOM.CSSStyleRule.parse = function(ruleText) {
+	var i = 0;
+	var state = "selector";
+	var index;
+	var j = i;
+	var buffer = "";
+
+	var SIGNIFICANT_WHITESPACE = {
+		"selector": true,
+		"value": true
+	};
+
+	var styleRule = new CSSOM.CSSStyleRule();
+	var name, priority="";
+
+	for (var character; (character = ruleText.charAt(i)); i++) {
+
+		switch (character) {
+
+		case " ":
+		case "\t":
+		case "\r":
+		case "\n":
+		case "\f":
+			if (SIGNIFICANT_WHITESPACE[state]) {
+				// Squash 2 or more white-spaces in the row into 1
+				switch (ruleText.charAt(i - 1)) {
+					case " ":
+					case "\t":
+					case "\r":
+					case "\n":
+					case "\f":
+						break;
+					default:
+						buffer += " ";
+						break;
+				}
+			}
+			break;
+
+		// String
+		case '"':
+			j = i + 1;
+			index = ruleText.indexOf('"', j) + 1;
+			if (!index) {
+				throw '" is missing';
+			}
+			buffer += ruleText.slice(i, index);
+			i = index - 1;
+			break;
+
+		case "'":
+			j = i + 1;
+			index = ruleText.indexOf("'", j) + 1;
+			if (!index) {
+				throw "' is missing";
+			}
+			buffer += ruleText.slice(i, index);
+			i = index - 1;
+			break;
+
+		// Comment
+		case "/":
+			if (ruleText.charAt(i + 1) === "*") {
+				i += 2;
+				index = ruleText.indexOf("*/", i);
+				if (index === -1) {
+					throw new SyntaxError("Missing */");
+				} else {
+					i = index + 1;
+				}
+			} else {
+				buffer += character;
+			}
+			break;
+
+		case "{":
+			if (state === "selector") {
+				styleRule.selectorText = buffer.trim();
+				buffer = "";
+				state = "name";
+			}
+			break;
+
+		case ":":
+			if (state === "name") {
+				name = buffer.trim();
+				buffer = "";
+				state = "value";
+			} else {
+				buffer += character;
+			}
+			break;
+
+		case "!":
+			if (state === "value" && ruleText.indexOf("!important", i) === i) {
+				priority = "important";
+				i += "important".length;
+			} else {
+				buffer += character;
+			}
+			break;
+
+		case ";":
+			if (state === "value") {
+				styleRule.style.setProperty(name, buffer.trim(), priority);
+				priority = "";
+				buffer = "";
+				state = "name";
+			} else {
+				buffer += character;
+			}
+			break;
+
+		case "}":
+			if (state === "value") {
+				styleRule.style.setProperty(name, buffer.trim(), priority);
+				priority = "";
+				buffer = "";
+			} else if (state === "name") {
+				break;
+			} else {
+				buffer += character;
+			}
+			state = "selector";
+			break;
+
+		default:
+			buffer += character;
+			break;
+
+		}
+	}
+
+	return styleRule;
+
+};
+
+
+//.CommonJS
+exports.CSSStyleRule = CSSOM.CSSStyleRule;
+///CommonJS
Index: frontend/node_modules/cssom/lib/CSSStyleSheet.js
===================================================================
--- frontend/node_modules/cssom/lib/CSSStyleSheet.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/CSSStyleSheet.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,88 @@
+//.CommonJS
+var CSSOM = {
+	StyleSheet: require("./StyleSheet").StyleSheet,
+	CSSStyleRule: require("./CSSStyleRule").CSSStyleRule
+};
+///CommonJS
+
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet
+ */
+CSSOM.CSSStyleSheet = function CSSStyleSheet() {
+	CSSOM.StyleSheet.call(this);
+	this.cssRules = [];
+};
+
+
+CSSOM.CSSStyleSheet.prototype = new CSSOM.StyleSheet();
+CSSOM.CSSStyleSheet.prototype.constructor = CSSOM.CSSStyleSheet;
+
+
+/**
+ * Used to insert a new rule into the style sheet. The new rule now becomes part of the cascade.
+ *
+ *   sheet = new Sheet("body {margin: 0}")
+ *   sheet.toString()
+ *   -> "body{margin:0;}"
+ *   sheet.insertRule("img {border: none}", 0)
+ *   -> 0
+ *   sheet.toString()
+ *   -> "img{border:none;}body{margin:0;}"
+ *
+ * @param {string} rule
+ * @param {number} index
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet-insertRule
+ * @return {number} The index within the style sheet's rule collection of the newly inserted rule.
+ */
+CSSOM.CSSStyleSheet.prototype.insertRule = function(rule, index) {
+	if (index < 0 || index > this.cssRules.length) {
+		throw new RangeError("INDEX_SIZE_ERR");
+	}
+	var cssRule = CSSOM.parse(rule).cssRules[0];
+	cssRule.parentStyleSheet = this;
+	this.cssRules.splice(index, 0, cssRule);
+	return index;
+};
+
+
+/**
+ * Used to delete a rule from the style sheet.
+ *
+ *   sheet = new Sheet("img{border:none} body{margin:0}")
+ *   sheet.toString()
+ *   -> "img{border:none;}body{margin:0;}"
+ *   sheet.deleteRule(0)
+ *   sheet.toString()
+ *   -> "body{margin:0;}"
+ *
+ * @param {number} index within the style sheet's rule list of the rule to remove.
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet-deleteRule
+ */
+CSSOM.CSSStyleSheet.prototype.deleteRule = function(index) {
+	if (index < 0 || index >= this.cssRules.length) {
+		throw new RangeError("INDEX_SIZE_ERR");
+	}
+	this.cssRules.splice(index, 1);
+};
+
+
+/**
+ * NON-STANDARD
+ * @return {string} serialize stylesheet
+ */
+CSSOM.CSSStyleSheet.prototype.toString = function() {
+	var result = "";
+	var rules = this.cssRules;
+	for (var i=0; i<rules.length; i++) {
+		result += rules[i].cssText + "\n";
+	}
+	return result;
+};
+
+
+//.CommonJS
+exports.CSSStyleSheet = CSSOM.CSSStyleSheet;
+CSSOM.parse = require('./parse').parse; // Cannot be included sooner due to the mutual dependency between parse.js and CSSStyleSheet.js
+///CommonJS
Index: frontend/node_modules/cssom/lib/CSSSupportsRule.js
===================================================================
--- frontend/node_modules/cssom/lib/CSSSupportsRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/CSSSupportsRule.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,36 @@
+//.CommonJS
+var CSSOM = {
+  CSSRule: require("./CSSRule").CSSRule,
+};
+///CommonJS
+
+
+/**
+ * @constructor
+ * @see https://drafts.csswg.org/css-conditional-3/#the-csssupportsrule-interface
+ */
+CSSOM.CSSSupportsRule = function CSSSupportsRule() {
+  CSSOM.CSSRule.call(this);
+  this.conditionText = '';
+  this.cssRules = [];
+};
+
+CSSOM.CSSSupportsRule.prototype = new CSSOM.CSSRule();
+CSSOM.CSSSupportsRule.prototype.constructor = CSSOM.CSSSupportsRule;
+CSSOM.CSSSupportsRule.prototype.type = 12;
+
+Object.defineProperty(CSSOM.CSSSupportsRule.prototype, "cssText", {
+  get: function() {
+    var cssTexts = [];
+
+    for (var i = 0, length = this.cssRules.length; i < length; i++) {
+      cssTexts.push(this.cssRules[i].cssText);
+    }
+
+    return "@supports " + this.conditionText + " {" + cssTexts.join("") + "}";
+  }
+});
+
+//.CommonJS
+exports.CSSSupportsRule = CSSOM.CSSSupportsRule;
+///CommonJS
Index: frontend/node_modules/cssom/lib/CSSValue.js
===================================================================
--- frontend/node_modules/cssom/lib/CSSValue.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/CSSValue.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,43 @@
+//.CommonJS
+var CSSOM = {};
+///CommonJS
+
+
+/**
+ * @constructor
+ * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue
+ *
+ * TODO: add if needed
+ */
+CSSOM.CSSValue = function CSSValue() {
+};
+
+CSSOM.CSSValue.prototype = {
+	constructor: CSSOM.CSSValue,
+
+	// @see: http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue
+	set cssText(text) {
+		var name = this._getConstructorName();
+
+		throw new Error('DOMException: property "cssText" of "' + name + '" is readonly and can not be replaced with "' + text + '"!');
+	},
+
+	get cssText() {
+		var name = this._getConstructorName();
+
+		throw new Error('getter "cssText" of "' + name + '" is not implemented!');
+	},
+
+	_getConstructorName: function() {
+		var s = this.constructor.toString(),
+				c = s.match(/function\s([^\(]+)/),
+				name = c[1];
+
+		return name;
+	}
+};
+
+
+//.CommonJS
+exports.CSSValue = CSSOM.CSSValue;
+///CommonJS
Index: frontend/node_modules/cssom/lib/CSSValueExpression.js
===================================================================
--- frontend/node_modules/cssom/lib/CSSValueExpression.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/CSSValueExpression.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,344 @@
+//.CommonJS
+var CSSOM = {
+	CSSValue: require('./CSSValue').CSSValue
+};
+///CommonJS
+
+
+/**
+ * @constructor
+ * @see http://msdn.microsoft.com/en-us/library/ms537634(v=vs.85).aspx
+ *
+ */
+CSSOM.CSSValueExpression = function CSSValueExpression(token, idx) {
+	this._token = token;
+	this._idx = idx;
+};
+
+CSSOM.CSSValueExpression.prototype = new CSSOM.CSSValue();
+CSSOM.CSSValueExpression.prototype.constructor = CSSOM.CSSValueExpression;
+
+/**
+ * parse css expression() value
+ *
+ * @return {Object}
+ *         - error:
+ *         or
+ *         - idx:
+ *         - expression:
+ *
+ * Example:
+ *
+ * .selector {
+ *		zoom: expression(documentElement.clientWidth > 1000 ? '1000px' : 'auto');
+ * }
+ */
+CSSOM.CSSValueExpression.prototype.parse = function() {
+	var token = this._token,
+			idx = this._idx;
+
+	var character = '',
+			expression = '',
+			error = '',
+			info,
+			paren = [];
+
+
+	for (; ; ++idx) {
+		character = token.charAt(idx);
+
+		// end of token
+		if (character === '') {
+			error = 'css expression error: unfinished expression!';
+			break;
+		}
+
+		switch(character) {
+			case '(':
+				paren.push(character);
+				expression += character;
+				break;
+
+			case ')':
+				paren.pop(character);
+				expression += character;
+				break;
+
+			case '/':
+				if ((info = this._parseJSComment(token, idx))) { // comment?
+					if (info.error) {
+						error = 'css expression error: unfinished comment in expression!';
+					} else {
+						idx = info.idx;
+						// ignore the comment
+					}
+				} else if ((info = this._parseJSRexExp(token, idx))) { // regexp
+					idx = info.idx;
+					expression += info.text;
+				} else { // other
+					expression += character;
+				}
+				break;
+
+			case "'":
+			case '"':
+				info = this._parseJSString(token, idx, character);
+				if (info) { // string
+					idx = info.idx;
+					expression += info.text;
+				} else {
+					expression += character;
+				}
+				break;
+
+			default:
+				expression += character;
+				break;
+		}
+
+		if (error) {
+			break;
+		}
+
+		// end of expression
+		if (paren.length === 0) {
+			break;
+		}
+	}
+
+	var ret;
+	if (error) {
+		ret = {
+			error: error
+		};
+	} else {
+		ret = {
+			idx: idx,
+			expression: expression
+		};
+	}
+
+	return ret;
+};
+
+
+/**
+ *
+ * @return {Object|false}
+ *          - idx:
+ *          - text:
+ *          or
+ *          - error:
+ *          or
+ *          false
+ *
+ */
+CSSOM.CSSValueExpression.prototype._parseJSComment = function(token, idx) {
+	var nextChar = token.charAt(idx + 1),
+			text;
+
+	if (nextChar === '/' || nextChar === '*') {
+		var startIdx = idx,
+				endIdx,
+				commentEndChar;
+
+		if (nextChar === '/') { // line comment
+			commentEndChar = '\n';
+		} else if (nextChar === '*') { // block comment
+			commentEndChar = '*/';
+		}
+
+		endIdx = token.indexOf(commentEndChar, startIdx + 1 + 1);
+		if (endIdx !== -1) {
+			endIdx = endIdx + commentEndChar.length - 1;
+			text = token.substring(idx, endIdx + 1);
+			return {
+				idx: endIdx,
+				text: text
+			};
+		} else {
+			var error = 'css expression error: unfinished comment in expression!';
+			return {
+				error: error
+			};
+		}
+	} else {
+		return false;
+	}
+};
+
+
+/**
+ *
+ * @return {Object|false}
+ *					- idx:
+ *					- text:
+ *					or 
+ *					false
+ *
+ */
+CSSOM.CSSValueExpression.prototype._parseJSString = function(token, idx, sep) {
+	var endIdx = this._findMatchedIdx(token, idx, sep),
+			text;
+
+	if (endIdx === -1) {
+		return false;
+	} else {
+		text = token.substring(idx, endIdx + sep.length);
+
+		return {
+			idx: endIdx,
+			text: text
+		};
+	}
+};
+
+
+/**
+ * parse regexp in css expression
+ *
+ * @return {Object|false}
+ *				- idx:
+ *				- regExp:
+ *				or 
+ *				false
+ */
+
+/*
+
+all legal RegExp
+ 
+/a/
+(/a/)
+[/a/]
+[12, /a/]
+
+!/a/
+
++/a/
+-/a/
+* /a/
+/ /a/
+%/a/
+
+===/a/
+!==/a/
+==/a/
+!=/a/
+>/a/
+>=/a/
+</a/
+<=/a/
+
+&/a/
+|/a/
+^/a/
+~/a/
+<</a/
+>>/a/
+>>>/a/
+
+&&/a/
+||/a/
+?/a/
+=/a/
+,/a/
+
+		delete /a/
+				in /a/
+instanceof /a/
+				new /a/
+		typeof /a/
+			void /a/
+
+*/
+CSSOM.CSSValueExpression.prototype._parseJSRexExp = function(token, idx) {
+	var before = token.substring(0, idx).replace(/\s+$/, ""),
+			legalRegx = [
+				/^$/,
+				/\($/,
+				/\[$/,
+				/\!$/,
+				/\+$/,
+				/\-$/,
+				/\*$/,
+				/\/\s+/,
+				/\%$/,
+				/\=$/,
+				/\>$/,
+				/<$/,
+				/\&$/,
+				/\|$/,
+				/\^$/,
+				/\~$/,
+				/\?$/,
+				/\,$/,
+				/delete$/,
+				/in$/,
+				/instanceof$/,
+				/new$/,
+				/typeof$/,
+				/void$/
+			];
+
+	var isLegal = legalRegx.some(function(reg) {
+		return reg.test(before);
+	});
+
+	if (!isLegal) {
+		return false;
+	} else {
+		var sep = '/';
+
+		// same logic as string
+		return this._parseJSString(token, idx, sep);
+	}
+};
+
+
+/**
+ *
+ * find next sep(same line) index in `token`
+ *
+ * @return {Number}
+ *
+ */
+CSSOM.CSSValueExpression.prototype._findMatchedIdx = function(token, idx, sep) {
+	var startIdx = idx,
+			endIdx;
+
+	var NOT_FOUND = -1;
+
+	while(true) {
+		endIdx = token.indexOf(sep, startIdx + 1);
+
+		if (endIdx === -1) { // not found
+			endIdx = NOT_FOUND;
+			break;
+		} else {
+			var text = token.substring(idx + 1, endIdx),
+					matched = text.match(/\\+$/);
+			if (!matched || matched[0] % 2 === 0) { // not escaped
+				break;
+			} else {
+				startIdx = endIdx;
+			}
+		}
+	}
+
+	// boundary must be in the same line(js sting or regexp)
+	var nextNewLineIdx = token.indexOf('\n', idx + 1);
+	if (nextNewLineIdx < endIdx) {
+		endIdx = NOT_FOUND;
+	}
+
+
+	return endIdx;
+};
+
+
+
+
+//.CommonJS
+exports.CSSValueExpression = CSSOM.CSSValueExpression;
+///CommonJS
Index: frontend/node_modules/cssom/lib/MatcherList.js
===================================================================
--- frontend/node_modules/cssom/lib/MatcherList.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/MatcherList.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,62 @@
+//.CommonJS
+var CSSOM = {};
+///CommonJS
+
+
+/**
+ * @constructor
+ * @see https://developer.mozilla.org/en/CSS/@-moz-document
+ */
+CSSOM.MatcherList = function MatcherList(){
+    this.length = 0;
+};
+
+CSSOM.MatcherList.prototype = {
+
+    constructor: CSSOM.MatcherList,
+
+    /**
+     * @return {string}
+     */
+    get matcherText() {
+        return Array.prototype.join.call(this, ", ");
+    },
+
+    /**
+     * @param {string} value
+     */
+    set matcherText(value) {
+        // just a temporary solution, actually it may be wrong by just split the value with ',', because a url can include ','.
+        var values = value.split(",");
+        var length = this.length = values.length;
+        for (var i=0; i<length; i++) {
+            this[i] = values[i].trim();
+        }
+    },
+
+    /**
+     * @param {string} matcher
+     */
+    appendMatcher: function(matcher) {
+        if (Array.prototype.indexOf.call(this, matcher) === -1) {
+            this[this.length] = matcher;
+            this.length++;
+        }
+    },
+
+    /**
+     * @param {string} matcher
+     */
+    deleteMatcher: function(matcher) {
+        var index = Array.prototype.indexOf.call(this, matcher);
+        if (index !== -1) {
+            Array.prototype.splice.call(this, index, 1);
+        }
+    }
+
+};
+
+
+//.CommonJS
+exports.MatcherList = CSSOM.MatcherList;
+///CommonJS
Index: frontend/node_modules/cssom/lib/MediaList.js
===================================================================
--- frontend/node_modules/cssom/lib/MediaList.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/MediaList.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,61 @@
+//.CommonJS
+var CSSOM = {};
+///CommonJS
+
+
+/**
+ * @constructor
+ * @see http://dev.w3.org/csswg/cssom/#the-medialist-interface
+ */
+CSSOM.MediaList = function MediaList(){
+	this.length = 0;
+};
+
+CSSOM.MediaList.prototype = {
+
+	constructor: CSSOM.MediaList,
+
+	/**
+	 * @return {string}
+	 */
+	get mediaText() {
+		return Array.prototype.join.call(this, ", ");
+	},
+
+	/**
+	 * @param {string} value
+	 */
+	set mediaText(value) {
+		var values = value.split(",");
+		var length = this.length = values.length;
+		for (var i=0; i<length; i++) {
+			this[i] = values[i].trim();
+		}
+	},
+
+	/**
+	 * @param {string} medium
+	 */
+	appendMedium: function(medium) {
+		if (Array.prototype.indexOf.call(this, medium) === -1) {
+			this[this.length] = medium;
+			this.length++;
+		}
+	},
+
+	/**
+	 * @param {string} medium
+	 */
+	deleteMedium: function(medium) {
+		var index = Array.prototype.indexOf.call(this, medium);
+		if (index !== -1) {
+			Array.prototype.splice.call(this, index, 1);
+		}
+	}
+
+};
+
+
+//.CommonJS
+exports.MediaList = CSSOM.MediaList;
+///CommonJS
Index: frontend/node_modules/cssom/lib/StyleSheet.js
===================================================================
--- frontend/node_modules/cssom/lib/StyleSheet.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/StyleSheet.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,17 @@
+//.CommonJS
+var CSSOM = {};
+///CommonJS
+
+
+/**
+ * @constructor
+ * @see http://dev.w3.org/csswg/cssom/#the-stylesheet-interface
+ */
+CSSOM.StyleSheet = function StyleSheet() {
+	this.parentStyleSheet = null;
+};
+
+
+//.CommonJS
+exports.StyleSheet = CSSOM.StyleSheet;
+///CommonJS
Index: frontend/node_modules/cssom/lib/clone.js
===================================================================
--- frontend/node_modules/cssom/lib/clone.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/clone.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,71 @@
+//.CommonJS
+var CSSOM = {
+	CSSStyleSheet: require("./CSSStyleSheet").CSSStyleSheet,
+	CSSStyleRule: require("./CSSStyleRule").CSSStyleRule,
+	CSSMediaRule: require("./CSSMediaRule").CSSMediaRule,
+	CSSSupportsRule: require("./CSSSupportsRule").CSSSupportsRule,
+	CSSStyleDeclaration: require("./CSSStyleDeclaration").CSSStyleDeclaration,
+	CSSKeyframeRule: require('./CSSKeyframeRule').CSSKeyframeRule,
+	CSSKeyframesRule: require('./CSSKeyframesRule').CSSKeyframesRule
+};
+///CommonJS
+
+
+/**
+ * Produces a deep copy of stylesheet — the instance variables of stylesheet are copied recursively.
+ * @param {CSSStyleSheet|CSSOM.CSSStyleSheet} stylesheet
+ * @nosideeffects
+ * @return {CSSOM.CSSStyleSheet}
+ */
+CSSOM.clone = function clone(stylesheet) {
+
+	var cloned = new CSSOM.CSSStyleSheet();
+
+	var rules = stylesheet.cssRules;
+	if (!rules) {
+		return cloned;
+	}
+
+	for (var i = 0, rulesLength = rules.length; i < rulesLength; i++) {
+		var rule = rules[i];
+		var ruleClone = cloned.cssRules[i] = new rule.constructor();
+
+		var style = rule.style;
+		if (style) {
+			var styleClone = ruleClone.style = new CSSOM.CSSStyleDeclaration();
+			for (var j = 0, styleLength = style.length; j < styleLength; j++) {
+				var name = styleClone[j] = style[j];
+				styleClone[name] = style[name];
+				styleClone._importants[name] = style.getPropertyPriority(name);
+			}
+			styleClone.length = style.length;
+		}
+
+		if (rule.hasOwnProperty('keyText')) {
+			ruleClone.keyText = rule.keyText;
+		}
+
+		if (rule.hasOwnProperty('selectorText')) {
+			ruleClone.selectorText = rule.selectorText;
+		}
+
+		if (rule.hasOwnProperty('mediaText')) {
+			ruleClone.mediaText = rule.mediaText;
+		}
+
+		if (rule.hasOwnProperty('conditionText')) {
+			ruleClone.conditionText = rule.conditionText;
+		}
+
+		if (rule.hasOwnProperty('cssRules')) {
+			ruleClone.cssRules = clone(rule).cssRules;
+		}
+	}
+
+	return cloned;
+
+};
+
+//.CommonJS
+exports.clone = CSSOM.clone;
+///CommonJS
Index: frontend/node_modules/cssom/lib/index.js
===================================================================
--- frontend/node_modules/cssom/lib/index.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/index.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,21 @@
+'use strict';
+
+exports.CSSStyleDeclaration = require('./CSSStyleDeclaration').CSSStyleDeclaration;
+exports.CSSRule = require('./CSSRule').CSSRule;
+exports.CSSStyleRule = require('./CSSStyleRule').CSSStyleRule;
+exports.MediaList = require('./MediaList').MediaList;
+exports.CSSMediaRule = require('./CSSMediaRule').CSSMediaRule;
+exports.CSSSupportsRule = require('./CSSSupportsRule').CSSSupportsRule;
+exports.CSSImportRule = require('./CSSImportRule').CSSImportRule;
+exports.CSSFontFaceRule = require('./CSSFontFaceRule').CSSFontFaceRule;
+exports.CSSHostRule = require('./CSSHostRule').CSSHostRule;
+exports.StyleSheet = require('./StyleSheet').StyleSheet;
+exports.CSSStyleSheet = require('./CSSStyleSheet').CSSStyleSheet;
+exports.CSSKeyframesRule = require('./CSSKeyframesRule').CSSKeyframesRule;
+exports.CSSKeyframeRule = require('./CSSKeyframeRule').CSSKeyframeRule;
+exports.MatcherList = require('./MatcherList').MatcherList;
+exports.CSSDocumentRule = require('./CSSDocumentRule').CSSDocumentRule;
+exports.CSSValue = require('./CSSValue').CSSValue;
+exports.CSSValueExpression = require('./CSSValueExpression').CSSValueExpression;
+exports.parse = require('./parse').parse;
+exports.clone = require('./clone').clone;
Index: frontend/node_modules/cssom/lib/parse.js
===================================================================
--- frontend/node_modules/cssom/lib/parse.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/lib/parse.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,463 @@
+//.CommonJS
+var CSSOM = {};
+///CommonJS
+
+
+/**
+ * @param {string} token
+ */
+CSSOM.parse = function parse(token) {
+
+	var i = 0;
+
+	/**
+		"before-selector" or
+		"selector" or
+		"atRule" or
+		"atBlock" or
+		"conditionBlock" or
+		"before-name" or
+		"name" or
+		"before-value" or
+		"value"
+	*/
+	var state = "before-selector";
+
+	var index;
+	var buffer = "";
+	var valueParenthesisDepth = 0;
+
+	var SIGNIFICANT_WHITESPACE = {
+		"selector": true,
+		"value": true,
+		"value-parenthesis": true,
+		"atRule": true,
+		"importRule-begin": true,
+		"importRule": true,
+		"atBlock": true,
+		"conditionBlock": true,
+		'documentRule-begin': true
+	};
+
+	var styleSheet = new CSSOM.CSSStyleSheet();
+
+	// @type CSSStyleSheet|CSSMediaRule|CSSSupportsRule|CSSFontFaceRule|CSSKeyframesRule|CSSDocumentRule
+	var currentScope = styleSheet;
+
+	// @type CSSMediaRule|CSSSupportsRule|CSSKeyframesRule|CSSDocumentRule
+	var parentRule;
+
+	var ancestorRules = [];
+	var hasAncestors = false;
+	var prevScope;
+
+	var name, priority="", styleRule, mediaRule, supportsRule, importRule, fontFaceRule, keyframesRule, documentRule, hostRule;
+
+	var atKeyframesRegExp = /@(-(?:\w+-)+)?keyframes/g;
+
+	var parseError = function(message) {
+		var lines = token.substring(0, i).split('\n');
+		var lineCount = lines.length;
+		var charCount = lines.pop().length + 1;
+		var error = new Error(message + ' (line ' + lineCount + ', char ' + charCount + ')');
+		error.line = lineCount;
+		/* jshint sub : true */
+		error['char'] = charCount;
+		error.styleSheet = styleSheet;
+		throw error;
+	};
+
+	for (var character; (character = token.charAt(i)); i++) {
+
+		switch (character) {
+
+		case " ":
+		case "\t":
+		case "\r":
+		case "\n":
+		case "\f":
+			if (SIGNIFICANT_WHITESPACE[state]) {
+				buffer += character;
+			}
+			break;
+
+		// String
+		case '"':
+			index = i + 1;
+			do {
+				index = token.indexOf('"', index) + 1;
+				if (!index) {
+					parseError('Unmatched "');
+				}
+			} while (token[index - 2] === '\\');
+			buffer += token.slice(i, index);
+			i = index - 1;
+			switch (state) {
+				case 'before-value':
+					state = 'value';
+					break;
+				case 'importRule-begin':
+					state = 'importRule';
+					break;
+			}
+			break;
+
+		case "'":
+			index = i + 1;
+			do {
+				index = token.indexOf("'", index) + 1;
+				if (!index) {
+					parseError("Unmatched '");
+				}
+			} while (token[index - 2] === '\\');
+			buffer += token.slice(i, index);
+			i = index - 1;
+			switch (state) {
+				case 'before-value':
+					state = 'value';
+					break;
+				case 'importRule-begin':
+					state = 'importRule';
+					break;
+			}
+			break;
+
+		// Comment
+		case "/":
+			if (token.charAt(i + 1) === "*") {
+				i += 2;
+				index = token.indexOf("*/", i);
+				if (index === -1) {
+					parseError("Missing */");
+				} else {
+					i = index + 1;
+				}
+			} else {
+				buffer += character;
+			}
+			if (state === "importRule-begin") {
+				buffer += " ";
+				state = "importRule";
+			}
+			break;
+
+		// At-rule
+		case "@":
+			if (token.indexOf("@-moz-document", i) === i) {
+				state = "documentRule-begin";
+				documentRule = new CSSOM.CSSDocumentRule();
+				documentRule.__starts = i;
+				i += "-moz-document".length;
+				buffer = "";
+				break;
+			} else if (token.indexOf("@media", i) === i) {
+				state = "atBlock";
+				mediaRule = new CSSOM.CSSMediaRule();
+				mediaRule.__starts = i;
+				i += "media".length;
+				buffer = "";
+				break;
+			} else if (token.indexOf("@supports", i) === i) {
+				state = "conditionBlock";
+				supportsRule = new CSSOM.CSSSupportsRule();
+				supportsRule.__starts = i;
+				i += "supports".length;
+				buffer = "";
+				break;
+			} else if (token.indexOf("@host", i) === i) {
+				state = "hostRule-begin";
+				i += "host".length;
+				hostRule = new CSSOM.CSSHostRule();
+				hostRule.__starts = i;
+				buffer = "";
+				break;
+			} else if (token.indexOf("@import", i) === i) {
+				state = "importRule-begin";
+				i += "import".length;
+				buffer += "@import";
+				break;
+			} else if (token.indexOf("@font-face", i) === i) {
+				state = "fontFaceRule-begin";
+				i += "font-face".length;
+				fontFaceRule = new CSSOM.CSSFontFaceRule();
+				fontFaceRule.__starts = i;
+				buffer = "";
+				break;
+			} else {
+				atKeyframesRegExp.lastIndex = i;
+				var matchKeyframes = atKeyframesRegExp.exec(token);
+				if (matchKeyframes && matchKeyframes.index === i) {
+					state = "keyframesRule-begin";
+					keyframesRule = new CSSOM.CSSKeyframesRule();
+					keyframesRule.__starts = i;
+					keyframesRule._vendorPrefix = matchKeyframes[1]; // Will come out as undefined if no prefix was found
+					i += matchKeyframes[0].length - 1;
+					buffer = "";
+					break;
+				} else if (state === "selector") {
+					state = "atRule";
+				}
+			}
+			buffer += character;
+			break;
+
+		case "{":
+			if (state === "selector" || state === "atRule") {
+				styleRule.selectorText = buffer.trim();
+				styleRule.style.__starts = i;
+				buffer = "";
+				state = "before-name";
+			} else if (state === "atBlock") {
+				mediaRule.media.mediaText = buffer.trim();
+
+				if (parentRule) {
+					ancestorRules.push(parentRule);
+				}
+
+				currentScope = parentRule = mediaRule;
+				mediaRule.parentStyleSheet = styleSheet;
+				buffer = "";
+				state = "before-selector";
+			} else if (state === "conditionBlock") {
+				supportsRule.conditionText = buffer.trim();
+
+				if (parentRule) {
+					ancestorRules.push(parentRule);
+				}
+
+				currentScope = parentRule = supportsRule;
+				supportsRule.parentStyleSheet = styleSheet;
+				buffer = "";
+				state = "before-selector";
+			} else if (state === "hostRule-begin") {
+				if (parentRule) {
+					ancestorRules.push(parentRule);
+				}
+
+				currentScope = parentRule = hostRule;
+				hostRule.parentStyleSheet = styleSheet;
+				buffer = "";
+				state = "before-selector";
+			} else if (state === "fontFaceRule-begin") {
+				if (parentRule) {
+					fontFaceRule.parentRule = parentRule;
+				}
+				fontFaceRule.parentStyleSheet = styleSheet;
+				styleRule = fontFaceRule;
+				buffer = "";
+				state = "before-name";
+			} else if (state === "keyframesRule-begin") {
+				keyframesRule.name = buffer.trim();
+				if (parentRule) {
+					ancestorRules.push(parentRule);
+					keyframesRule.parentRule = parentRule;
+				}
+				keyframesRule.parentStyleSheet = styleSheet;
+				currentScope = parentRule = keyframesRule;
+				buffer = "";
+				state = "keyframeRule-begin";
+			} else if (state === "keyframeRule-begin") {
+				styleRule = new CSSOM.CSSKeyframeRule();
+				styleRule.keyText = buffer.trim();
+				styleRule.__starts = i;
+				buffer = "";
+				state = "before-name";
+			} else if (state === "documentRule-begin") {
+				// FIXME: what if this '{' is in the url text of the match function?
+				documentRule.matcher.matcherText = buffer.trim();
+				if (parentRule) {
+					ancestorRules.push(parentRule);
+					documentRule.parentRule = parentRule;
+				}
+				currentScope = parentRule = documentRule;
+				documentRule.parentStyleSheet = styleSheet;
+				buffer = "";
+				state = "before-selector";
+			}
+			break;
+
+		case ":":
+			if (state === "name") {
+				name = buffer.trim();
+				buffer = "";
+				state = "before-value";
+			} else {
+				buffer += character;
+			}
+			break;
+
+		case "(":
+			if (state === 'value') {
+				// ie css expression mode
+				if (buffer.trim() === 'expression') {
+					var info = (new CSSOM.CSSValueExpression(token, i)).parse();
+
+					if (info.error) {
+						parseError(info.error);
+					} else {
+						buffer += info.expression;
+						i = info.idx;
+					}
+				} else {
+					state = 'value-parenthesis';
+					//always ensure this is reset to 1 on transition
+					//from value to value-parenthesis
+					valueParenthesisDepth = 1;
+					buffer += character;
+				}
+			} else if (state === 'value-parenthesis') {
+				valueParenthesisDepth++;
+				buffer += character;
+			} else {
+				buffer += character;
+			}
+			break;
+
+		case ")":
+			if (state === 'value-parenthesis') {
+				valueParenthesisDepth--;
+				if (valueParenthesisDepth === 0) state = 'value';
+			}
+			buffer += character;
+			break;
+
+		case "!":
+			if (state === "value" && token.indexOf("!important", i) === i) {
+				priority = "important";
+				i += "important".length;
+			} else {
+				buffer += character;
+			}
+			break;
+
+		case ";":
+			switch (state) {
+				case "value":
+					styleRule.style.setProperty(name, buffer.trim(), priority);
+					priority = "";
+					buffer = "";
+					state = "before-name";
+					break;
+				case "atRule":
+					buffer = "";
+					state = "before-selector";
+					break;
+				case "importRule":
+					importRule = new CSSOM.CSSImportRule();
+					importRule.parentStyleSheet = importRule.styleSheet.parentStyleSheet = styleSheet;
+					importRule.cssText = buffer + character;
+					styleSheet.cssRules.push(importRule);
+					buffer = "";
+					state = "before-selector";
+					break;
+				default:
+					buffer += character;
+					break;
+			}
+			break;
+
+		case "}":
+			switch (state) {
+				case "value":
+					styleRule.style.setProperty(name, buffer.trim(), priority);
+					priority = "";
+					/* falls through */
+				case "before-name":
+				case "name":
+					styleRule.__ends = i + 1;
+					if (parentRule) {
+						styleRule.parentRule = parentRule;
+					}
+					styleRule.parentStyleSheet = styleSheet;
+					currentScope.cssRules.push(styleRule);
+					buffer = "";
+					if (currentScope.constructor === CSSOM.CSSKeyframesRule) {
+						state = "keyframeRule-begin";
+					} else {
+						state = "before-selector";
+					}
+					break;
+				case "keyframeRule-begin":
+				case "before-selector":
+				case "selector":
+					// End of media/supports/document rule.
+					if (!parentRule) {
+						parseError("Unexpected }");
+					}
+
+					// Handle rules nested in @media or @supports
+					hasAncestors = ancestorRules.length > 0;
+
+					while (ancestorRules.length > 0) {
+						parentRule = ancestorRules.pop();
+
+						if (
+							parentRule.constructor.name === "CSSMediaRule"
+							|| parentRule.constructor.name === "CSSSupportsRule"
+						) {
+							prevScope = currentScope;
+							currentScope = parentRule;
+							currentScope.cssRules.push(prevScope);
+							break;
+						}
+
+						if (ancestorRules.length === 0) {
+							hasAncestors = false;
+						}
+					}
+					
+					if (!hasAncestors) {
+						currentScope.__ends = i + 1;
+						styleSheet.cssRules.push(currentScope);
+						currentScope = styleSheet;
+						parentRule = null;
+					}
+
+					buffer = "";
+					state = "before-selector";
+					break;
+			}
+			break;
+
+		default:
+			switch (state) {
+				case "before-selector":
+					state = "selector";
+					styleRule = new CSSOM.CSSStyleRule();
+					styleRule.__starts = i;
+					break;
+				case "before-name":
+					state = "name";
+					break;
+				case "before-value":
+					state = "value";
+					break;
+				case "importRule-begin":
+					state = "importRule";
+					break;
+			}
+			buffer += character;
+			break;
+		}
+	}
+
+	return styleSheet;
+};
+
+
+//.CommonJS
+exports.parse = CSSOM.parse;
+// The following modules cannot be included sooner due to the mutual dependency with parse.js
+CSSOM.CSSStyleSheet = require("./CSSStyleSheet").CSSStyleSheet;
+CSSOM.CSSStyleRule = require("./CSSStyleRule").CSSStyleRule;
+CSSOM.CSSImportRule = require("./CSSImportRule").CSSImportRule;
+CSSOM.CSSMediaRule = require("./CSSMediaRule").CSSMediaRule;
+CSSOM.CSSSupportsRule = require("./CSSSupportsRule").CSSSupportsRule;
+CSSOM.CSSFontFaceRule = require("./CSSFontFaceRule").CSSFontFaceRule;
+CSSOM.CSSHostRule = require("./CSSHostRule").CSSHostRule;
+CSSOM.CSSStyleDeclaration = require('./CSSStyleDeclaration').CSSStyleDeclaration;
+CSSOM.CSSKeyframeRule = require('./CSSKeyframeRule').CSSKeyframeRule;
+CSSOM.CSSKeyframesRule = require('./CSSKeyframesRule').CSSKeyframesRule;
+CSSOM.CSSValueExpression = require('./CSSValueExpression').CSSValueExpression;
+CSSOM.CSSDocumentRule = require('./CSSDocumentRule').CSSDocumentRule;
+///CommonJS
Index: frontend/node_modules/cssom/package.json
===================================================================
--- frontend/node_modules/cssom/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/cssom/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,18 @@
+{
+  "name": "cssom",
+  "description": "CSS Object Model implementation and CSS parser",
+  "keywords": [
+    "CSS",
+    "CSSOM",
+    "parser",
+    "styleSheet"
+  ],
+  "version": "0.4.4",
+  "author": "Nikita Vasilyev <me@elv1s.ru>",
+  "repository": "NV/CSSOM",
+  "files": [
+    "lib/"
+  ],
+  "main": "./lib/index.js",
+  "license": "MIT"
+}
