diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7176f4b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+**.DS_Store
diff --git a/CNAME b/CNAME
new file mode 100644
index 0000000..e6fbf56
--- /dev/null
+++ b/CNAME
@@ -0,0 +1 @@
+term.syui.ai
diff --git a/css/terminal-nyan.css b/css/terminal-nyan.css
new file mode 100644
index 0000000..c63f825
--- /dev/null
+++ b/css/terminal-nyan.css
@@ -0,0 +1,8 @@
+#window {
+    -moz-box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.75);
+    -webkit-box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.75);
+    background: #333;
+    height: 100%;
+    overflow: hidden;
+    width: 100%;
+}
diff --git a/css/terminal.css b/css/terminal.css
new file mode 100644
index 0000000..1b9950b
--- /dev/null
+++ b/css/terminal.css
@@ -0,0 +1,486 @@
+html {
+    -webkit-font-smoothing: antialiased;
+    -moz-font-smoothing: antialiased;
+    -ms-font-smoothing: antialiased;
+    -o-font-smoothing: antialiased;
+}
+body {
+    background-attachment: fixed;
+    -webkit-background-size: cover;
+    background-size: cover;
+    color: #444;
+    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+
+#window {
+    margin-left: auto;
+    margin-right: auto;
+    background: #333;
+    border-radius: 4px;
+    overflow: hidden;
+    width: 100%;
+				height: 100%;
+				margin:5px;
+}
+
+#topbar {
+    width: 100%;
+    height: 21px;
+    font-size: 16px;
+    font-family: "Myriad Pro", sans-serif;
+    text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
+}
+#topbar ul li {
+    float: left;
+    padding: 0 10px;
+    height: 21px;
+    line-height: 24px;
+}
+#topbar ul li:first-child {
+    font-size: 20px;
+    line-height: 26px;
+    margin-left: 5px;
+}
+#topbar ul li:nth-child(2) {
+    font-family: "Myriad-Semi", sans-serif;
+}
+#topbar ul li:active {
+    background-image: -webkit-gradient(linear, left bottom, left top, color-stop(1, #4a82ff), color-stop(0, #0052fc));
+    color: #fff;
+    text-shadow: none;
+}
+#toolbar {
+    width: 100%;
+    height: 25px;
+    background: #ccc;
+}
+#toolbar .top {
+    float: left;
+    width: 100%;
+    height: 23px;
+}
+#toolbar .bottom {
+    float: left;
+    width: 100%;
+    height: 30px;
+}
+#toolbar #lights {
+    float: left;
+    position: relative;
+    top: 6px;
+    left: 7px;
+}
+.light {
+    float: left;
+    width: 14px;
+    height: 14px;
+    border-radius: 14px;
+    -webkit-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.5), 0px 0px 3px #000 inset;
+    -moz-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.5), 0px 0px 3px #000 inset;
+    box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.5), 0px 0px 3px #000 inset;
+    overflow: hidden;
+}
+#lights:hover .glyph {
+    opacity: 1;
+    cursor: default;
+}
+.light .shine {
+    width: 4px;
+    height: 3px;
+    border-radius: 10px;
+    background: -moz-radial-gradient(center, ellipse cover, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
+    background-image: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, rgba(255, 255, 255, 1)), color-stop(100%, rgba(255, 255, 255, 0)));
+    background: -webkit-radial-gradient(center, ellipse cover, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
+    background: -o-radial-gradient(center, ellipse cover, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
+    background: -ms-radial-gradient(center, ellipse cover, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
+    background: radial-gradient(center, ellipse cover, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
+}
+.light .glow {
+    width: 14px;
+    height: 8px;
+    background-image: -webkit-gradient(radial, center bottom, 0, center center, 5, from(rgba(255, 255, 255, 0.75)), to(rgba(255, 255, 255, 0)));
+    background: 0px 0px -moz-radial-gradient(bottom, cover, rgba(255, 255, 255, 0.70) 0%, rgba(255, 255, 255, 0) 80%);
+}
+.red {
+    background: #f41b16;
+    background: -moz-linear-gradient(top, #f41b16 0%, #fc7471 100%);
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f41b16), color-stop(100%, #fc7471));
+    background: -webkit-linear-gradient(top, #f41b16 0%, #fc7471 100%);
+    background: -o-linear-gradient(top, #f41b16 0%, #fc7471 100%);
+    background: -ms-linear-gradient(top, #f41b16 0%, #fc7471 100%);
+    background: linear-gradient(top, #f41b16 0%, #fc7471 100%);
+}
+.red:active {
+    background: #972f2e;
+    background: -moz-linear-gradient(top, #972f2e 0%, #fc7471 100%);
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #972f2e), color-stop(100%, #fc7471));
+    background: -webkit-linear-gradient(top, #972f2e 0%, #fc7471 100%);
+    background: -o-linear-gradient(top, #972f2e 0%, #fc7471 100%);
+    background: -ms-linear-gradient(top, #972f2e 0%, #fc7471 100%);
+    background: linear-gradient(top, #972f2e 0%, #fc7471 100%);
+}
+.red .shine {
+    position: relative;
+    top: -21px;
+    left: 5px;
+}
+.red .glow {
+    position: relative;
+    top: -20px;
+}
+.red .glyph {
+    position: relative;
+    top: -5px;
+    left: 3px;
+    font-size: 14px;
+    font-weight: 400;
+    color: #9b3a36;
+    z-index: 50;
+    opacity: 0;
+}
+.yellow {
+    background: #f4a316;
+    background: -moz-linear-gradient(left, #f4a316 0%, #fcc371 100%);
+    background: -webkit-gradient(linear, left top, right top, color-stop(0%, #f4a316), color-stop(100%, #fcc371));
+    background: -webkit-linear-gradient(left, #f4a316 0%, #fcc371 100%);
+    background: -o-linear-gradient(left, #f4a316 0%, #fcc371 100%);
+    background: -ms-linear-gradient(left, #f4a316 0%, #fcc371 100%);
+    background: linear-gradient(left, #f4a316 0%, #fcc371 100%);
+    margin: 0px 7px;
+}
+.yellow:active {
+    background: #ae4f1e;
+    background: -moz-linear-gradient(top, #ae4f1e 0%, #fcc371 100%);
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ae4f1e), color-stop(100%, #fcc371));
+    background: -webkit-linear-gradient(top, #ae4f1e 0%, #fcc371 100%);
+    background: -o-linear-gradient(top, #ae4f1e 0%, #fcc371 100%);
+    background: -ms-linear-gradient(top, #ae4f1e 0%, #fcc371 100%);
+    background: linear-gradient(top, #ae4f1e 0%, #fcc371 100%);
+}
+.yellow .shine {
+    position: relative;
+    top: -21px;
+    left: 5px;
+}
+.yellow .glow {
+    position: relative;
+    top: -20px;
+}
+.yellow .glyph {
+    position: relative;
+    top: -5px;
+    left: 3px;
+    font-size: 24px;
+    color: #854322;
+    z-index: 50;
+    opacity: 0;
+    -webkit-transform: scaleY(1.5) scaleX(1.3);
+}
+.green {
+    background: #4cae2e;
+    background: -moz-linear-gradient(top, #4cae2e 0%, #dafc71 100%);
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #4cae2e), color-stop(100%, #dafc71));
+    background: -webkit-linear-gradient(top, #4cae2e 0%, #dafc71 100%);
+    background: -o-linear-gradient(top, #4cae2e 0%, #dafc71 100%);
+    background: -ms-linear-gradient(top, #4cae2e 0%, #dafc71 100%);
+    background: linear-gradient(top, #4cae2e 0%, #dafc71 100%);
+}
+.green:active {
+    background: #48752b;
+    background: -moz-linear-gradient(top, #48752b 0%, #dafc71 100%);
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #48752b), color-stop(100%, #dafc71));
+    background: -webkit-linear-gradient(top, #48752b 0%, #dafc71 100%);
+    background: -o-linear-gradient(top, #48752b 0%, #dafc71 100%);
+    background: -ms-linear-gradient(top, #48752b 0%, #dafc71 100%);
+    background: linear-gradient(top, #48752b 0%, #dafc71 100%);
+}
+.green .shine {
+    position: relative;
+    top: -20px;
+    left: 5px;
+}
+.green .glow {
+    position: relative;
+    top: -20px;
+}
+.green .glyph {
+    position: relative;
+    top: -5px;
+    left: 3px;
+    font-size: 14px;
+    font-weight: bold;
+    color: #25571d;
+    z-index: 50;
+    opacity: 0;
+}
+@-moz-document url-prefix() {
+    .red .glyph {
+        position: relative;
+        top: -5px;
+    }
+    .yellow .glyph {
+        top: -4px;
+        left: 3px;
+    }
+    .green .glyph {
+        position: relative;
+        top: -4px;
+    }
+}
+#title {
+    float: left;
+    position: relative;
+    top: 6px;
+    width: 40%;
+    left: 45%;
+    font-family: "Myriad Pro", sans-serif;
+    font-size: 16px;
+    line-height: 14px;
+    font-weight: bold;
+}
+.folder {
+    float: left;
+    margin-right: 5px;
+}
+.folder .tab {
+    width: 4px;
+    height: 2px;
+    background: #a4c5da;
+    border: 1px solid #728ea3;
+    border-bottom: none;
+    border-radius: 2px 2px 0px 0px;
+    -webkit-box-shadow: 0px -1px 0px #99b5c7 inset;
+    margin-left: 1px;
+    z-index: 5000;
+    margin-bottom: -1px;
+}
+.folder .body {
+    width: 14px;
+    height: 10px;
+    border: 1px solid #6e8ba1;
+    background: #b8cfe0;
+    background: -moz-linear-gradient(top, #b8cfe0 0%, #86adc8 100%);
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #b8cfe0), color-stop(100%, #86adc8));
+    background: -webkit-linear-gradient(top, #b8cfe0 0%, #86adc8 100%);
+    background: -o-linear-gradient(top, #b8cfe0 0%, #86adc8 100%);
+    background: -ms-linear-gradient(top, #b8cfe0 0%, #86adc8 100%);
+    background: linear-gradient(top, #b8cfe0 0%, #86adc8 100%);
+    z-index: -50;
+    -webkit-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25) inset, 0px 1px 0px rgba(0, 0, 0, 0.2);
+    -moz-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25) inset, 0px 1px 0px rgba(0, 0, 0, 0.2);
+}
+#nav {
+    margin: 1px 8px;
+    float: left;
+}
+#view {
+    margin: 2px 0 0 110px;
+    display: inline-block;
+}
+.control_box {
+    height: 20px;
+    border-radius: 3px;
+    border: 1px solid #555;
+    background-image: -webkit-gradient(linear, left bottom, left top, color-stop(1, #fefefe), color-stop(0, #b8b8b8));
+    box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
+}
+.control_box .control {
+    height: 20px;
+    border-right: 1px solid #2e2e2e;
+    float: left;
+    text-align: center;
+    width: 27px;
+}
+.control:last-child {
+    border-right: 0px solid !important;
+}
+.control:active {
+    background: #b0afb0;
+    -webkit-box-shadow: 0px 0px 4px #000 inset;
+}
+.active {
+    background: #707070 !important;
+    -webkit-box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.6) inset !important;
+}
+#body {
+    font-family: Andale Mono, monospace;
+    line-height: 1em;
+    font-size: 13px;
+    float: left;
+    width: 100%;
+    background: #002b36;
+    padding: 10px;
+    line-height: 1.5em;
+}
+#body p {
+    color: #63de00!important;
+}
+@keyframes blink {
+    0% {
+        background: rgba(99, 222, 0, 100);
+    }
+    100% {
+        background: rgba(99, 222, 0, 0);
+    }
+}
+@-webkit-keyframes blink {
+    0% {
+        background: rgba(99, 222, 0, 100);
+    }
+    100% {
+        background: rgba(99, 222, 0, 0);
+    }
+}
+@-moz-keyframes blink {
+    0% {
+        background: rgba(99, 222, 0, 100);
+    }
+    100% {
+        background: rgba(99, 222, 0, 0);
+    }
+}
+.cursor {
+    width: 10px;
+    margin-left: 0px;
+    color: #fff;
+}
+#body p::-webkit-selection {
+    background: #0b209e;
+}
+#body p::selection {
+    background: #0b209e;
+}
+#body p::-moz-selection {
+    background: #0b209e;
+}
+#body p {
+    margin-top: 5px;
+    margin-bottom: 5px;
+    font-size: 13px;
+}
+#content {
+    float: left;
+    margin-top: 1px;
+}
+#foot {
+    height: 23px;
+    width: 100%;
+    float: left;
+    background-image: -webkit-gradient(linear, left bottom, left top, color-stop(1, #cbcbcb), color-stop(0, #a7a7a7));
+    border-top: 1px solid #515151;
+    border-radius: 0 0 5px 5px;
+}
+#foot .handle {
+    width: 11px;
+    height: 11px;
+    float: right;
+    margin: 6px;
+    overflow: hidden;
+}
+.handle .grip {
+    -webkit-transform: rotate(45deg) scaley(3);
+    margin: 2px 0 0 2px;
+    color: #646464;
+    text-shadow: 1px 1px 0 #c6c6c6;
+    font-size: 14px;
+}
+.icon .frame {
+    width: 82px;
+    height: 82px;
+    border-radius: 5px;
+    border: 2px solid transparent;
+}
+.icon .name {
+    color: #000;
+    padding-top: 3px;
+    border-radius: 15px;
+    width: 55px;
+    margin: 5px 0 0 15px;
+}
+.icon .folder {
+    margin: 15px 0 0 6px;
+}
+#icon-github {
+    text-align: -999px;
+    font-size: 1px;
+    display: block;
+    width: 156px;
+    height: 133px;
+    background-image: url(../img/sprite.png);
+    background-position: 0 133px;
+}
+#icon-github:hover {
+    background-position: 0 0px;
+}
+#icon-rubygems {
+    text-align: -999px;
+    font-size: 1px;
+    display: block;
+    width: 156px;
+    height: 133px;
+    background-image: url(../img/sprite.png);
+    background-position: 158px 133px;
+}
+#icon-rubygems:hover {
+    background-position: 158px 0px;
+}
+.source-urls {
+    margin-top: 40px;
+    margin-bottom: 40px;
+}
+.no-margin-bot {
+    color: #337AB7;
+}
+span {
+    font-size: 15px;
+}
+#particles-js {
+    position: absolute;
+    width: 98%;
+}
+#particles-js-no {
+    position: absolute;
+    width: 98%;
+}
+
+#icon-github:hover,
+i.icon.ion-close-circled:hover,
+i.icon.ion-minus-circled:hover,
+i.icon.ion-plus-circled:hover {
+    color: rgba(0, 0, 0, .5);
+}
+i.icon.ion-close-circled {
+    color: rgba(212, 42, 38, 0.83);
+    text-shadow: 0 0 1px rgba(187, 187, 187, 0.56);
+    padding-top: 3px;
+}
+i.icon.ion-minus-circled {
+    color: rgb(160, 165, 34);
+    text-shadow: 0 0 1px rgba(187, 187, 187, 0.56);
+    padding-top: 3px;
+}
+i.icon.ion-plus-circled {
+    color: rgb(82, 183, 51);
+    text-shadow: 0 0 1px rgba(187, 187, 187, 0.56);
+    padding-top: 3px;
+}
+.icon {
+    margin: 7px;
+    float: left;
+    font-size: 20px;
+}
+#title-left {
+    position: relative;
+    top: -8px;
+    font-family: "Myriad Pro", sans-serif;
+    font-size: 14px;
+    left: 49%;
+}
+#terminal-origin {
+    font-family: monospace;
+}
+@media all and (-webkit-min-device-pixel-ratio: 0) and (min-resolution: .001dpcm) {
+    #title-left {
+        top: -13px;
+    }
+}
diff --git a/css/terminal.mobile.css b/css/terminal.mobile.css
new file mode 100644
index 0000000..fbf2afc
--- /dev/null
+++ b/css/terminal.mobile.css
@@ -0,0 +1,22 @@
+@media screen and (max-width:1000px){i.icon.ion-minus-circled{display:none}
+#window{width:100%;}
+}
+@media screen and (max-width:800px){body{padding-top:0px;}
+#title-left{left:50%;}
+#window{width:100%;}
+.container{padding:0px;}
+/*article{padding:10px 20px;}*/
+i.icon.ion-minus-circled{display:none}
+}
+@media screen and (max-width:800px){#title-left{left:48%;}
+}
+@media screen and (max-width:500px){#title-left{left:40%;}
+}
+@media screen and (max-width:400px){body{padding-top:0px;width:auto;}
+#title-left{left:50%;}
+/*article{padding:10px 10px;}*/
+#particles-js{width:auto;}
+#particles-js-no{width:auto;}
+i.icon.ion-minus-circled{display:none}
+i.icon.ion-plus-circled{display:none}
+}
diff --git a/icon/ai.png b/icon/ai.png
new file mode 100644
index 0000000..d21dabe
Binary files /dev/null and b/icon/ai.png differ
diff --git a/icon/ai.svg b/icon/ai.svg
new file mode 100644
index 0000000..8926e2a
--- /dev/null
+++ b/icon/ai.svg
@@ -0,0 +1,1882 @@
+
+
diff --git a/icon/apple-touch-icon.png b/icon/apple-touch-icon.png
new file mode 100644
index 0000000..d21dabe
Binary files /dev/null and b/icon/apple-touch-icon.png differ
diff --git a/icon/avatar.png b/icon/avatar.png
new file mode 100644
index 0000000..f091ef1
Binary files /dev/null and b/icon/avatar.png differ
diff --git a/icon/term.png b/icon/term.png
new file mode 100644
index 0000000..dcff3bc
Binary files /dev/null and b/icon/term.png differ
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..5e0a606
--- /dev/null
+++ b/index.html
@@ -0,0 +1,25 @@
+
+
+	
+		ai/term
+		
+		
+		
+		
+		
+		
+		
+		
+		
+		
+		
+		
+		
+		
+		
+		
+		
+		
+		
+		
+	
diff --git a/js/bundle.js b/js/bundle.js
new file mode 100644
index 0000000..21c283e
--- /dev/null
+++ b/js/bundle.js
@@ -0,0 +1,5241 @@
+/******/ (function(modules) { // webpackBootstrap
+/******/ 	var parentHotUpdateCallback = this["webpackHotUpdate"];
+/******/ 	this["webpackHotUpdate"] = 
+/******/ 	function webpackHotUpdateCallback(chunkId, moreModules) { // eslint-disable-line no-unused-vars
+/******/ 		hotAddUpdateChunk(chunkId, moreModules);
+/******/ 		if(parentHotUpdateCallback) parentHotUpdateCallback(chunkId, moreModules);
+/******/ 	}
+/******/ 	
+/******/ 	function hotDownloadUpdateChunk(chunkId) { // eslint-disable-line no-unused-vars
+/******/ 		var head = document.getElementsByTagName("head")[0];
+/******/ 		var script = document.createElement("script");
+/******/ 		script.type = "text/javascript";
+/******/ 		script.charset = "utf-8";
+/******/ 		script.src = __webpack_require__.p + "" + chunkId + "." + hotCurrentHash + ".hot-update.js";
+/******/ 		head.appendChild(script);
+/******/ 	}
+/******/ 	
+/******/ 	function hotDownloadManifest(callback) { // eslint-disable-line no-unused-vars
+/******/ 		if(typeof XMLHttpRequest === "undefined")
+/******/ 			return callback(new Error("No browser support"));
+/******/ 		try {
+/******/ 			var request = new XMLHttpRequest();
+/******/ 			var requestPath = __webpack_require__.p + "" + hotCurrentHash + ".hot-update.json";
+/******/ 			request.open("GET", requestPath, true);
+/******/ 			request.timeout = 10000;
+/******/ 			request.send(null);
+/******/ 		} catch(err) {
+/******/ 			return callback(err);
+/******/ 		}
+/******/ 		request.onreadystatechange = function() {
+/******/ 			if(request.readyState !== 4) return;
+/******/ 			if(request.status === 0) {
+/******/ 				// timeout
+/******/ 				callback(new Error("Manifest request to " + requestPath + " timed out."));
+/******/ 			} else if(request.status === 404) {
+/******/ 				// no update available
+/******/ 				callback();
+/******/ 			} else if(request.status !== 200 && request.status !== 304) {
+/******/ 				// other failure
+/******/ 				callback(new Error("Manifest request to " + requestPath + " failed."));
+/******/ 			} else {
+/******/ 				// success
+/******/ 				try {
+/******/ 					var update = JSON.parse(request.responseText);
+/******/ 				} catch(e) {
+/******/ 					callback(e);
+/******/ 					return;
+/******/ 				}
+/******/ 				callback(null, update);
+/******/ 			}
+/******/ 		};
+/******/ 	}
+
+/******/ 	
+/******/ 	
+/******/ 	// Copied from https://github.com/facebook/react/blob/bef45b0/src/shared/utils/canDefineProperty.js
+/******/ 	var canDefineProperty = false;
+/******/ 	try {
+/******/ 		Object.defineProperty({}, "x", {
+/******/ 			get: function() {}
+/******/ 		});
+/******/ 		canDefineProperty = true;
+/******/ 	} catch(x) {
+/******/ 		// IE will fail on defineProperty
+/******/ 	}
+/******/ 	
+/******/ 	var hotApplyOnUpdate = true;
+/******/ 	var hotCurrentHash = "df5ff963eab1d8f408b8"; // eslint-disable-line no-unused-vars
+/******/ 	var hotCurrentModuleData = {};
+/******/ 	var hotCurrentParents = []; // eslint-disable-line no-unused-vars
+/******/ 	
+/******/ 	function hotCreateRequire(moduleId) { // eslint-disable-line no-unused-vars
+/******/ 		var me = installedModules[moduleId];
+/******/ 		if(!me) return __webpack_require__;
+/******/ 		var fn = function(request) {
+/******/ 			if(me.hot.active) {
+/******/ 				if(installedModules[request]) {
+/******/ 					if(installedModules[request].parents.indexOf(moduleId) < 0)
+/******/ 						installedModules[request].parents.push(moduleId);
+/******/ 					if(me.children.indexOf(request) < 0)
+/******/ 						me.children.push(request);
+/******/ 				} else hotCurrentParents = [moduleId];
+/******/ 			} else {
+/******/ 				console.warn("[HMR] unexpected require(" + request + ") from disposed module " + moduleId);
+/******/ 				hotCurrentParents = [];
+/******/ 			}
+/******/ 			return __webpack_require__(request);
+/******/ 		};
+/******/ 		for(var name in __webpack_require__) {
+/******/ 			if(Object.prototype.hasOwnProperty.call(__webpack_require__, name)) {
+/******/ 				if(canDefineProperty) {
+/******/ 					Object.defineProperty(fn, name, (function(name) {
+/******/ 						return {
+/******/ 							configurable: true,
+/******/ 							enumerable: true,
+/******/ 							get: function() {
+/******/ 								return __webpack_require__[name];
+/******/ 							},
+/******/ 							set: function(value) {
+/******/ 								__webpack_require__[name] = value;
+/******/ 							}
+/******/ 						};
+/******/ 					}(name)));
+/******/ 				} else {
+/******/ 					fn[name] = __webpack_require__[name];
+/******/ 				}
+/******/ 			}
+/******/ 		}
+/******/ 	
+/******/ 		function ensure(chunkId, callback) {
+/******/ 			if(hotStatus === "ready")
+/******/ 				hotSetStatus("prepare");
+/******/ 			hotChunksLoading++;
+/******/ 			__webpack_require__.e(chunkId, function() {
+/******/ 				try {
+/******/ 					callback.call(null, fn);
+/******/ 				} finally {
+/******/ 					finishChunkLoading();
+/******/ 				}
+/******/ 	
+/******/ 				function finishChunkLoading() {
+/******/ 					hotChunksLoading--;
+/******/ 					if(hotStatus === "prepare") {
+/******/ 						if(!hotWaitingFilesMap[chunkId]) {
+/******/ 							hotEnsureUpdateChunk(chunkId);
+/******/ 						}
+/******/ 						if(hotChunksLoading === 0 && hotWaitingFiles === 0) {
+/******/ 							hotUpdateDownloaded();
+/******/ 						}
+/******/ 					}
+/******/ 				}
+/******/ 			});
+/******/ 		}
+/******/ 		if(canDefineProperty) {
+/******/ 			Object.defineProperty(fn, "e", {
+/******/ 				enumerable: true,
+/******/ 				value: ensure
+/******/ 			});
+/******/ 		} else {
+/******/ 			fn.e = ensure;
+/******/ 		}
+/******/ 		return fn;
+/******/ 	}
+/******/ 	
+/******/ 	function hotCreateModule(moduleId) { // eslint-disable-line no-unused-vars
+/******/ 		var hot = {
+/******/ 			// private stuff
+/******/ 			_acceptedDependencies: {},
+/******/ 			_declinedDependencies: {},
+/******/ 			_selfAccepted: false,
+/******/ 			_selfDeclined: false,
+/******/ 			_disposeHandlers: [],
+/******/ 	
+/******/ 			// Module API
+/******/ 			active: true,
+/******/ 			accept: function(dep, callback) {
+/******/ 				if(typeof dep === "undefined")
+/******/ 					hot._selfAccepted = true;
+/******/ 				else if(typeof dep === "function")
+/******/ 					hot._selfAccepted = dep;
+/******/ 				else if(typeof dep === "object")
+/******/ 					for(var i = 0; i < dep.length; i++)
+/******/ 						hot._acceptedDependencies[dep[i]] = callback;
+/******/ 				else
+/******/ 					hot._acceptedDependencies[dep] = callback;
+/******/ 			},
+/******/ 			decline: function(dep) {
+/******/ 				if(typeof dep === "undefined")
+/******/ 					hot._selfDeclined = true;
+/******/ 				else if(typeof dep === "number")
+/******/ 					hot._declinedDependencies[dep] = true;
+/******/ 				else
+/******/ 					for(var i = 0; i < dep.length; i++)
+/******/ 						hot._declinedDependencies[dep[i]] = true;
+/******/ 			},
+/******/ 			dispose: function(callback) {
+/******/ 				hot._disposeHandlers.push(callback);
+/******/ 			},
+/******/ 			addDisposeHandler: function(callback) {
+/******/ 				hot._disposeHandlers.push(callback);
+/******/ 			},
+/******/ 			removeDisposeHandler: function(callback) {
+/******/ 				var idx = hot._disposeHandlers.indexOf(callback);
+/******/ 				if(idx >= 0) hot._disposeHandlers.splice(idx, 1);
+/******/ 			},
+/******/ 	
+/******/ 			// Management API
+/******/ 			check: hotCheck,
+/******/ 			apply: hotApply,
+/******/ 			status: function(l) {
+/******/ 				if(!l) return hotStatus;
+/******/ 				hotStatusHandlers.push(l);
+/******/ 			},
+/******/ 			addStatusHandler: function(l) {
+/******/ 				hotStatusHandlers.push(l);
+/******/ 			},
+/******/ 			removeStatusHandler: function(l) {
+/******/ 				var idx = hotStatusHandlers.indexOf(l);
+/******/ 				if(idx >= 0) hotStatusHandlers.splice(idx, 1);
+/******/ 			},
+/******/ 	
+/******/ 			//inherit from previous dispose call
+/******/ 			data: hotCurrentModuleData[moduleId]
+/******/ 		};
+/******/ 		return hot;
+/******/ 	}
+/******/ 	
+/******/ 	var hotStatusHandlers = [];
+/******/ 	var hotStatus = "idle";
+/******/ 	
+/******/ 	function hotSetStatus(newStatus) {
+/******/ 		hotStatus = newStatus;
+/******/ 		for(var i = 0; i < hotStatusHandlers.length; i++)
+/******/ 			hotStatusHandlers[i].call(null, newStatus);
+/******/ 	}
+/******/ 	
+/******/ 	// while downloading
+/******/ 	var hotWaitingFiles = 0;
+/******/ 	var hotChunksLoading = 0;
+/******/ 	var hotWaitingFilesMap = {};
+/******/ 	var hotRequestedFilesMap = {};
+/******/ 	var hotAvailibleFilesMap = {};
+/******/ 	var hotCallback;
+/******/ 	
+/******/ 	// The update info
+/******/ 	var hotUpdate, hotUpdateNewHash;
+/******/ 	
+/******/ 	function toModuleId(id) {
+/******/ 		var isNumber = (+id) + "" === id;
+/******/ 		return isNumber ? +id : id;
+/******/ 	}
+/******/ 	
+/******/ 	function hotCheck(apply, callback) {
+/******/ 		if(hotStatus !== "idle") throw new Error("check() is only allowed in idle status");
+/******/ 		if(typeof apply === "function") {
+/******/ 			hotApplyOnUpdate = false;
+/******/ 			callback = apply;
+/******/ 		} else {
+/******/ 			hotApplyOnUpdate = apply;
+/******/ 			callback = callback || function(err) {
+/******/ 				if(err) throw err;
+/******/ 			};
+/******/ 		}
+/******/ 		hotSetStatus("check");
+/******/ 		hotDownloadManifest(function(err, update) {
+/******/ 			if(err) return callback(err);
+/******/ 			if(!update) {
+/******/ 				hotSetStatus("idle");
+/******/ 				callback(null, null);
+/******/ 				return;
+/******/ 			}
+/******/ 	
+/******/ 			hotRequestedFilesMap = {};
+/******/ 			hotAvailibleFilesMap = {};
+/******/ 			hotWaitingFilesMap = {};
+/******/ 			for(var i = 0; i < update.c.length; i++)
+/******/ 				hotAvailibleFilesMap[update.c[i]] = true;
+/******/ 			hotUpdateNewHash = update.h;
+/******/ 	
+/******/ 			hotSetStatus("prepare");
+/******/ 			hotCallback = callback;
+/******/ 			hotUpdate = {};
+/******/ 			var chunkId = 0;
+/******/ 			{ // eslint-disable-line no-lone-blocks
+/******/ 				/*globals chunkId */
+/******/ 				hotEnsureUpdateChunk(chunkId);
+/******/ 			}
+/******/ 			if(hotStatus === "prepare" && hotChunksLoading === 0 && hotWaitingFiles === 0) {
+/******/ 				hotUpdateDownloaded();
+/******/ 			}
+/******/ 		});
+/******/ 	}
+/******/ 	
+/******/ 	function hotAddUpdateChunk(chunkId, moreModules) { // eslint-disable-line no-unused-vars
+/******/ 		if(!hotAvailibleFilesMap[chunkId] || !hotRequestedFilesMap[chunkId])
+/******/ 			return;
+/******/ 		hotRequestedFilesMap[chunkId] = false;
+/******/ 		for(var moduleId in moreModules) {
+/******/ 			if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
+/******/ 				hotUpdate[moduleId] = moreModules[moduleId];
+/******/ 			}
+/******/ 		}
+/******/ 		if(--hotWaitingFiles === 0 && hotChunksLoading === 0) {
+/******/ 			hotUpdateDownloaded();
+/******/ 		}
+/******/ 	}
+/******/ 	
+/******/ 	function hotEnsureUpdateChunk(chunkId) {
+/******/ 		if(!hotAvailibleFilesMap[chunkId]) {
+/******/ 			hotWaitingFilesMap[chunkId] = true;
+/******/ 		} else {
+/******/ 			hotRequestedFilesMap[chunkId] = true;
+/******/ 			hotWaitingFiles++;
+/******/ 			hotDownloadUpdateChunk(chunkId);
+/******/ 		}
+/******/ 	}
+/******/ 	
+/******/ 	function hotUpdateDownloaded() {
+/******/ 		hotSetStatus("ready");
+/******/ 		var callback = hotCallback;
+/******/ 		hotCallback = null;
+/******/ 		if(!callback) return;
+/******/ 		if(hotApplyOnUpdate) {
+/******/ 			hotApply(hotApplyOnUpdate, callback);
+/******/ 		} else {
+/******/ 			var outdatedModules = [];
+/******/ 			for(var id in hotUpdate) {
+/******/ 				if(Object.prototype.hasOwnProperty.call(hotUpdate, id)) {
+/******/ 					outdatedModules.push(toModuleId(id));
+/******/ 				}
+/******/ 			}
+/******/ 			callback(null, outdatedModules);
+/******/ 		}
+/******/ 	}
+/******/ 	
+/******/ 	function hotApply(options, callback) {
+/******/ 		if(hotStatus !== "ready") throw new Error("apply() is only allowed in ready status");
+/******/ 		if(typeof options === "function") {
+/******/ 			callback = options;
+/******/ 			options = {};
+/******/ 		} else if(options && typeof options === "object") {
+/******/ 			callback = callback || function(err) {
+/******/ 				if(err) throw err;
+/******/ 			};
+/******/ 		} else {
+/******/ 			options = {};
+/******/ 			callback = callback || function(err) {
+/******/ 				if(err) throw err;
+/******/ 			};
+/******/ 		}
+/******/ 	
+/******/ 		function getAffectedStuff(module) {
+/******/ 			var outdatedModules = [module];
+/******/ 			var outdatedDependencies = {};
+/******/ 	
+/******/ 			var queue = outdatedModules.slice();
+/******/ 			while(queue.length > 0) {
+/******/ 				var moduleId = queue.pop();
+/******/ 				var module = installedModules[moduleId];
+/******/ 				if(!module || module.hot._selfAccepted)
+/******/ 					continue;
+/******/ 				if(module.hot._selfDeclined) {
+/******/ 					return new Error("Aborted because of self decline: " + moduleId);
+/******/ 				}
+/******/ 				if(moduleId === 0) {
+/******/ 					return;
+/******/ 				}
+/******/ 				for(var i = 0; i < module.parents.length; i++) {
+/******/ 					var parentId = module.parents[i];
+/******/ 					var parent = installedModules[parentId];
+/******/ 					if(parent.hot._declinedDependencies[moduleId]) {
+/******/ 						return new Error("Aborted because of declined dependency: " + moduleId + " in " + parentId);
+/******/ 					}
+/******/ 					if(outdatedModules.indexOf(parentId) >= 0) continue;
+/******/ 					if(parent.hot._acceptedDependencies[moduleId]) {
+/******/ 						if(!outdatedDependencies[parentId])
+/******/ 							outdatedDependencies[parentId] = [];
+/******/ 						addAllToSet(outdatedDependencies[parentId], [moduleId]);
+/******/ 						continue;
+/******/ 					}
+/******/ 					delete outdatedDependencies[parentId];
+/******/ 					outdatedModules.push(parentId);
+/******/ 					queue.push(parentId);
+/******/ 				}
+/******/ 			}
+/******/ 	
+/******/ 			return [outdatedModules, outdatedDependencies];
+/******/ 		}
+/******/ 	
+/******/ 		function addAllToSet(a, b) {
+/******/ 			for(var i = 0; i < b.length; i++) {
+/******/ 				var item = b[i];
+/******/ 				if(a.indexOf(item) < 0)
+/******/ 					a.push(item);
+/******/ 			}
+/******/ 		}
+/******/ 	
+/******/ 		// at begin all updates modules are outdated
+/******/ 		// the "outdated" status can propagate to parents if they don't accept the children
+/******/ 		var outdatedDependencies = {};
+/******/ 		var outdatedModules = [];
+/******/ 		var appliedUpdate = {};
+/******/ 		for(var id in hotUpdate) {
+/******/ 			if(Object.prototype.hasOwnProperty.call(hotUpdate, id)) {
+/******/ 				var moduleId = toModuleId(id);
+/******/ 				var result = getAffectedStuff(moduleId);
+/******/ 				if(!result) {
+/******/ 					if(options.ignoreUnaccepted)
+/******/ 						continue;
+/******/ 					hotSetStatus("abort");
+/******/ 					return callback(new Error("Aborted because " + moduleId + " is not accepted"));
+/******/ 				}
+/******/ 				if(result instanceof Error) {
+/******/ 					hotSetStatus("abort");
+/******/ 					return callback(result);
+/******/ 				}
+/******/ 				appliedUpdate[moduleId] = hotUpdate[moduleId];
+/******/ 				addAllToSet(outdatedModules, result[0]);
+/******/ 				for(var moduleId in result[1]) {
+/******/ 					if(Object.prototype.hasOwnProperty.call(result[1], moduleId)) {
+/******/ 						if(!outdatedDependencies[moduleId])
+/******/ 							outdatedDependencies[moduleId] = [];
+/******/ 						addAllToSet(outdatedDependencies[moduleId], result[1][moduleId]);
+/******/ 					}
+/******/ 				}
+/******/ 			}
+/******/ 		}
+/******/ 	
+/******/ 		// Store self accepted outdated modules to require them later by the module system
+/******/ 		var outdatedSelfAcceptedModules = [];
+/******/ 		for(var i = 0; i < outdatedModules.length; i++) {
+/******/ 			var moduleId = outdatedModules[i];
+/******/ 			if(installedModules[moduleId] && installedModules[moduleId].hot._selfAccepted)
+/******/ 				outdatedSelfAcceptedModules.push({
+/******/ 					module: moduleId,
+/******/ 					errorHandler: installedModules[moduleId].hot._selfAccepted
+/******/ 				});
+/******/ 		}
+/******/ 	
+/******/ 		// Now in "dispose" phase
+/******/ 		hotSetStatus("dispose");
+/******/ 		var queue = outdatedModules.slice();
+/******/ 		while(queue.length > 0) {
+/******/ 			var moduleId = queue.pop();
+/******/ 			var module = installedModules[moduleId];
+/******/ 			if(!module) continue;
+/******/ 	
+/******/ 			var data = {};
+/******/ 	
+/******/ 			// Call dispose handlers
+/******/ 			var disposeHandlers = module.hot._disposeHandlers;
+/******/ 			for(var j = 0; j < disposeHandlers.length; j++) {
+/******/ 				var cb = disposeHandlers[j];
+/******/ 				cb(data);
+/******/ 			}
+/******/ 			hotCurrentModuleData[moduleId] = data;
+/******/ 	
+/******/ 			// disable module (this disables requires from this module)
+/******/ 			module.hot.active = false;
+/******/ 	
+/******/ 			// remove module from cache
+/******/ 			delete installedModules[moduleId];
+/******/ 	
+/******/ 			// remove "parents" references from all children
+/******/ 			for(var j = 0; j < module.children.length; j++) {
+/******/ 				var child = installedModules[module.children[j]];
+/******/ 				if(!child) continue;
+/******/ 				var idx = child.parents.indexOf(moduleId);
+/******/ 				if(idx >= 0) {
+/******/ 					child.parents.splice(idx, 1);
+/******/ 				}
+/******/ 			}
+/******/ 		}
+/******/ 	
+/******/ 		// remove outdated dependency from module children
+/******/ 		for(var moduleId in outdatedDependencies) {
+/******/ 			if(Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId)) {
+/******/ 				var module = installedModules[moduleId];
+/******/ 				var moduleOutdatedDependencies = outdatedDependencies[moduleId];
+/******/ 				for(var j = 0; j < moduleOutdatedDependencies.length; j++) {
+/******/ 					var dependency = moduleOutdatedDependencies[j];
+/******/ 					var idx = module.children.indexOf(dependency);
+/******/ 					if(idx >= 0) module.children.splice(idx, 1);
+/******/ 				}
+/******/ 			}
+/******/ 		}
+/******/ 	
+/******/ 		// Not in "apply" phase
+/******/ 		hotSetStatus("apply");
+/******/ 	
+/******/ 		hotCurrentHash = hotUpdateNewHash;
+/******/ 	
+/******/ 		// insert new code
+/******/ 		for(var moduleId in appliedUpdate) {
+/******/ 			if(Object.prototype.hasOwnProperty.call(appliedUpdate, moduleId)) {
+/******/ 				modules[moduleId] = appliedUpdate[moduleId];
+/******/ 			}
+/******/ 		}
+/******/ 	
+/******/ 		// call accept handlers
+/******/ 		var error = null;
+/******/ 		for(var moduleId in outdatedDependencies) {
+/******/ 			if(Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId)) {
+/******/ 				var module = installedModules[moduleId];
+/******/ 				var moduleOutdatedDependencies = outdatedDependencies[moduleId];
+/******/ 				var callbacks = [];
+/******/ 				for(var i = 0; i < moduleOutdatedDependencies.length; i++) {
+/******/ 					var dependency = moduleOutdatedDependencies[i];
+/******/ 					var cb = module.hot._acceptedDependencies[dependency];
+/******/ 					if(callbacks.indexOf(cb) >= 0) continue;
+/******/ 					callbacks.push(cb);
+/******/ 				}
+/******/ 				for(var i = 0; i < callbacks.length; i++) {
+/******/ 					var cb = callbacks[i];
+/******/ 					try {
+/******/ 						cb(outdatedDependencies);
+/******/ 					} catch(err) {
+/******/ 						if(!error)
+/******/ 							error = err;
+/******/ 					}
+/******/ 				}
+/******/ 			}
+/******/ 		}
+/******/ 	
+/******/ 		// Load self accepted modules
+/******/ 		for(var i = 0; i < outdatedSelfAcceptedModules.length; i++) {
+/******/ 			var item = outdatedSelfAcceptedModules[i];
+/******/ 			var moduleId = item.module;
+/******/ 			hotCurrentParents = [moduleId];
+/******/ 			try {
+/******/ 				__webpack_require__(moduleId);
+/******/ 			} catch(err) {
+/******/ 				if(typeof item.errorHandler === "function") {
+/******/ 					try {
+/******/ 						item.errorHandler(err);
+/******/ 					} catch(err) {
+/******/ 						if(!error)
+/******/ 							error = err;
+/******/ 					}
+/******/ 				} else if(!error)
+/******/ 					error = err;
+/******/ 			}
+/******/ 		}
+/******/ 	
+/******/ 		// handle errors in accept handlers and self accepted module load
+/******/ 		if(error) {
+/******/ 			hotSetStatus("fail");
+/******/ 			return callback(error);
+/******/ 		}
+/******/ 	
+/******/ 		hotSetStatus("idle");
+/******/ 		callback(null, outdatedModules);
+/******/ 	}
+
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId])
+/******/ 			return installedModules[moduleId].exports;
+
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			exports: {},
+/******/ 			id: moduleId,
+/******/ 			loaded: false,
+/******/ 			hot: hotCreateModule(moduleId),
+/******/ 			parents: hotCurrentParents,
+/******/ 			children: []
+/******/ 		};
+
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
+
+/******/ 		// Flag the module as loaded
+/******/ 		module.loaded = true;
+
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+
+
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+
+/******/ 	// __webpack_hash__
+/******/ 	__webpack_require__.h = function() { return hotCurrentHash; };
+
+/******/ 	// Load entry module and return exports
+/******/ 	return hotCreateRequire(0)(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+
+	var riot = __webpack_require__(1);
+	// Provide some settings
+	riot.settings.brackets = '{{ }}';
+	// Get application tag and mount it! Yeah baby!
+	__webpack_require__(3);
+	riot.mount('app');
+	// Router
+	__webpack_require__(33);
+	// SASS
+	__webpack_require__(52);
+	__webpack_require__(54);
+	__webpack_require__(56);
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	var __WEBPACK_AMD_DEFINE_RESULT__;/* Riot v2.6.8, @license MIT */
+
+	;(function(window, undefined) {
+	  'use strict';
+	var riot = { version: 'v2.6.8', settings: {} },
+	  // be aware, internal usage
+	  // ATTENTION: prefix the global dynamic variables with `__`
+
+	  // counter to give a unique id to all the Tag instances
+	  __uid = 0,
+	  // tags instances cache
+	  __virtualDom = [],
+	  // tags implementation cache
+	  __tagImpl = {},
+
+	  /**
+	   * Const
+	   */
+	  GLOBAL_MIXIN = '__global_mixin',
+
+	  // riot specific prefixes
+	  RIOT_PREFIX = 'riot-',
+	  RIOT_TAG = RIOT_PREFIX + 'tag',
+	  RIOT_TAG_IS = 'data-is',
+
+	  // for typeof == '' comparisons
+	  T_STRING = 'string',
+	  T_OBJECT = 'object',
+	  T_UNDEF  = 'undefined',
+	  T_FUNCTION = 'function',
+	  XLINK_NS = 'http://www.w3.org/1999/xlink',
+	  XLINK_REGEX = /^xlink:(\w+)/,
+	  // special native tags that cannot be treated like the others
+	  SPECIAL_TAGS_REGEX = /^(?:t(?:body|head|foot|[rhd])|caption|col(?:group)?|opt(?:ion|group))$/,
+	  RESERVED_WORDS_BLACKLIST = /^(?:_(?:item|id|parent)|update|root|(?:un)?mount|mixin|is(?:Mounted|Loop)|tags|parent|opts|trigger|o(?:n|ff|ne))$/,
+	  // SVG tags list https://www.w3.org/TR/SVG/attindex.html#PresentationAttributes
+	  SVG_TAGS_LIST = ['altGlyph', 'animate', 'animateColor', 'circle', 'clipPath', 'defs', 'ellipse', 'feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feFlood', 'feGaussianBlur', 'feImage', 'feMerge', 'feMorphology', 'feOffset', 'feSpecularLighting', 'feTile', 'feTurbulence', 'filter', 'font', 'foreignObject', 'g', 'glyph', 'glyphRef', 'image', 'line', 'linearGradient', 'marker', 'mask', 'missing-glyph', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'svg', 'switch', 'symbol', 'text', 'textPath', 'tref', 'tspan', 'use'],
+
+	  // version# for IE 8-11, 0 for others
+	  IE_VERSION = (window && window.document || {}).documentMode | 0,
+
+	  // detect firefox to fix #1374
+	  FIREFOX = window && !!window.InstallTrigger
+	/* istanbul ignore next */
+	riot.observable = function(el) {
+
+	  /**
+	   * Extend the original object or create a new empty one
+	   * @type { Object }
+	   */
+
+	  el = el || {}
+
+	  /**
+	   * Private variables
+	   */
+	  var callbacks = {},
+	    slice = Array.prototype.slice
+
+	  /**
+	   * Private Methods
+	   */
+
+	  /**
+	   * Helper function needed to get and loop all the events in a string
+	   * @param   { String }   e - event string
+	   * @param   {Function}   fn - callback
+	   */
+	  function onEachEvent(e, fn) {
+	    var es = e.split(' '), l = es.length, i = 0
+	    for (; i < l; i++) {
+	      var name = es[i]
+	      if (name) fn(name, i)
+	    }
+	  }
+
+	  /**
+	   * Public Api
+	   */
+
+	  // extend the el object adding the observable methods
+	  Object.defineProperties(el, {
+	    /**
+	     * Listen to the given space separated list of `events` and
+	     * execute the `callback` each time an event is triggered.
+	     * @param  { String } events - events ids
+	     * @param  { Function } fn - callback function
+	     * @returns { Object } el
+	     */
+	    on: {
+	      value: function(events, fn) {
+	        if (typeof fn != 'function')  return el
+
+	        onEachEvent(events, function(name, pos) {
+	          (callbacks[name] = callbacks[name] || []).push(fn)
+	          fn.typed = pos > 0
+	        })
+
+	        return el
+	      },
+	      enumerable: false,
+	      writable: false,
+	      configurable: false
+	    },
+
+	    /**
+	     * Removes the given space separated list of `events` listeners
+	     * @param   { String } events - events ids
+	     * @param   { Function } fn - callback function
+	     * @returns { Object } el
+	     */
+	    off: {
+	      value: function(events, fn) {
+	        if (events == '*' && !fn) callbacks = {}
+	        else {
+	          onEachEvent(events, function(name, pos) {
+	            if (fn) {
+	              var arr = callbacks[name]
+	              for (var i = 0, cb; cb = arr && arr[i]; ++i) {
+	                if (cb == fn) arr.splice(i--, 1)
+	              }
+	            } else delete callbacks[name]
+	          })
+	        }
+	        return el
+	      },
+	      enumerable: false,
+	      writable: false,
+	      configurable: false
+	    },
+
+	    /**
+	     * Listen to the given space separated list of `events` and
+	     * execute the `callback` at most once
+	     * @param   { String } events - events ids
+	     * @param   { Function } fn - callback function
+	     * @returns { Object } el
+	     */
+	    one: {
+	      value: function(events, fn) {
+	        function on() {
+	          el.off(events, on)
+	          fn.apply(el, arguments)
+	        }
+	        return el.on(events, on)
+	      },
+	      enumerable: false,
+	      writable: false,
+	      configurable: false
+	    },
+
+	    /**
+	     * Execute all callback functions that listen to
+	     * the given space separated list of `events`
+	     * @param   { String } events - events ids
+	     * @returns { Object } el
+	     */
+	    trigger: {
+	      value: function(events) {
+
+	        // getting the arguments
+	        var arglen = arguments.length - 1,
+	          args = new Array(arglen),
+	          fns
+
+	        for (var i = 0; i < arglen; i++) {
+	          args[i] = arguments[i + 1] // skip first argument
+	        }
+
+	        onEachEvent(events, function(name, pos) {
+
+	          fns = slice.call(callbacks[name] || [], 0)
+
+	          for (var i = 0, fn; fn = fns[i]; ++i) {
+	            if (fn.busy) continue
+	            fn.busy = 1
+	            fn.apply(el, fn.typed ? [name].concat(args) : args)
+	            if (fns[i] !== fn) { i-- }
+	            fn.busy = 0
+	          }
+
+	          if (callbacks['*'] && name != '*')
+	            el.trigger.apply(el, ['*', name].concat(args))
+
+	        })
+
+	        return el
+	      },
+	      enumerable: false,
+	      writable: false,
+	      configurable: false
+	    }
+	  })
+
+	  return el
+
+	}
+	/* istanbul ignore next */
+	;(function(riot) {
+
+	/**
+	 * Simple client-side router
+	 * @module riot-route
+	 */
+
+
+	var RE_ORIGIN = /^.+?\/\/+[^\/]+/,
+	  EVENT_LISTENER = 'EventListener',
+	  REMOVE_EVENT_LISTENER = 'remove' + EVENT_LISTENER,
+	  ADD_EVENT_LISTENER = 'add' + EVENT_LISTENER,
+	  HAS_ATTRIBUTE = 'hasAttribute',
+	  REPLACE = 'replace',
+	  POPSTATE = 'popstate',
+	  HASHCHANGE = 'hashchange',
+	  TRIGGER = 'trigger',
+	  MAX_EMIT_STACK_LEVEL = 3,
+	  win = typeof window != 'undefined' && window,
+	  doc = typeof document != 'undefined' && document,
+	  hist = win && history,
+	  loc = win && (hist.location || win.location), // see html5-history-api
+	  prot = Router.prototype, // to minify more
+	  clickEvent = doc && doc.ontouchstart ? 'touchstart' : 'click',
+	  started = false,
+	  central = riot.observable(),
+	  routeFound = false,
+	  debouncedEmit,
+	  base, current, parser, secondParser, emitStack = [], emitStackLevel = 0
+
+	/**
+	 * Default parser. You can replace it via router.parser method.
+	 * @param {string} path - current path (normalized)
+	 * @returns {array} array
+	 */
+	function DEFAULT_PARSER(path) {
+	  return path.split(/[/?#]/)
+	}
+
+	/**
+	 * Default parser (second). You can replace it via router.parser method.
+	 * @param {string} path - current path (normalized)
+	 * @param {string} filter - filter string (normalized)
+	 * @returns {array} array
+	 */
+	function DEFAULT_SECOND_PARSER(path, filter) {
+	  var re = new RegExp('^' + filter[REPLACE](/\*/g, '([^/?#]+?)')[REPLACE](/\.\./, '.*') + '$'),
+	    args = path.match(re)
+
+	  if (args) return args.slice(1)
+	}
+
+	/**
+	 * Simple/cheap debounce implementation
+	 * @param   {function} fn - callback
+	 * @param   {number} delay - delay in seconds
+	 * @returns {function} debounced function
+	 */
+	function debounce(fn, delay) {
+	  var t
+	  return function () {
+	    clearTimeout(t)
+	    t = setTimeout(fn, delay)
+	  }
+	}
+
+	/**
+	 * Set the window listeners to trigger the routes
+	 * @param {boolean} autoExec - see route.start
+	 */
+	function start(autoExec) {
+	  debouncedEmit = debounce(emit, 1)
+	  win[ADD_EVENT_LISTENER](POPSTATE, debouncedEmit)
+	  win[ADD_EVENT_LISTENER](HASHCHANGE, debouncedEmit)
+	  doc[ADD_EVENT_LISTENER](clickEvent, click)
+	  if (autoExec) emit(true)
+	}
+
+	/**
+	 * Router class
+	 */
+	function Router() {
+	  this.$ = []
+	  riot.observable(this) // make it observable
+	  central.on('stop', this.s.bind(this))
+	  central.on('emit', this.e.bind(this))
+	}
+
+	function normalize(path) {
+	  return path[REPLACE](/^\/|\/$/, '')
+	}
+
+	function isString(str) {
+	  return typeof str == 'string'
+	}
+
+	/**
+	 * Get the part after domain name
+	 * @param {string} href - fullpath
+	 * @returns {string} path from root
+	 */
+	function getPathFromRoot(href) {
+	  return (href || loc.href)[REPLACE](RE_ORIGIN, '')
+	}
+
+	/**
+	 * Get the part after base
+	 * @param {string} href - fullpath
+	 * @returns {string} path from base
+	 */
+	function getPathFromBase(href) {
+	  return base[0] == '#'
+	    ? (href || loc.href || '').split(base)[1] || ''
+	    : (loc ? getPathFromRoot(href) : href || '')[REPLACE](base, '')
+	}
+
+	function emit(force) {
+	  // the stack is needed for redirections
+	  var isRoot = emitStackLevel == 0, first
+	  if (MAX_EMIT_STACK_LEVEL <= emitStackLevel) return
+
+	  emitStackLevel++
+	  emitStack.push(function() {
+	    var path = getPathFromBase()
+	    if (force || path != current) {
+	      central[TRIGGER]('emit', path)
+	      current = path
+	    }
+	  })
+	  if (isRoot) {
+	    while (first = emitStack.shift()) first() // stack increses within this call
+	    emitStackLevel = 0
+	  }
+	}
+
+	function click(e) {
+	  if (
+	    e.which != 1 // not left click
+	    || e.metaKey || e.ctrlKey || e.shiftKey // or meta keys
+	    || e.defaultPrevented // or default prevented
+	  ) return
+
+	  var el = e.target
+	  while (el && el.nodeName != 'A') el = el.parentNode
+
+	  if (
+	    !el || el.nodeName != 'A' // not A tag
+	    || el[HAS_ATTRIBUTE]('download') // has download attr
+	    || !el[HAS_ATTRIBUTE]('href') // has no href attr
+	    || el.target && el.target != '_self' // another window or frame
+	    || el.href.indexOf(loc.href.match(RE_ORIGIN)[0]) == -1 // cross origin
+	  ) return
+
+	  if (el.href != loc.href
+	    && (
+	      el.href.split('#')[0] == loc.href.split('#')[0] // internal jump
+	      || base[0] != '#' && getPathFromRoot(el.href).indexOf(base) !== 0 // outside of base
+	      || base[0] == '#' && el.href.split(base)[0] != loc.href.split(base)[0] // outside of #base
+	      || !go(getPathFromBase(el.href), el.title || doc.title) // route not found
+	    )) return
+
+	  e.preventDefault()
+	}
+
+	/**
+	 * Go to the path
+	 * @param {string} path - destination path
+	 * @param {string} title - page title
+	 * @param {boolean} shouldReplace - use replaceState or pushState
+	 * @returns {boolean} - route not found flag
+	 */
+	function go(path, title, shouldReplace) {
+	  // Server-side usage: directly execute handlers for the path
+	  if (!hist) return central[TRIGGER]('emit', getPathFromBase(path))
+
+	  path = base + normalize(path)
+	  title = title || doc.title
+	  // browsers ignores the second parameter `title`
+	  shouldReplace
+	    ? hist.replaceState(null, title, path)
+	    : hist.pushState(null, title, path)
+	  // so we need to set it manually
+	  doc.title = title
+	  routeFound = false
+	  emit()
+	  return routeFound
+	}
+
+	/**
+	 * Go to path or set action
+	 * a single string:                go there
+	 * two strings:                    go there with setting a title
+	 * two strings and boolean:        replace history with setting a title
+	 * a single function:              set an action on the default route
+	 * a string/RegExp and a function: set an action on the route
+	 * @param {(string|function)} first - path / action / filter
+	 * @param {(string|RegExp|function)} second - title / action
+	 * @param {boolean} third - replace flag
+	 */
+	prot.m = function(first, second, third) {
+	  if (isString(first) && (!second || isString(second))) go(first, second, third || false)
+	  else if (second) this.r(first, second)
+	  else this.r('@', first)
+	}
+
+	/**
+	 * Stop routing
+	 */
+	prot.s = function() {
+	  this.off('*')
+	  this.$ = []
+	}
+
+	/**
+	 * Emit
+	 * @param {string} path - path
+	 */
+	prot.e = function(path) {
+	  this.$.concat('@').some(function(filter) {
+	    var args = (filter == '@' ? parser : secondParser)(normalize(path), normalize(filter))
+	    if (typeof args != 'undefined') {
+	      this[TRIGGER].apply(null, [filter].concat(args))
+	      return routeFound = true // exit from loop
+	    }
+	  }, this)
+	}
+
+	/**
+	 * Register route
+	 * @param {string} filter - filter for matching to url
+	 * @param {function} action - action to register
+	 */
+	prot.r = function(filter, action) {
+	  if (filter != '@') {
+	    filter = '/' + normalize(filter)
+	    this.$.push(filter)
+	  }
+	  this.on(filter, action)
+	}
+
+	var mainRouter = new Router()
+	var route = mainRouter.m.bind(mainRouter)
+
+	/**
+	 * Create a sub router
+	 * @returns {function} the method of a new Router object
+	 */
+	route.create = function() {
+	  var newSubRouter = new Router()
+	  // assign sub-router's main method
+	  var router = newSubRouter.m.bind(newSubRouter)
+	  // stop only this sub-router
+	  router.stop = newSubRouter.s.bind(newSubRouter)
+	  return router
+	}
+
+	/**
+	 * Set the base of url
+	 * @param {(str|RegExp)} arg - a new base or '#' or '#!'
+	 */
+	route.base = function(arg) {
+	  base = arg || '#'
+	  current = getPathFromBase() // recalculate current path
+	}
+
+	/** Exec routing right now **/
+	route.exec = function() {
+	  emit(true)
+	}
+
+	/**
+	 * Replace the default router to yours
+	 * @param {function} fn - your parser function
+	 * @param {function} fn2 - your secondParser function
+	 */
+	route.parser = function(fn, fn2) {
+	  if (!fn && !fn2) {
+	    // reset parser for testing...
+	    parser = DEFAULT_PARSER
+	    secondParser = DEFAULT_SECOND_PARSER
+	  }
+	  if (fn) parser = fn
+	  if (fn2) secondParser = fn2
+	}
+
+	/**
+	 * Helper function to get url query as an object
+	 * @returns {object} parsed query
+	 */
+	route.query = function() {
+	  var q = {}
+	  var href = loc.href || current
+	  href[REPLACE](/[?&](.+?)=([^&]*)/g, function(_, k, v) { q[k] = v })
+	  return q
+	}
+
+	/** Stop routing **/
+	route.stop = function () {
+	  if (started) {
+	    if (win) {
+	      win[REMOVE_EVENT_LISTENER](POPSTATE, debouncedEmit)
+	      win[REMOVE_EVENT_LISTENER](HASHCHANGE, debouncedEmit)
+	      doc[REMOVE_EVENT_LISTENER](clickEvent, click)
+	    }
+	    central[TRIGGER]('stop')
+	    started = false
+	  }
+	}
+
+	/**
+	 * Start routing
+	 * @param {boolean} autoExec - automatically exec after starting if true
+	 */
+	route.start = function (autoExec) {
+	  if (!started) {
+	    if (win) {
+	      if (document.readyState == 'complete') start(autoExec)
+	      // the timeout is needed to solve
+	      // a weird safari bug https://github.com/riot/route/issues/33
+	      else win[ADD_EVENT_LISTENER]('load', function() {
+	        setTimeout(function() { start(autoExec) }, 1)
+	      })
+	    }
+	    started = true
+	  }
+	}
+
+	/** Prepare the router **/
+	route.base()
+	route.parser()
+
+	riot.route = route
+	})(riot)
+	/* istanbul ignore next */
+
+	/**
+	 * The riot template engine
+	 * @version v2.4.2
+	 */
+	/**
+	 * riot.util.brackets
+	 *
+	 * - `brackets    ` - Returns a string or regex based on its parameter
+	 * - `brackets.set` - Change the current riot brackets
+	 *
+	 * @module
+	 */
+
+	var brackets = (function (UNDEF) {
+
+	  var
+	    REGLOB = 'g',
+
+	    R_MLCOMMS = /\/\*[^*]*\*+(?:[^*\/][^*]*\*+)*\//g,
+
+	    R_STRINGS = /"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'/g,
+
+	    S_QBLOCKS = R_STRINGS.source + '|' +
+	      /(?:\breturn\s+|(?:[$\w\)\]]|\+\+|--)\s*(\/)(?![*\/]))/.source + '|' +
+	      /\/(?=[^*\/])[^[\/\\]*(?:(?:\[(?:\\.|[^\]\\]*)*\]|\\.)[^[\/\\]*)*?(\/)[gim]*/.source,
+
+	    UNSUPPORTED = RegExp('[\\' + 'x00-\\x1F<>a-zA-Z0-9\'",;\\\\]'),
+
+	    NEED_ESCAPE = /(?=[[\]()*+?.^$|])/g,
+
+	    FINDBRACES = {
+	      '(': RegExp('([()])|'   + S_QBLOCKS, REGLOB),
+	      '[': RegExp('([[\\]])|' + S_QBLOCKS, REGLOB),
+	      '{': RegExp('([{}])|'   + S_QBLOCKS, REGLOB)
+	    },
+
+	    DEFAULT = '{ }'
+
+	  var _pairs = [
+	    '{', '}',
+	    '{', '}',
+	    /{[^}]*}/,
+	    /\\([{}])/g,
+	    /\\({)|{/g,
+	    RegExp('\\\\(})|([[({])|(})|' + S_QBLOCKS, REGLOB),
+	    DEFAULT,
+	    /^\s*{\^?\s*([$\w]+)(?:\s*,\s*(\S+))?\s+in\s+(\S.*)\s*}/,
+	    /(^|[^\\]){=[\S\s]*?}/
+	  ]
+
+	  var
+	    cachedBrackets = UNDEF,
+	    _regex,
+	    _cache = [],
+	    _settings
+
+	  function _loopback (re) { return re }
+
+	  function _rewrite (re, bp) {
+	    if (!bp) bp = _cache
+	    return new RegExp(
+	      re.source.replace(/{/g, bp[2]).replace(/}/g, bp[3]), re.global ? REGLOB : ''
+	    )
+	  }
+
+	  function _create (pair) {
+	    if (pair === DEFAULT) return _pairs
+
+	    var arr = pair.split(' ')
+
+	    if (arr.length !== 2 || UNSUPPORTED.test(pair)) {
+	      throw new Error('Unsupported brackets "' + pair + '"')
+	    }
+	    arr = arr.concat(pair.replace(NEED_ESCAPE, '\\').split(' '))
+
+	    arr[4] = _rewrite(arr[1].length > 1 ? /{[\S\s]*?}/ : _pairs[4], arr)
+	    arr[5] = _rewrite(pair.length > 3 ? /\\({|})/g : _pairs[5], arr)
+	    arr[6] = _rewrite(_pairs[6], arr)
+	    arr[7] = RegExp('\\\\(' + arr[3] + ')|([[({])|(' + arr[3] + ')|' + S_QBLOCKS, REGLOB)
+	    arr[8] = pair
+	    return arr
+	  }
+
+	  function _brackets (reOrIdx) {
+	    return reOrIdx instanceof RegExp ? _regex(reOrIdx) : _cache[reOrIdx]
+	  }
+
+	  _brackets.split = function split (str, tmpl, _bp) {
+	    // istanbul ignore next: _bp is for the compiler
+	    if (!_bp) _bp = _cache
+
+	    var
+	      parts = [],
+	      match,
+	      isexpr,
+	      start,
+	      pos,
+	      re = _bp[6]
+
+	    isexpr = start = re.lastIndex = 0
+
+	    while ((match = re.exec(str))) {
+
+	      pos = match.index
+
+	      if (isexpr) {
+
+	        if (match[2]) {
+	          re.lastIndex = skipBraces(str, match[2], re.lastIndex)
+	          continue
+	        }
+	        if (!match[3]) {
+	          continue
+	        }
+	      }
+
+	      if (!match[1]) {
+	        unescapeStr(str.slice(start, pos))
+	        start = re.lastIndex
+	        re = _bp[6 + (isexpr ^= 1)]
+	        re.lastIndex = start
+	      }
+	    }
+
+	    if (str && start < str.length) {
+	      unescapeStr(str.slice(start))
+	    }
+
+	    return parts
+
+	    function unescapeStr (s) {
+	      if (tmpl || isexpr) {
+	        parts.push(s && s.replace(_bp[5], '$1'))
+	      } else {
+	        parts.push(s)
+	      }
+	    }
+
+	    function skipBraces (s, ch, ix) {
+	      var
+	        match,
+	        recch = FINDBRACES[ch]
+
+	      recch.lastIndex = ix
+	      ix = 1
+	      while ((match = recch.exec(s))) {
+	        if (match[1] &&
+	          !(match[1] === ch ? ++ix : --ix)) break
+	      }
+	      return ix ? s.length : recch.lastIndex
+	    }
+	  }
+
+	  _brackets.hasExpr = function hasExpr (str) {
+	    return _cache[4].test(str)
+	  }
+
+	  _brackets.loopKeys = function loopKeys (expr) {
+	    var m = expr.match(_cache[9])
+
+	    return m
+	      ? { key: m[1], pos: m[2], val: _cache[0] + m[3].trim() + _cache[1] }
+	      : { val: expr.trim() }
+	  }
+
+	  _brackets.array = function array (pair) {
+	    return pair ? _create(pair) : _cache
+	  }
+
+	  function _reset (pair) {
+	    if ((pair || (pair = DEFAULT)) !== _cache[8]) {
+	      _cache = _create(pair)
+	      _regex = pair === DEFAULT ? _loopback : _rewrite
+	      _cache[9] = _regex(_pairs[9])
+	    }
+	    cachedBrackets = pair
+	  }
+
+	  function _setSettings (o) {
+	    var b
+
+	    o = o || {}
+	    b = o.brackets
+	    Object.defineProperty(o, 'brackets', {
+	      set: _reset,
+	      get: function () { return cachedBrackets },
+	      enumerable: true
+	    })
+	    _settings = o
+	    _reset(b)
+	  }
+
+	  Object.defineProperty(_brackets, 'settings', {
+	    set: _setSettings,
+	    get: function () { return _settings }
+	  })
+
+	  /* istanbul ignore next: in the browser riot is always in the scope */
+	  _brackets.settings = typeof riot !== 'undefined' && riot.settings || {}
+	  _brackets.set = _reset
+
+	  _brackets.R_STRINGS = R_STRINGS
+	  _brackets.R_MLCOMMS = R_MLCOMMS
+	  _brackets.S_QBLOCKS = S_QBLOCKS
+
+	  return _brackets
+
+	})()
+
+	/**
+	 * @module tmpl
+	 *
+	 * tmpl          - Root function, returns the template value, render with data
+	 * tmpl.hasExpr  - Test the existence of a expression inside a string
+	 * tmpl.loopKeys - Get the keys for an 'each' loop (used by `_each`)
+	 */
+
+	var tmpl = (function () {
+
+	  var _cache = {}
+
+	  function _tmpl (str, data) {
+	    if (!str) return str
+
+	    return (_cache[str] || (_cache[str] = _create(str))).call(data, _logErr)
+	  }
+
+	  _tmpl.haveRaw = brackets.hasRaw
+
+	  _tmpl.hasExpr = brackets.hasExpr
+
+	  _tmpl.loopKeys = brackets.loopKeys
+
+	  // istanbul ignore next
+	  _tmpl.clearCache = function () { _cache = {} }
+
+	  _tmpl.errorHandler = null
+
+	  function _logErr (err, ctx) {
+
+	    if (_tmpl.errorHandler) {
+
+	      err.riotData = {
+	        tagName: ctx && ctx.root && ctx.root.tagName,
+	        _riot_id: ctx && ctx._riot_id  //eslint-disable-line camelcase
+	      }
+	      _tmpl.errorHandler(err)
+	    }
+	  }
+
+	  function _create (str) {
+	    var expr = _getTmpl(str)
+
+	    if (expr.slice(0, 11) !== 'try{return ') expr = 'return ' + expr
+
+	    return new Function('E', expr + ';')    // eslint-disable-line no-new-func
+	  }
+
+	  var
+	    CH_IDEXPR = String.fromCharCode(0x2057),
+	    RE_CSNAME = /^(?:(-?[_A-Za-z\xA0-\xFF][-\w\xA0-\xFF]*)|\u2057(\d+)~):/,
+	    RE_QBLOCK = RegExp(brackets.S_QBLOCKS, 'g'),
+	    RE_DQUOTE = /\u2057/g,
+	    RE_QBMARK = /\u2057(\d+)~/g
+
+	  function _getTmpl (str) {
+	    var
+	      qstr = [],
+	      expr,
+	      parts = brackets.split(str.replace(RE_DQUOTE, '"'), 1)
+
+	    if (parts.length > 2 || parts[0]) {
+	      var i, j, list = []
+
+	      for (i = j = 0; i < parts.length; ++i) {
+
+	        expr = parts[i]
+
+	        if (expr && (expr = i & 1
+
+	            ? _parseExpr(expr, 1, qstr)
+
+	            : '"' + expr
+	                .replace(/\\/g, '\\\\')
+	                .replace(/\r\n?|\n/g, '\\n')
+	                .replace(/"/g, '\\"') +
+	              '"'
+
+	          )) list[j++] = expr
+
+	      }
+
+	      expr = j < 2 ? list[0]
+	           : '[' + list.join(',') + '].join("")'
+
+	    } else {
+
+	      expr = _parseExpr(parts[1], 0, qstr)
+	    }
+
+	    if (qstr[0]) {
+	      expr = expr.replace(RE_QBMARK, function (_, pos) {
+	        return qstr[pos]
+	          .replace(/\r/g, '\\r')
+	          .replace(/\n/g, '\\n')
+	      })
+	    }
+	    return expr
+	  }
+
+	  var
+	    RE_BREND = {
+	      '(': /[()]/g,
+	      '[': /[[\]]/g,
+	      '{': /[{}]/g
+	    }
+
+	  function _parseExpr (expr, asText, qstr) {
+
+	    expr = expr
+	          .replace(RE_QBLOCK, function (s, div) {
+	            return s.length > 2 && !div ? CH_IDEXPR + (qstr.push(s) - 1) + '~' : s
+	          })
+	          .replace(/\s+/g, ' ').trim()
+	          .replace(/\ ?([[\({},?\.:])\ ?/g, '$1')
+
+	    if (expr) {
+	      var
+	        list = [],
+	        cnt = 0,
+	        match
+
+	      while (expr &&
+	            (match = expr.match(RE_CSNAME)) &&
+	            !match.index
+	        ) {
+	        var
+	          key,
+	          jsb,
+	          re = /,|([[{(])|$/g
+
+	        expr = RegExp.rightContext
+	        key  = match[2] ? qstr[match[2]].slice(1, -1).trim().replace(/\s+/g, ' ') : match[1]
+
+	        while (jsb = (match = re.exec(expr))[1]) skipBraces(jsb, re)
+
+	        jsb  = expr.slice(0, match.index)
+	        expr = RegExp.rightContext
+
+	        list[cnt++] = _wrapExpr(jsb, 1, key)
+	      }
+
+	      expr = !cnt ? _wrapExpr(expr, asText)
+	           : cnt > 1 ? '[' + list.join(',') + '].join(" ").trim()' : list[0]
+	    }
+	    return expr
+
+	    function skipBraces (ch, re) {
+	      var
+	        mm,
+	        lv = 1,
+	        ir = RE_BREND[ch]
+
+	      ir.lastIndex = re.lastIndex
+	      while (mm = ir.exec(expr)) {
+	        if (mm[0] === ch) ++lv
+	        else if (!--lv) break
+	      }
+	      re.lastIndex = lv ? expr.length : ir.lastIndex
+	    }
+	  }
+
+	  // istanbul ignore next: not both
+	  var // eslint-disable-next-line max-len
+	    JS_CONTEXT = '"in this?this:' + (typeof window !== 'object' ? 'global' : 'window') + ').',
+	    JS_VARNAME = /[,{][\$\w]+(?=:)|(^ *|[^$\w\.{])(?!(?:typeof|true|false|null|undefined|in|instanceof|is(?:Finite|NaN)|void|NaN|new|Date|RegExp|Math)(?![$\w]))([$_A-Za-z][$\w]*)/g,
+	    JS_NOPROPS = /^(?=(\.[$\w]+))\1(?:[^.[(]|$)/
+
+	  function _wrapExpr (expr, asText, key) {
+	    var tb
+
+	    expr = expr.replace(JS_VARNAME, function (match, p, mvar, pos, s) {
+	      if (mvar) {
+	        pos = tb ? 0 : pos + match.length
+
+	        if (mvar !== 'this' && mvar !== 'global' && mvar !== 'window') {
+	          match = p + '("' + mvar + JS_CONTEXT + mvar
+	          if (pos) tb = (s = s[pos]) === '.' || s === '(' || s === '['
+	        } else if (pos) {
+	          tb = !JS_NOPROPS.test(s.slice(pos))
+	        }
+	      }
+	      return match
+	    })
+
+	    if (tb) {
+	      expr = 'try{return ' + expr + '}catch(e){E(e,this)}'
+	    }
+
+	    if (key) {
+
+	      expr = (tb
+	          ? 'function(){' + expr + '}.call(this)' : '(' + expr + ')'
+	        ) + '?"' + key + '":""'
+
+	    } else if (asText) {
+
+	      expr = 'function(v){' + (tb
+	          ? expr.replace('return ', 'v=') : 'v=(' + expr + ')'
+	        ) + ';return v||v===0?v:""}.call(this)'
+	    }
+
+	    return expr
+	  }
+
+	  _tmpl.version = brackets.version = 'v2.4.2'
+
+	  return _tmpl
+
+	})()
+
+	/*
+	  lib/browser/tag/mkdom.js
+
+	  Includes hacks needed for the Internet Explorer version 9 and below
+	  See: http://kangax.github.io/compat-table/es5/#ie8
+	       http://codeplanet.io/dropping-ie8/
+	*/
+	var mkdom = (function _mkdom() {
+	  var
+	    reHasYield  = /|>([\S\s]*?)<\/yield\s*>|>)/ig,
+	    reYieldSrc  = /]*)['"]\s*>([\S\s]*?)<\/yield\s*>/ig,
+	    reYieldDest = /|>([\S\s]*?)<\/yield\s*>)/ig
+	  var
+	    rootEls = { tr: 'tbody', th: 'tr', td: 'tr', col: 'colgroup' },
+	    tblTags = IE_VERSION && IE_VERSION < 10
+	      ? SPECIAL_TAGS_REGEX : /^(?:t(?:body|head|foot|[rhd])|caption|col(?:group)?)$/
+
+	  /**
+	   * Creates a DOM element to wrap the given content. Normally an `DIV`, but can be
+	   * also a `TABLE`, `SELECT`, `TBODY`, `TR`, or `COLGROUP` element.
+	   *
+	   * @param   { String } templ  - The template coming from the custom tag definition
+	   * @param   { String } [html] - HTML content that comes from the DOM element where you
+	   *           will mount the tag, mostly the original tag in the page
+	   * @param   { Boolean } checkSvg - flag needed to know if we need to force the svg rendering in case of loop nodes
+	   * @returns {HTMLElement} DOM element with _templ_ merged through `YIELD` with the _html_.
+	   */
+	  function _mkdom(templ, html, checkSvg) {
+	    var
+	      match   = templ && templ.match(/^\s*<([-\w]+)/),
+	      tagName = match && match[1].toLowerCase(),
+	      el = mkEl('div', checkSvg && isSVGTag(tagName))
+
+	    // replace all the yield tags with the tag inner html
+	    templ = replaceYield(templ, html)
+
+	    /* istanbul ignore next */
+	    if (tblTags.test(tagName))
+	      el = specialTags(el, templ, tagName)
+	    else
+	      setInnerHTML(el, templ)
+
+	    el.stub = true
+
+	    return el
+	  }
+
+	  /*
+	    Creates the root element for table or select child elements:
+	    tr/th/td/thead/tfoot/tbody/caption/col/colgroup/option/optgroup
+	  */
+	  function specialTags(el, templ, tagName) {
+	    var
+	      select = tagName[0] === 'o',
+	      parent = select ? 'select>' : 'table>'
+
+	    // trim() is important here, this ensures we don't have artifacts,
+	    // so we can check if we have only one element inside the parent
+	    el.innerHTML = '<' + parent + templ.trim() + '' + parent
+	    parent = el.firstChild
+
+	    // returns the immediate parent if tr/th/td/col is the only element, if not
+	    // returns the whole tree, as this can include additional elements
+	    if (select) {
+	      parent.selectedIndex = -1  // for IE9, compatible w/current riot behavior
+	    } else {
+	      // avoids insertion of cointainer inside container (ex: tbody inside tbody)
+	      var tname = rootEls[tagName]
+	      if (tname && parent.childElementCount === 1) parent = $(tname, parent)
+	    }
+	    return parent
+	  }
+
+	  /*
+	    Replace the yield tag from any tag template with the innerHTML of the
+	    original tag in the page
+	  */
+	  function replaceYield(templ, html) {
+	    // do nothing if no yield
+	    if (!reHasYield.test(templ)) return templ
+
+	    // be careful with #1343 - string on the source having `$1`
+	    var src = {}
+
+	    html = html && html.replace(reYieldSrc, function (_, ref, text) {
+	      src[ref] = src[ref] || text   // preserve first definition
+	      return ''
+	    }).trim()
+
+	    return templ
+	      .replace(reYieldDest, function (_, ref, def) {  // yield with from - to attrs
+	        return src[ref] || def || ''
+	      })
+	      .replace(reYieldAll, function (_, def) {        // yield without any "from"
+	        return html || def || ''
+	      })
+	  }
+
+	  return _mkdom
+
+	})()
+
+	/**
+	 * Convert the item looped into an object used to extend the child tag properties
+	 * @param   { Object } expr - object containing the keys used to extend the children tags
+	 * @param   { * } key - value to assign to the new object returned
+	 * @param   { * } val - value containing the position of the item in the array
+	 * @returns { Object } - new object containing the values of the original item
+	 *
+	 * The variables 'key' and 'val' are arbitrary.
+	 * They depend on the collection type looped (Array, Object)
+	 * and on the expression used on the each tag
+	 *
+	 */
+	function mkitem(expr, key, val) {
+	  var item = {}
+	  item[expr.key] = key
+	  if (expr.pos) item[expr.pos] = val
+	  return item
+	}
+
+	/**
+	 * Unmount the redundant tags
+	 * @param   { Array } items - array containing the current items to loop
+	 * @param   { Array } tags - array containing all the children tags
+	 */
+	function unmountRedundant(items, tags) {
+
+	  var i = tags.length,
+	    j = items.length,
+	    t
+
+	  while (i > j) {
+	    t = tags[--i]
+	    tags.splice(i, 1)
+	    t.unmount()
+	  }
+	}
+
+	/**
+	 * Move the nested custom tags in non custom loop tags
+	 * @param   { Object } child - non custom loop tag
+	 * @param   { Number } i - current position of the loop tag
+	 */
+	function moveNestedTags(child, i) {
+	  Object.keys(child.tags).forEach(function(tagName) {
+	    var tag = child.tags[tagName]
+	    if (isArray(tag))
+	      each(tag, function (t) {
+	        moveChildTag(t, tagName, i)
+	      })
+	    else
+	      moveChildTag(tag, tagName, i)
+	  })
+	}
+
+	/**
+	 * Adds the elements for a virtual tag
+	 * @param { Tag } tag - the tag whose root's children will be inserted or appended
+	 * @param { Node } src - the node that will do the inserting or appending
+	 * @param { Tag } target - only if inserting, insert before this tag's first child
+	 */
+	function addVirtual(tag, src, target) {
+	  var el = tag._root, sib
+	  tag._virts = []
+	  while (el) {
+	    sib = el.nextSibling
+	    if (target)
+	      src.insertBefore(el, target._root)
+	    else
+	      src.appendChild(el)
+
+	    tag._virts.push(el) // hold for unmounting
+	    el = sib
+	  }
+	}
+
+	/**
+	 * Move virtual tag and all child nodes
+	 * @param { Tag } tag - first child reference used to start move
+	 * @param { Node } src  - the node that will do the inserting
+	 * @param { Tag } target - insert before this tag's first child
+	 * @param { Number } len - how many child nodes to move
+	 */
+	function moveVirtual(tag, src, target, len) {
+	  var el = tag._root, sib, i = 0
+	  for (; i < len; i++) {
+	    sib = el.nextSibling
+	    src.insertBefore(el, target._root)
+	    el = sib
+	  }
+	}
+
+	/**
+	 * Insert a new tag avoiding the insert for the conditional tags
+	 * @param   {Boolean} isVirtual [description]
+	 * @param   { Tag }  prevTag - tag instance used as reference to prepend our new tag
+	 * @param   { Tag }  newTag - new tag to be inserted
+	 * @param   { HTMLElement }  root - loop parent node
+	 * @param   { Array }  tags - array containing the current tags list
+	 * @param   { Function }  virtualFn - callback needed to move or insert virtual DOM
+	 * @param   { Object } dom - DOM node we need to loop
+	 */
+	function insertTag(isVirtual, prevTag, newTag, root, tags, virtualFn, dom) {
+	  if (isInStub(prevTag.root)) return
+	  if (isVirtual) virtualFn(prevTag, root, newTag, dom.childNodes.length)
+	  else root.insertBefore(prevTag.root, newTag.root) // #1374 some browsers reset selected here
+	}
+
+
+	/**
+	 * Manage tags having the 'each'
+	 * @param   { Object } dom - DOM node we need to loop
+	 * @param   { Tag } parent - parent tag instance where the dom node is contained
+	 * @param   { String } expr - string contained in the 'each' attribute
+	 */
+	function _each(dom, parent, expr) {
+
+	  // remove the each property from the original tag
+	  remAttr(dom, 'each')
+
+	  var mustReorder = typeof getAttr(dom, 'no-reorder') !== T_STRING || remAttr(dom, 'no-reorder'),
+	    tagName = getTagName(dom),
+	    impl = __tagImpl[tagName] || { tmpl: getOuterHTML(dom) },
+	    useRoot = SPECIAL_TAGS_REGEX.test(tagName),
+	    root = dom.parentNode,
+	    ref = document.createTextNode(''),
+	    child = getTag(dom),
+	    isOption = tagName.toLowerCase() === 'option', // the option tags must be treated differently
+	    tags = [],
+	    oldItems = [],
+	    hasKeys,
+	    isVirtual = dom.tagName == 'VIRTUAL'
+
+	  // parse the each expression
+	  expr = tmpl.loopKeys(expr)
+
+	  // insert a marked where the loop tags will be injected
+	  root.insertBefore(ref, dom)
+
+	  // clean template code
+	  parent.one('before-mount', function () {
+
+	    // remove the original DOM node
+	    dom.parentNode.removeChild(dom)
+	    if (root.stub) root = parent.root
+
+	  }).on('update', function () {
+	    // get the new items collection
+	    var items = tmpl(expr.val, parent),
+	      // create a fragment to hold the new DOM nodes to inject in the parent tag
+	      frag = document.createDocumentFragment()
+
+	    // object loop. any changes cause full redraw
+	    if (!isArray(items)) {
+	      hasKeys = items || false
+	      items = hasKeys ?
+	        Object.keys(items).map(function (key) {
+	          return mkitem(expr, key, items[key])
+	        }) : []
+	    }
+
+	    // loop all the new items
+	    var i = 0,
+	      itemsLength = items.length
+
+	    for (; i < itemsLength; i++) {
+	      // reorder only if the items are objects
+	      var
+	        item = items[i],
+	        _mustReorder = mustReorder && typeof item == T_OBJECT && !hasKeys,
+	        oldPos = oldItems.indexOf(item),
+	        pos = ~oldPos && _mustReorder ? oldPos : i,
+	        // does a tag exist in this position?
+	        tag = tags[pos]
+
+	      item = !hasKeys && expr.key ? mkitem(expr, item, i) : item
+
+	      // new tag
+	      if (
+	        !_mustReorder && !tag // with no-reorder we just update the old tags
+	        ||
+	        _mustReorder && !~oldPos || !tag // by default we always try to reorder the DOM elements
+	      ) {
+
+	        tag = new Tag(impl, {
+	          parent: parent,
+	          isLoop: true,
+	          hasImpl: !!__tagImpl[tagName],
+	          root: useRoot ? root : dom.cloneNode(),
+	          item: item
+	        }, dom.innerHTML)
+
+	        tag.mount()
+
+	        if (isVirtual) tag._root = tag.root.firstChild // save reference for further moves or inserts
+	        // this tag must be appended
+	        if (i == tags.length || !tags[i]) { // fix 1581
+	          if (isVirtual)
+	            addVirtual(tag, frag)
+	          else frag.appendChild(tag.root)
+	        }
+	        // this tag must be insert
+	        else {
+	          insertTag(isVirtual, tag, tags[i], root, tags, addVirtual, dom)
+	          oldItems.splice(i, 0, item)
+	        }
+
+	        tags.splice(i, 0, tag)
+	        pos = i // handled here so no move
+	      } else tag.update(item, true)
+
+	      // reorder the tag if it's not located in its previous position
+	      if (
+	        pos !== i && _mustReorder &&
+	        tags[i] // fix 1581 unable to reproduce it in a test!
+	      ) {
+	        // #closes 2040 PLEASE DON'T REMOVE IT!
+	        // there are no tests for this feature
+	        if (contains(items, oldItems[i]))
+	          insertTag(isVirtual, tag, tags[i], root, tags, moveVirtual, dom)
+
+	        // update the position attribute if it exists
+	        if (expr.pos)
+	          tag[expr.pos] = i
+	        // move the old tag instance
+	        tags.splice(i, 0, tags.splice(pos, 1)[0])
+	        // move the old item
+	        oldItems.splice(i, 0, oldItems.splice(pos, 1)[0])
+	        // if the loop tags are not custom
+	        // we need to move all their custom tags into the right position
+	        if (!child && tag.tags) moveNestedTags(tag, i)
+	      }
+
+	      // cache the original item to use it in the events bound to this node
+	      // and its children
+	      tag._item = item
+	      // cache the real parent tag internally
+	      defineProperty(tag, '_parent', parent)
+	    }
+
+	    // remove the redundant tags
+	    unmountRedundant(items, tags)
+
+	    // insert the new nodes
+	    root.insertBefore(frag, ref)
+	    if (isOption) {
+
+	      // #1374 FireFox bug in