diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..9f11b755a17d8192c60f61cb17b8902dffbd9f23
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.idea/
diff --git a/.htaccess b/.htaccess
index 97216901b3a9278cc1996b84de5665eb0429a91e..83f9f9cf2e14008ec64eac0e86d632f9991af027 100644
--- a/.htaccess
+++ b/.htaccess
@@ -2,3 +2,6 @@
    # Enable expirations.
    ExpiresActive Off
 </IfModule>
+
+RewriteEngine on
+RewriteRule ^(.*).less$ less/style.php?name=$1.less
diff --git a/ajax/ConfigurationComponent.php b/ajax/ConfigurationComponent.php
deleted file mode 100755
index 0df7bb1ab02f7a5e87cfc203aeea8fde49cb94b0..0000000000000000000000000000000000000000
--- a/ajax/ConfigurationComponent.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-	namespace App\Controller\Component;
-
-	use Cake\Controller\Component;
-	use Cake\Filesystem\File;
-
-	class ConfigurationComponent extends Component {
-
-		private $session = NULL;
-		private $folder = null;
-
-		public function initialize(array $config) {
-			$this->session = $this->request->session();
-		}
-
-		public function getConfiguration($session_key, $config_name = '', $config_type = 'panel') {
-			if (!is_string($session_key)
-			|| !is_string($config_name)
-			|| !is_string($config_type)
-			|| empty($session_key)) {
-				return FALSE;
-			}
-			// load data from session or reload data to session?
-	/*		if ($this->session->check($session_key)) {
-				// return configuration
-				return $this->session->read($session_key);
-			} else {*/
-				// reload configuration
-				return $this->getReloadedConfiguration($session_key, $config_name, $config_type);
-	//		}
-		}
-
-		public function getReloadedConfiguration($session_key, $config_name = '', $config_type = 'panel') {
-			if (!is_string($session_key)
-			|| !is_string($config_name)
-			|| !is_string($config_type)
-			|| (strpos($config_type, ".."))
-			|| empty($config_name)
-			|| empty($session_key)) {
-				return FALSE;
-			}
-			// get filename for configuration
-			$file = new File(ROOT.'/config/'.$config_type.'/'.$config_name.'.json');
-			// can we get our configuration?
-			if ($file->exists() && $file->readable()
-			&& !(($file_content = $file->read()) === false)) {
-				// decode, save and return configuration
-				$result = json_decode($file_content,true);
-				$this->session->write($session_key, $result);
-				return $result;
-			} else {
-				// ERROR!
-				return FALSE;
-			}
-		}
-
-	}
diff --git a/config/config.php b/config/config.php
new file mode 100644
index 0000000000000000000000000000000000000000..163f2a6dc5893787db484cbc08505530405b58e1
--- /dev/null
+++ b/config/config.php
@@ -0,0 +1,3 @@
+<?php
+const ROOT_DIR="/infoscreen";
+?>
diff --git a/css/colors.less b/css/colors.less
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/css/design.css b/css/design.css
deleted file mode 100755
index d972af786868c8a83741284d2deca978435f6aeb..0000000000000000000000000000000000000000
--- a/css/design.css
+++ /dev/null
@@ -1,48 +0,0 @@
-@viewport {
-  width: device-width;
-  user-zoom: fixed;
-}
-body {
-  margin: 0px;
-  background: #0a0a0a;
-  font-family: Arial;
-  overflow: hidden;
-}
-[data-container=panel] {
-  background-color: rgba(8, 8, 8, 0.68);
-  border: solid 1px #252525;
-  box-shadow: 0px 2px 1px #000000;
-  padding: 6px;
-  /*	margin: 5px;*/
-  float: left;
-  box-sizing: border-box;
-  height: 100%;
-  width: 100%;
-  overflow: hidden;
-}
-[data-container=panelContainer] {
-  float: left;
-  width: 100%;
-  height: 100%;
-  /*padding: 4px;*/
-  padding: 0.2vw;
-  box-sizing: border-box;
-}
-[data-container=split] {
-  box-sizing: border-box;
-  /*	display: flex;
-	flex-direction: column;*/
-  height: 100%;
-  width: 100%;
-  float: left;
-}
-[data-container=main] {
-  height: 100%;
-  width: 100%;
-  position: absolute;
-  box-sizing: border-box;
-  padding: 0.2vw;
-  background: radial-gradient(black 15%, transparent 15%) 0 0, radial-gradient(black 15%, transparent 15%) 12px 12px, radial-gradient(rgba(255, 255, 255, 0.1) 15%, transparent 20%) 0 1px, radial-gradient(rgba(255, 255, 255, 0.1) 15%, transparent 20%) 12px 13px;
-  background-size: 24px 24px;
-  background-color: #171717;
-}
diff --git a/css/design.less b/css/design.less
index ef8f4750a6647da810596029167ec4efa8bb0b0a..6cd6069f7241e8b8c744c6872cf7364d788bddee 100755
--- a/css/design.less
+++ b/css/design.less
@@ -6,18 +6,17 @@
 }
 
 body {
-	margin: 0px;
-	background: #0a0a0a;
-	font-family: Arial;
-	overflow:hidden;
+    margin: 0;
+    background: #0a0a0a;
+    font-family: Arial, serif;
+    overflow:hidden;
 }
 
 [data-container=panel] {
 	background-color: rgba(8, 8, 8, 0.68);
 	border: solid 1px #252525;
-	box-shadow: 0px 2px 1px #000000;
+	box-shadow: 0 2px 1px #000000;
 	padding: 6px;
-/*	margin: 5px;*/
 	float:left;
 	box-sizing: border-box;
 	height:100%;
@@ -49,11 +48,13 @@ body {
 	position:absolute;
 
 	box-sizing: border-box;
-		padding: 0.2vw;
-    background: radial-gradient(black 15%, transparent 15%) 0 0, radial-gradient(black 15%, transparent 15%) @dotdist @dotdist, radial-gradient(rgba(255,255,255,.1) 
-15%, 
-transparent 20%) 0 1px, radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) @dotdist @dotdist+1;
+    padding: 0.2vw;
+    background:
+      radial-gradient(black 15%, transparent 15%) 0 0,
+      radial-gradient(black 15%, transparent 15%) @dotdist @dotdist,
+      radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 0 1px,
+      radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) @dotdist @dotdist+1,
+      #171717;
     background-size: @dotdist*2 @dotdist*2;
-    background-color: #171717;
 }
 
diff --git a/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png b/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png
new file mode 100644
index 0000000000000000000000000000000000000000..ed793737cc1d1383f3478faa1b9519c9f3318268
Binary files /dev/null and b/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png differ
diff --git a/css/images/ui-bg_diagonals-thick_20_666666_40x40.png b/css/images/ui-bg_diagonals-thick_20_666666_40x40.png
new file mode 100644
index 0000000000000000000000000000000000000000..337d9ed0f9909b0510fb11258e7a4edc4432c15c
Binary files /dev/null and b/css/images/ui-bg_diagonals-thick_20_666666_40x40.png differ
diff --git a/css/images/ui-bg_flat_0_aaaaaa_40x100.png b/css/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644
index 0000000000000000000000000000000000000000..b8d4e42a7e7b16d4a16c3b5b736517f41145f722
Binary files /dev/null and b/css/images/ui-bg_flat_0_aaaaaa_40x100.png differ
diff --git a/css/images/ui-bg_flat_10_000000_40x100.png b/css/images/ui-bg_flat_10_000000_40x100.png
new file mode 100644
index 0000000000000000000000000000000000000000..2fd24e203646d56fa3df07b5df3bf8f364f492b2
Binary files /dev/null and b/css/images/ui-bg_flat_10_000000_40x100.png differ
diff --git a/css/images/ui-bg_flat_75_ffffff_40x100.png b/css/images/ui-bg_flat_75_ffffff_40x100.png
new file mode 100644
index 0000000000000000000000000000000000000000..d104ec9fc55b9ace0f300dde5f4b2a8edf547b1c
Binary files /dev/null and b/css/images/ui-bg_flat_75_ffffff_40x100.png differ
diff --git a/css/images/ui-bg_glass_100_f6f6f6_1x400.png b/css/images/ui-bg_glass_100_f6f6f6_1x400.png
new file mode 100644
index 0000000000000000000000000000000000000000..0fccfbcf3243850c80947e1002f035601fc2228b
Binary files /dev/null and b/css/images/ui-bg_glass_100_f6f6f6_1x400.png differ
diff --git a/css/images/ui-bg_glass_100_fdf5ce_1x400.png b/css/images/ui-bg_glass_100_fdf5ce_1x400.png
new file mode 100644
index 0000000000000000000000000000000000000000..d7899969c45c69c8cd8bce58571c13e43d352c3d
Binary files /dev/null and b/css/images/ui-bg_glass_100_fdf5ce_1x400.png differ
diff --git a/css/images/ui-bg_glass_55_fbf9ee_1x400.png b/css/images/ui-bg_glass_55_fbf9ee_1x400.png
new file mode 100644
index 0000000000000000000000000000000000000000..9580d20e1112f6ba320fde6b6c5f11e897866d32
Binary files /dev/null and b/css/images/ui-bg_glass_55_fbf9ee_1x400.png differ
diff --git a/css/images/ui-bg_glass_65_ffffff_1x400.png b/css/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644
index 0000000000000000000000000000000000000000..2eb7240cc1894737a632ec476a8c341e26f5dee3
Binary files /dev/null and b/css/images/ui-bg_glass_65_ffffff_1x400.png differ
diff --git a/css/images/ui-bg_glass_75_dadada_1x400.png b/css/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100644
index 0000000000000000000000000000000000000000..ead19f215a8b1b4aac5daae187f36ea985ce252a
Binary files /dev/null and b/css/images/ui-bg_glass_75_dadada_1x400.png differ
diff --git a/css/images/ui-bg_glass_75_e6e6e6_1x400.png b/css/images/ui-bg_glass_75_e6e6e6_1x400.png
new file mode 100644
index 0000000000000000000000000000000000000000..e1a4e788533e86847c13e28ca1120c7ca753b370
Binary files /dev/null and b/css/images/ui-bg_glass_75_e6e6e6_1x400.png differ
diff --git a/css/images/ui-bg_glass_95_fef1ec_1x400.png b/css/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644
index 0000000000000000000000000000000000000000..97592ae9b2660fd6addb50f948039c841e62fcdc
Binary files /dev/null and b/css/images/ui-bg_glass_95_fef1ec_1x400.png differ
diff --git a/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png b/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png
new file mode 100644
index 0000000000000000000000000000000000000000..06a7321e28f17b231118249038797cd71549fdaa
Binary files /dev/null and b/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png differ
diff --git a/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png b/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
new file mode 100644
index 0000000000000000000000000000000000000000..256154537205de6fed50fafb52e41cfbc5282d03
Binary files /dev/null and b/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png differ
diff --git a/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png
new file mode 100644
index 0000000000000000000000000000000000000000..4de437c8038ab4fcf5bc7f2d0bf7530127567041
Binary files /dev/null and b/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png differ
diff --git a/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png b/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png
new file mode 100644
index 0000000000000000000000000000000000000000..367be20d6d6359689a715e9d10ef0bbc251a97b3
Binary files /dev/null and b/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png differ
diff --git a/css/images/ui-icons_222222_256x240.png b/css/images/ui-icons_222222_256x240.png
new file mode 100644
index 0000000000000000000000000000000000000000..e9c8e16ac5e7f61c843fbac290ce30c5de7e40b6
Binary files /dev/null and b/css/images/ui-icons_222222_256x240.png differ
diff --git a/css/images/ui-icons_228ef1_256x240.png b/css/images/ui-icons_228ef1_256x240.png
new file mode 100644
index 0000000000000000000000000000000000000000..0c554acbc625ea41123a7faea547a5696171fd29
Binary files /dev/null and b/css/images/ui-icons_228ef1_256x240.png differ
diff --git a/css/images/ui-icons_2e83ff_256x240.png b/css/images/ui-icons_2e83ff_256x240.png
new file mode 100644
index 0000000000000000000000000000000000000000..f2bf8388370920783b94285cb75827ce4b4cc1c5
Binary files /dev/null and b/css/images/ui-icons_2e83ff_256x240.png differ
diff --git a/css/images/ui-icons_454545_256x240.png b/css/images/ui-icons_454545_256x240.png
new file mode 100644
index 0000000000000000000000000000000000000000..d6169e8bf9389ab9b5b7d2c6f0c5fe3e4d363105
Binary files /dev/null and b/css/images/ui-icons_454545_256x240.png differ
diff --git a/css/images/ui-icons_888888_256x240.png b/css/images/ui-icons_888888_256x240.png
new file mode 100644
index 0000000000000000000000000000000000000000..d3e6e02a03d4cfdc6a2114f736aa57e8a898b98b
Binary files /dev/null and b/css/images/ui-icons_888888_256x240.png differ
diff --git a/css/images/ui-icons_cd0a0a_256x240.png b/css/images/ui-icons_cd0a0a_256x240.png
new file mode 100644
index 0000000000000000000000000000000000000000..49370189231d006600b0f0c2967cad1583eba634
Binary files /dev/null and b/css/images/ui-icons_cd0a0a_256x240.png differ
diff --git a/css/images/ui-icons_ef8c08_256x240.png b/css/images/ui-icons_ef8c08_256x240.png
new file mode 100644
index 0000000000000000000000000000000000000000..d76d10a8392e995c353b537e786f2bfdb5d2dbc4
Binary files /dev/null and b/css/images/ui-icons_ef8c08_256x240.png differ
diff --git a/css/images/ui-icons_ffd27a_256x240.png b/css/images/ui-icons_ffd27a_256x240.png
new file mode 100644
index 0000000000000000000000000000000000000000..5e9d27a7247427b7ace97779e10105260e1c3bb8
Binary files /dev/null and b/css/images/ui-icons_ffd27a_256x240.png differ
diff --git a/css/images/ui-icons_ffffff_256x240.png b/css/images/ui-icons_ffffff_256x240.png
new file mode 100644
index 0000000000000000000000000000000000000000..cd6c26561dcce4ed91d3f9d6f98b6bf9feb03847
Binary files /dev/null and b/css/images/ui-icons_ffffff_256x240.png differ
diff --git a/css/jquery.ui.css b/css/jquery.ui.css
new file mode 100644
index 0000000000000000000000000000000000000000..b1e84a014c27af882cb70a2222d389abdd21f2fc
--- /dev/null
+++ b/css/jquery.ui.css
@@ -0,0 +1,1225 @@
+/*! jQuery UI - v1.11.4 - 2015-03-11
+* http://jqueryui.com
+* Includes: core.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, draggable.css, menu.css, progressbar.css, resizable.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden {
+	display: none;
+}
+.ui-helper-hidden-accessible {
+	border: 0;
+	clip: rect(0 0 0 0);
+	height: 1px;
+	margin: -1px;
+	overflow: hidden;
+	padding: 0;
+	position: absolute;
+	width: 1px;
+}
+.ui-helper-reset {
+	margin: 0;
+	padding: 0;
+	border: 0;
+	outline: 0;
+	line-height: 1.3;
+	text-decoration: none;
+	font-size: 100%;
+	list-style: none;
+}
+.ui-helper-clearfix:before,
+.ui-helper-clearfix:after {
+	content: "";
+	display: table;
+	border-collapse: collapse;
+}
+.ui-helper-clearfix:after {
+	clear: both;
+}
+.ui-helper-clearfix {
+	min-height: 0; /* support: IE7 */
+}
+.ui-helper-zfix {
+	width: 100%;
+	height: 100%;
+	top: 0;
+	left: 0;
+	position: absolute;
+	opacity: 0;
+	filter:Alpha(Opacity=0); /* support: IE8 */
+}
+
+.ui-front {
+	z-index: 100;
+}
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled {
+	cursor: default !important;
+}
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon {
+	display: block;
+	text-indent: -99999px;
+	overflow: hidden;
+	background-repeat: no-repeat;
+}
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay {
+	position: fixed;
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+}
+.ui-accordion .ui-accordion-header {
+	display: block;
+	cursor: pointer;
+	position: relative;
+	margin: 2px 0 0 0;
+	padding: .5em .5em .5em .7em;
+	min-height: 0; /* support: IE7 */
+	font-size: 100%;
+}
+.ui-accordion .ui-accordion-icons {
+	padding-left: 2.2em;
+}
+.ui-accordion .ui-accordion-icons .ui-accordion-icons {
+	padding-left: 2.2em;
+}
+.ui-accordion .ui-accordion-header .ui-accordion-header-icon {
+	position: absolute;
+	left: .5em;
+	top: 50%;
+	margin-top: -8px;
+}
+.ui-accordion .ui-accordion-content {
+	padding: 1em 2.2em;
+	border-top: 0;
+	overflow: auto;
+}
+.ui-autocomplete {
+	position: absolute;
+	top: 0;
+	left: 0;
+	cursor: default;
+}
+.ui-button {
+	display: inline-block;
+	position: relative;
+	padding: 0;
+	line-height: normal;
+	margin-right: .1em;
+	cursor: pointer;
+	vertical-align: middle;
+	text-align: center;
+	overflow: visible; /* removes extra width in IE */
+}
+.ui-button,
+.ui-button:link,
+.ui-button:visited,
+.ui-button:hover,
+.ui-button:active {
+	text-decoration: none;
+}
+/* to make room for the icon, a width needs to be set here */
+.ui-button-icon-only {
+	width: 2.2em;
+}
+/* button elements seem to need a little more width */
+button.ui-button-icon-only {
+	width: 2.4em;
+}
+.ui-button-icons-only {
+	width: 3.4em;
+}
+button.ui-button-icons-only {
+	width: 3.7em;
+}
+
+/* button text element */
+.ui-button .ui-button-text {
+	display: block;
+	line-height: normal;
+}
+.ui-button-text-only .ui-button-text {
+	padding: .4em 1em;
+}
+.ui-button-icon-only .ui-button-text,
+.ui-button-icons-only .ui-button-text {
+	padding: .4em;
+	text-indent: -9999999px;
+}
+.ui-button-text-icon-primary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+	padding: .4em 1em .4em 2.1em;
+}
+.ui-button-text-icon-secondary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+	padding: .4em 2.1em .4em 1em;
+}
+.ui-button-text-icons .ui-button-text {
+	padding-left: 2.1em;
+	padding-right: 2.1em;
+}
+/* no icon support for input elements, provide padding by default */
+input.ui-button {
+	padding: .4em 1em;
+}
+
+/* button icon element(s) */
+.ui-button-icon-only .ui-icon,
+.ui-button-text-icon-primary .ui-icon,
+.ui-button-text-icon-secondary .ui-icon,
+.ui-button-text-icons .ui-icon,
+.ui-button-icons-only .ui-icon {
+	position: absolute;
+	top: 50%;
+	margin-top: -8px;
+}
+.ui-button-icon-only .ui-icon {
+	left: 50%;
+	margin-left: -8px;
+}
+.ui-button-text-icon-primary .ui-button-icon-primary,
+.ui-button-text-icons .ui-button-icon-primary,
+.ui-button-icons-only .ui-button-icon-primary {
+	left: .5em;
+}
+.ui-button-text-icon-secondary .ui-button-icon-secondary,
+.ui-button-text-icons .ui-button-icon-secondary,
+.ui-button-icons-only .ui-button-icon-secondary {
+	right: .5em;
+}
+
+/* button sets */
+.ui-buttonset {
+	margin-right: 7px;
+}
+.ui-buttonset .ui-button {
+	margin-left: 0;
+	margin-right: -.3em;
+}
+
+/* workarounds */
+/* reset extra padding in Firefox, see h5bp.com/l */
+input.ui-button::-moz-focus-inner,
+button.ui-button::-moz-focus-inner {
+	border: 0;
+	padding: 0;
+}
+.ui-datepicker {
+	width: 17em;
+	padding: .2em .2em 0;
+	display: none;
+}
+.ui-datepicker .ui-datepicker-header {
+	position: relative;
+	padding: .2em 0;
+}
+.ui-datepicker .ui-datepicker-prev,
+.ui-datepicker .ui-datepicker-next {
+	position: absolute;
+	top: 2px;
+	width: 1.8em;
+	height: 1.8em;
+}
+.ui-datepicker .ui-datepicker-prev-hover,
+.ui-datepicker .ui-datepicker-next-hover {
+	top: 1px;
+}
+.ui-datepicker .ui-datepicker-prev {
+	left: 2px;
+}
+.ui-datepicker .ui-datepicker-next {
+	right: 2px;
+}
+.ui-datepicker .ui-datepicker-prev-hover {
+	left: 1px;
+}
+.ui-datepicker .ui-datepicker-next-hover {
+	right: 1px;
+}
+.ui-datepicker .ui-datepicker-prev span,
+.ui-datepicker .ui-datepicker-next span {
+	display: block;
+	position: absolute;
+	left: 50%;
+	margin-left: -8px;
+	top: 50%;
+	margin-top: -8px;
+}
+.ui-datepicker .ui-datepicker-title {
+	margin: 0 2.3em;
+	line-height: 1.8em;
+	text-align: center;
+}
+.ui-datepicker .ui-datepicker-title select {
+	font-size: 1em;
+	margin: 1px 0;
+}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year {
+	width: 45%;
+}
+.ui-datepicker table {
+	width: 100%;
+	font-size: .9em;
+	border-collapse: collapse;
+	margin: 0 0 .4em;
+}
+.ui-datepicker th {
+	padding: .7em .3em;
+	text-align: center;
+	font-weight: bold;
+	border: 0;
+}
+.ui-datepicker td {
+	border: 0;
+	padding: 1px;
+}
+.ui-datepicker td span,
+.ui-datepicker td a {
+	display: block;
+	padding: .2em;
+	text-align: right;
+	text-decoration: none;
+}
+.ui-datepicker .ui-datepicker-buttonpane {
+	background-image: none;
+	margin: .7em 0 0 0;
+	padding: 0 .2em;
+	border-left: 0;
+	border-right: 0;
+	border-bottom: 0;
+}
+.ui-datepicker .ui-datepicker-buttonpane button {
+	float: right;
+	margin: .5em .2em .4em;
+	cursor: pointer;
+	padding: .2em .6em .3em .6em;
+	width: auto;
+	overflow: visible;
+}
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
+	float: left;
+}
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi {
+	width: auto;
+}
+.ui-datepicker-multi .ui-datepicker-group {
+	float: left;
+}
+.ui-datepicker-multi .ui-datepicker-group table {
+	width: 95%;
+	margin: 0 auto .4em;
+}
+.ui-datepicker-multi-2 .ui-datepicker-group {
+	width: 50%;
+}
+.ui-datepicker-multi-3 .ui-datepicker-group {
+	width: 33.3%;
+}
+.ui-datepicker-multi-4 .ui-datepicker-group {
+	width: 25%;
+}
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
+	border-left-width: 0;
+}
+.ui-datepicker-multi .ui-datepicker-buttonpane {
+	clear: left;
+}
+.ui-datepicker-row-break {
+	clear: both;
+	width: 100%;
+	font-size: 0;
+}
+
+/* RTL support */
+.ui-datepicker-rtl {
+	direction: rtl;
+}
+.ui-datepicker-rtl .ui-datepicker-prev {
+	right: 2px;
+	left: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-next {
+	left: 2px;
+	right: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-prev:hover {
+	right: 1px;
+	left: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-next:hover {
+	left: 1px;
+	right: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane {
+	clear: right;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane button {
+	float: left;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
+.ui-datepicker-rtl .ui-datepicker-group {
+	float: right;
+}
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
+	border-right-width: 0;
+	border-left-width: 1px;
+}
+.ui-dialog {
+	overflow: hidden;
+	position: absolute;
+	top: 0;
+	left: 0;
+	padding: .2em;
+	outline: 0;
+}
+.ui-dialog .ui-dialog-titlebar {
+	padding: .4em 1em;
+	position: relative;
+}
+.ui-dialog .ui-dialog-title {
+	float: left;
+	margin: .1em 0;
+	white-space: nowrap;
+	width: 90%;
+	overflow: hidden;
+	text-overflow: ellipsis;
+}
+.ui-dialog .ui-dialog-titlebar-close {
+	position: absolute;
+	right: .3em;
+	top: 50%;
+	width: 20px;
+	margin: -10px 0 0 0;
+	padding: 1px;
+	height: 20px;
+}
+.ui-dialog .ui-dialog-content {
+	position: relative;
+	border: 0;
+	padding: .5em 1em;
+	background: none;
+	overflow: auto;
+}
+.ui-dialog .ui-dialog-buttonpane {
+	text-align: left;
+	border-width: 1px 0 0 0;
+	background-image: none;
+	margin-top: .5em;
+	padding: .3em 1em .5em .4em;
+}
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
+	float: right;
+}
+.ui-dialog .ui-dialog-buttonpane button {
+	margin: .5em .4em .5em 0;
+	cursor: pointer;
+}
+.ui-dialog .ui-resizable-se {
+	width: 12px;
+	height: 12px;
+	right: -5px;
+	bottom: -5px;
+	background-position: 16px 16px;
+}
+.ui-draggable .ui-dialog-titlebar {
+	cursor: move;
+}
+.ui-draggable-handle {
+	-ms-touch-action: none;
+	touch-action: none;
+}
+.ui-menu {
+	list-style: none;
+	padding: 0;
+	margin: 0;
+	display: block;
+	outline: none;
+}
+.ui-menu .ui-menu {
+	position: absolute;
+}
+.ui-menu .ui-menu-item {
+	position: relative;
+	margin: 0;
+	padding: 3px 1em 3px .4em;
+	cursor: pointer;
+	min-height: 0; /* support: IE7 */
+	/* support: IE10, see #8844 */
+	list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
+}
+.ui-menu .ui-menu-divider {
+	margin: 5px 0;
+	height: 0;
+	font-size: 0;
+	line-height: 0;
+	border-width: 1px 0 0 0;
+}
+.ui-menu .ui-state-focus,
+.ui-menu .ui-state-active {
+	margin: -1px;
+}
+
+/* icon support */
+.ui-menu-icons {
+	position: relative;
+}
+.ui-menu-icons .ui-menu-item {
+	padding-left: 2em;
+}
+
+/* left-aligned */
+.ui-menu .ui-icon {
+	position: absolute;
+	top: 0;
+	bottom: 0;
+	left: .2em;
+	margin: auto 0;
+}
+
+/* right-aligned */
+.ui-menu .ui-menu-icon {
+	left: auto;
+	right: 0;
+}
+.ui-progressbar {
+	height: 2em;
+	text-align: left;
+	overflow: hidden;
+}
+.ui-progressbar .ui-progressbar-value {
+	margin: -1px;
+	height: 100%;
+}
+.ui-progressbar .ui-progressbar-overlay {
+	background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");
+	height: 100%;
+	filter: alpha(opacity=25); /* support: IE8 */
+	opacity: 0.25;
+}
+.ui-progressbar-indeterminate .ui-progressbar-value {
+	background-image: none;
+}
+.ui-resizable {
+	position: relative;
+}
+.ui-resizable-handle {
+	position: absolute;
+	font-size: 0.1px;
+	display: block;
+	-ms-touch-action: none;
+	touch-action: none;
+}
+.ui-resizable-disabled .ui-resizable-handle,
+.ui-resizable-autohide .ui-resizable-handle {
+	display: none;
+}
+.ui-resizable-n {
+	cursor: n-resize;
+	height: 7px;
+	width: 100%;
+	top: -5px;
+	left: 0;
+}
+.ui-resizable-s {
+	cursor: s-resize;
+	height: 7px;
+	width: 100%;
+	bottom: -5px;
+	left: 0;
+}
+.ui-resizable-e {
+	cursor: e-resize;
+	width: 7px;
+	right: -5px;
+	top: 0;
+	height: 100%;
+}
+.ui-resizable-w {
+	cursor: w-resize;
+	width: 7px;
+	left: -5px;
+	top: 0;
+	height: 100%;
+}
+.ui-resizable-se {
+	cursor: se-resize;
+	width: 12px;
+	height: 12px;
+	right: 1px;
+	bottom: 1px;
+}
+.ui-resizable-sw {
+	cursor: sw-resize;
+	width: 9px;
+	height: 9px;
+	left: -5px;
+	bottom: -5px;
+}
+.ui-resizable-nw {
+	cursor: nw-resize;
+	width: 9px;
+	height: 9px;
+	left: -5px;
+	top: -5px;
+}
+.ui-resizable-ne {
+	cursor: ne-resize;
+	width: 9px;
+	height: 9px;
+	right: -5px;
+	top: -5px;
+}
+.ui-selectable {
+	-ms-touch-action: none;
+	touch-action: none;
+}
+.ui-selectable-helper {
+	position: absolute;
+	z-index: 100;
+	border: 1px dotted black;
+}
+.ui-selectmenu-menu {
+	padding: 0;
+	margin: 0;
+	position: absolute;
+	top: 0;
+	left: 0;
+	display: none;
+}
+.ui-selectmenu-menu .ui-menu {
+	overflow: auto;
+	/* Support: IE7 */
+	overflow-x: hidden;
+	padding-bottom: 1px;
+}
+.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
+	font-size: 1em;
+	font-weight: bold;
+	line-height: 1.5;
+	padding: 2px 0.4em;
+	margin: 0.5em 0 0 0;
+	height: auto;
+	border: 0;
+}
+.ui-selectmenu-open {
+	display: block;
+}
+.ui-selectmenu-button {
+	display: inline-block;
+	overflow: hidden;
+	position: relative;
+	text-decoration: none;
+	cursor: pointer;
+}
+.ui-selectmenu-button span.ui-icon {
+	right: 0.5em;
+	left: auto;
+	margin-top: -8px;
+	position: absolute;
+	top: 50%;
+}
+.ui-selectmenu-button span.ui-selectmenu-text {
+	text-align: left;
+	padding: 0.4em 2.1em 0.4em 1em;
+	display: block;
+	line-height: 1.4;
+	overflow: hidden;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+}
+.ui-slider {
+	position: relative;
+	text-align: left;
+}
+.ui-slider .ui-slider-handle {
+	position: absolute;
+	z-index: 2;
+	width: 1.2em;
+	height: 1.2em;
+	cursor: default;
+	-ms-touch-action: none;
+	touch-action: none;
+}
+.ui-slider .ui-slider-range {
+	position: absolute;
+	z-index: 1;
+	font-size: .7em;
+	display: block;
+	border: 0;
+	background-position: 0 0;
+}
+
+/* support: IE8 - See #6727 */
+.ui-slider.ui-state-disabled .ui-slider-handle,
+.ui-slider.ui-state-disabled .ui-slider-range {
+	filter: inherit;
+}
+
+.ui-slider-horizontal {
+	height: .8em;
+}
+.ui-slider-horizontal .ui-slider-handle {
+	top: -.3em;
+	margin-left: -.6em;
+}
+.ui-slider-horizontal .ui-slider-range {
+	top: 0;
+	height: 100%;
+}
+.ui-slider-horizontal .ui-slider-range-min {
+	left: 0;
+}
+.ui-slider-horizontal .ui-slider-range-max {
+	right: 0;
+}
+
+.ui-slider-vertical {
+	width: .8em;
+	height: 100px;
+}
+.ui-slider-vertical .ui-slider-handle {
+	left: -.3em;
+	margin-left: 0;
+	margin-bottom: -.6em;
+}
+.ui-slider-vertical .ui-slider-range {
+	left: 0;
+	width: 100%;
+}
+.ui-slider-vertical .ui-slider-range-min {
+	bottom: 0;
+}
+.ui-slider-vertical .ui-slider-range-max {
+	top: 0;
+}
+.ui-sortable-handle {
+	-ms-touch-action: none;
+	touch-action: none;
+}
+.ui-spinner {
+	position: relative;
+	display: inline-block;
+	overflow: hidden;
+	padding: 0;
+	vertical-align: middle;
+}
+.ui-spinner-input {
+	border: none;
+	background: none;
+	color: inherit;
+	padding: 0;
+	margin: .2em 0;
+	vertical-align: middle;
+	margin-left: .4em;
+	margin-right: 22px;
+}
+.ui-spinner-button {
+	width: 16px;
+	height: 50%;
+	font-size: .5em;
+	padding: 0;
+	margin: 0;
+	text-align: center;
+	position: absolute;
+	cursor: default;
+	display: block;
+	overflow: hidden;
+	right: 0;
+}
+/* more specificity required here to override default borders */
+.ui-spinner a.ui-spinner-button {
+	border-top: none;
+	border-bottom: none;
+	border-right: none;
+}
+/* vertically center icon */
+.ui-spinner .ui-icon {
+	position: absolute;
+	margin-top: -8px;
+	top: 50%;
+	left: 0;
+}
+.ui-spinner-up {
+	top: 0;
+}
+.ui-spinner-down {
+	bottom: 0;
+}
+
+/* TR overrides */
+.ui-spinner .ui-icon-triangle-1-s {
+	/* need to fix icons sprite */
+	background-position: -65px -16px;
+}
+.ui-tabs {
+	position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+	padding: .2em;
+}
+.ui-tabs .ui-tabs-nav {
+	margin: 0;
+	padding: .2em .2em 0;
+}
+.ui-tabs .ui-tabs-nav li {
+	list-style: none;
+	float: left;
+	position: relative;
+	top: 0;
+	margin: 1px .2em 0 0;
+	border-bottom-width: 0;
+	padding: 0;
+	white-space: nowrap;
+}
+.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
+	float: left;
+	padding: .5em 1em;
+	text-decoration: none;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active {
+	margin-bottom: -1px;
+	padding-bottom: 1px;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
+.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
+.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
+	cursor: text;
+}
+.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
+	cursor: pointer;
+}
+.ui-tabs .ui-tabs-panel {
+	display: block;
+	border-width: 0;
+	padding: 1em 1.4em;
+	background: none;
+}
+.ui-tooltip {
+	padding: 8px;
+	position: absolute;
+	z-index: 9999;
+	max-width: 300px;
+	-webkit-box-shadow: 0 0 5px #aaa;
+	box-shadow: 0 0 5px #aaa;
+}
+body .ui-tooltip {
+	border-width: 2px;
+}
+
+/* Component containers
+----------------------------------*/
+.ui-widget {
+	font-family: Verdana,Arial,sans-serif;
+	font-size: 2.5em;
+}
+.ui-widget .ui-widget {
+	font-size: 1em;
+}
+.ui-widget input,
+.ui-widget select,
+.ui-widget textarea,
+.ui-widget button {
+	font-family: Verdana,Arial,sans-serif;
+	font-size: 1em;
+}
+.ui-widget-content {
+	border: 1px solid #aaaaaa;
+	background: #ffffff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x;
+	color: #222222;
+}
+.ui-widget-content a {
+	color: #222222;
+}
+.ui-widget-header {
+	border: 1px solid #aaaaaa;
+	background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;
+	color: #222222;
+	font-weight: bold;
+}
+.ui-widget-header a {
+	color: #222222;
+}
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default,
+.ui-widget-content .ui-state-default,
+.ui-widget-header .ui-state-default {
+	border: 1px solid #d3d3d3;
+	background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
+	font-weight: normal;
+	color: #555555;
+}
+.ui-state-default a,
+.ui-state-default a:link,
+.ui-state-default a:visited {
+	color: #555555;
+	text-decoration: none;
+}
+.ui-state-hover,
+.ui-widget-content .ui-state-hover,
+.ui-widget-header .ui-state-hover,
+.ui-state-focus,
+.ui-widget-content .ui-state-focus,
+.ui-widget-header .ui-state-focus {
+	border: 1px solid #999999;
+	background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;
+	font-weight: normal;
+	color: #212121;
+}
+.ui-state-hover a,
+.ui-state-hover a:hover,
+.ui-state-hover a:link,
+.ui-state-hover a:visited,
+.ui-state-focus a,
+.ui-state-focus a:hover,
+.ui-state-focus a:link,
+.ui-state-focus a:visited {
+	color: #212121;
+	text-decoration: none;
+}
+.ui-state-active,
+.ui-widget-content .ui-state-active,
+.ui-widget-header .ui-state-active {
+	border: 1px solid #aaaaaa;
+	background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
+	font-weight: normal;
+	color: #212121;
+}
+.ui-state-active a,
+.ui-state-active a:link,
+.ui-state-active a:visited {
+	color: #212121;
+	text-decoration: none;
+}
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight,
+.ui-widget-content .ui-state-highlight,
+.ui-widget-header .ui-state-highlight {
+	border: 1px solid #fcefa1;
+	background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;
+	color: #363636;
+}
+.ui-state-highlight a,
+.ui-widget-content .ui-state-highlight a,
+.ui-widget-header .ui-state-highlight a {
+	color: #363636;
+}
+.ui-state-error,
+.ui-widget-content .ui-state-error,
+.ui-widget-header .ui-state-error {
+	border: 1px solid #cd0a0a;
+	background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;
+	color: #cd0a0a;
+}
+.ui-state-error a,
+.ui-widget-content .ui-state-error a,
+.ui-widget-header .ui-state-error a {
+	color: #cd0a0a;
+}
+.ui-state-error-text,
+.ui-widget-content .ui-state-error-text,
+.ui-widget-header .ui-state-error-text {
+	color: #cd0a0a;
+}
+.ui-priority-primary,
+.ui-widget-content .ui-priority-primary,
+.ui-widget-header .ui-priority-primary {
+	font-weight: bold;
+}
+.ui-priority-secondary,
+.ui-widget-content .ui-priority-secondary,
+.ui-widget-header .ui-priority-secondary {
+	opacity: .7;
+	filter:Alpha(Opacity=70); /* support: IE8 */
+	font-weight: normal;
+}
+.ui-state-disabled,
+.ui-widget-content .ui-state-disabled,
+.ui-widget-header .ui-state-disabled {
+	opacity: .35;
+	filter:Alpha(Opacity=35); /* support: IE8 */
+	background-image: none;
+}
+.ui-state-disabled .ui-icon {
+	filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
+}
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon {
+	width: 16px;
+	height: 16px;
+}
+.ui-icon,
+.ui-widget-content .ui-icon {
+	background-image: url("images/ui-icons_222222_256x240.png");
+}
+.ui-widget-header .ui-icon {
+	background-image: url("images/ui-icons_222222_256x240.png");
+}
+.ui-state-default .ui-icon {
+	background-image: url("images/ui-icons_888888_256x240.png");
+}
+.ui-state-hover .ui-icon,
+.ui-state-focus .ui-icon {
+	background-image: url("images/ui-icons_454545_256x240.png");
+}
+.ui-state-active .ui-icon {
+	background-image: url("images/ui-icons_454545_256x240.png");
+}
+.ui-state-highlight .ui-icon {
+	background-image: url("images/ui-icons_2e83ff_256x240.png");
+}
+.ui-state-error .ui-icon,
+.ui-state-error-text .ui-icon {
+	background-image: url("images/ui-icons_cd0a0a_256x240.png");
+}
+
+/* positioning */
+.ui-icon-blank { background-position: 16px 16px; }
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-on { background-position: -96px -144px; }
+.ui-icon-radio-off { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-left,
+.ui-corner-tl {
+	border-top-left-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-right,
+.ui-corner-tr {
+	border-top-right-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-left,
+.ui-corner-bl {
+	border-bottom-left-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-right,
+.ui-corner-br {
+	border-bottom-right-radius: 4px;
+}
+
+/* Overlays */
+.ui-widget-overlay {
+	background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
+	opacity: .3;
+	filter: Alpha(Opacity=30); /* support: IE8 */
+}
+.ui-widget-shadow {
+	margin: -8px 0 0 -8px;
+	padding: 8px;
+	background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
+	opacity: .3;
+	filter: Alpha(Opacity=30); /* support: IE8 */
+	border-radius: 8px;
+}
\ No newline at end of file
diff --git a/css/marquee.css b/css/marquee.less
similarity index 100%
rename from css/marquee.css
rename to css/marquee.less
diff --git a/index.html b/index.html
index 1296b72b14b98e14749e7c936b00cd5be8df5d94..690de0f9b519fc4068a866c688a4d9c64e65b32f 100755
--- a/index.html
+++ b/index.html
@@ -1,43 +1,30 @@
 <!DOCTYPE html>
 <html>
-  <head>
+    <head>
     <title>Infoboard</title>
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <link href="favicon.png" type="image/x-icon" rel="icon">
-    <link rel="stylesheet" href="css/font.css">
-    <link rel="stylesheet" href="css/design.css">
-    <link rel="stylesheet" href="css/marquee.css">
+    <link href="favicon.png" type="image/x-icon" rel="icon"/>
+    <link rel="stylesheet" href="css/font.css"/>
+    <link rel="stylesheet" href="css/design.less"/>
+    <link rel="stylesheet" href="css/marquee.less"/>
+    <link rel="stylesheet" href="css/jquery.ui.css"/>
     <script type="text/javascript" src="js/jquery-2.1.4.min.js"></script>
     <script type="text/javascript" src="js/jquery-ui.min.js"></script>
-    <script type="text/javascript" src="js/jquery.jcookie.min.js"></script>
     <script type="text/javascript" src="js/marquee.js"></script>
-    <script type="text/javascript" src="js/panelAPI.js"></script>
+    <script type="text/javascript" src="js/layoutloader.js"></script>
     <script type="text/javascript" src="js/webfontloader.js"></script>
-
-    <script type="text/javascript">
-    //<![CDATA[
-    $(document).ready(function(){
-    	window.fontsReady = false;
-	WebFont.load( {
-			custom	: {
-				families	: ['time-medium', 'time-fat', 'vrr'],
-				urls		: ['css/font.css']
-			},
-			active	: function() {
-				window.fontsReady = true;
-			}
-		});	
-
-        var layoutname=$.jCookie("layout");
-        layoutname=(typeof(layoutname)=="undefined" ? "default" : layoutname);
-      layout.loadLayout(layoutname);
-    });
-    //]]>
-    </script>
+    <script type="text/javascript" src="js/starter.js"></script>
   </head>
   <body>
     <div data-container="main">
+        <noscript>
+            <div data-container="panel" style="
+                color: white;
+                text-shadow: black 10px 0px 0px;
+                font-size: 40pt;
+            ">Diese Seite benötigt JavaScript!</div>
+        </noscript>
     </div>
   </body>
 </html>
diff --git a/js/fontloader.js b/js/fontloader.js
new file mode 100644
index 0000000000000000000000000000000000000000..b507892d16200ca99f191e6c7bb7673744af8878
--- /dev/null
+++ b/js/fontloader.js
@@ -0,0 +1,6 @@
+/**
+ * Created by tilman on 02.10.15.
+ */
+fontloader = {};
+
+fontloader
\ No newline at end of file
diff --git a/js/jquery.jcookie.min.js b/js/jquery.jcookie.min.js
deleted file mode 100755
index 29d709d3ca672c7e923734434b8a07cd6f86bfc1..0000000000000000000000000000000000000000
--- a/js/jquery.jcookie.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/** https://github.com/martinkr/jCookie - Copyright (c) 2008-2011 Martin Krause - Dual licensed under the MIT and GPL licenses. */
-jQuery.jCookie=function(i,b,l,j){if(!navigator.cookieEnabled){return false}var j=j||{};if(typeof(arguments[0])!=="string"&&arguments.length===1){j=arguments[0];i=j.name;b=j.value;l=j.expires}i=encodeURI(i);if(b&&(typeof(b)!=="number"&&typeof(b)!=="string"&&b!==null)){return false}var e=j.path?"; path="+j.path:"";var f=j.domain?"; domain="+j.domain:"";var d=j.secure?"; secure":"";var g="";if(b||(b===null&&arguments.length==2)){l=(l===null||(b===null&&arguments.length==2))?-1:l;if(typeof(l)==="number"&&l!="session"&&l!==undefined){var k=new Date();k.setTime(k.getTime()+(l*24*60*60*1000));g=["; expires=",k.toGMTString()].join("")}document.cookie=[i,"=",encodeURI(b),g,f,e,d].join("");return true}if(!b&&typeof(arguments[0])==="string"&&arguments.length==1&&document.cookie&&document.cookie.length){var a=document.cookie.split(";");var h=a.length;while(h--){var c=a[h].split("=");if(jQuery.trim(c[0])===i){return decodeURI(c[1])}}return undefined}if(!document.cookie||!document.cookie.length){return undefined}return false};
\ No newline at end of file
diff --git a/js/panelAPI.js b/js/layoutloader.js
similarity index 82%
rename from js/panelAPI.js
rename to js/layoutloader.js
index 056d24d851b5700c35bec08879da4891ab49785a..5e7a9540e184621e5cf6d7dee0e1770c79debf43 100755
--- a/js/panelAPI.js
+++ b/js/layoutloader.js
@@ -15,6 +15,11 @@ layout.processLayout = function(json, container) {
       layout.processLayout(json.right, cont).css("width",(100.0-json.cut)+"%");
       return cont;
     case "panel":
+
+        if (json.name == "") {
+            layout.error(json);
+        }
+
         var p = $("<div>")
           .attr("data-container","panel")
           .attr("data-template",json.name)
@@ -22,9 +27,8 @@ layout.processLayout = function(json, container) {
         var cont = $("<div>").attr("data-container","panelContainer").append(p);
         $(container).append(cont);
 
-      if (json.name != "") {
         layout.insertTemplate(json.name,p);
-      }
+
 
       return cont;
     default:
@@ -34,11 +38,10 @@ layout.processLayout = function(json, container) {
 }
 
 layout.insertTemplate = function(name, panel) {
-  var tmp = null;
-  for (ti in layout.templates) {
-    if (layout.templates[ti].name == name)
+  for (var tmp in layout.templates) {
+    if (layout.templates[tmp].name == name)
     {
-      layout.templates[ti].panels.push(panel);
+      layout.templates[tmp].panels.push(panel);
       return;
     }
 
@@ -65,10 +68,6 @@ layout.insertTemplate = function(name, panel) {
               doStuff = null;
           }
 
-          if (e.css!=null) {
-            t.css = $("<style>").attr("type","text/css").attr("data-template",t.name).text(e.css);
-            $("body").append(t.css);
-          }
           t.template = $.parseHTML(e.template);
 
           for (p in t.panels) {
@@ -99,14 +98,27 @@ layout.insertTemplate = function(name, panel) {
           layout.error("get fail of template " + n );
         });
 
-      	$.get("style.php?style=" + n, function(k) {
-          console.log("get success of style " + n)
+
+          t.css = $("<link>").attr("rel","stylesheet").attr("href", "panels/" + n + "/style.less").attr("data-template",t.name);
+
+
+          t.css.on("load",function() {
+              console.log("get success of style " + n);
+              e.css= t.css;
+              doMore();
+          });
+
+
+          /*.fail(function() {
+              layout.error("get fail of style " + n);
+          });*/
+
+          $("head").append(t.css);
+      	/*$.get("panels/" + n + "/style.less", function(k) {
           e.css=k;
           doMore();
       	},"text")
-        .fail(function() {
-          layout.error("get fail of style " + n);
-        });
+        */
 
 
         $.get("panels/" + n + "/script.js", function(k){
@@ -146,4 +158,4 @@ layout.error = function(e) {
   console.log("Layout: Error " + e);
 },
 
-layout.templates = [];
+layout.templates = [];
\ No newline at end of file
diff --git a/js/starter.js b/js/starter.js
new file mode 100644
index 0000000000000000000000000000000000000000..8fa0f784ba2783f9d09116764c159f0112398f5f
--- /dev/null
+++ b/js/starter.js
@@ -0,0 +1,18 @@
+$(document).ready(function(){
+    window.fontsReady = false;
+    WebFont.load( {
+        custom	: {
+            families	: ['time-medium', 'time-fat', 'vrr'],
+        },
+        active	: function() {
+            window.fontsReady = true;
+        }
+    });
+
+    var params = location.search.replace('?','').split('&').reduce(function(s,c){var t=c.split('=');s[t[0]]=t[1];return s;},{});
+    var layoutname = (typeof(params.layout)=="undefined" ? "default" : params.layout);
+
+    layout.loadLayout(layoutname);
+});/**
+ * Created by tilman on 30.09.15.
+ */
diff --git a/less/font.php b/less/font.php
new file mode 100644
index 0000000000000000000000000000000000000000..9a48d3f2ba63163a65344ec409eed84261a1056e
--- /dev/null
+++ b/less/font.php
@@ -0,0 +1,78 @@
+<?php
+
+$tmp_dir = "tmp";
+chdir("..");
+
+if (!isset($_GET["name"])) {
+    http_response_code(404);
+    echo "no valid file given";
+    return;
+}
+
+$less_file = $_GET["name"]; //"panels/departure/style.less";
+$debug=isset($_GET["debug"]);
+
+include "config/config.php";
+echo ROOT_DIR;
+
+
+$panel = null;
+
+if ($debug)
+    header("content-type:text/plain;charset=utf8");
+
+
+if (!file_exists($less_file)) {
+    http_response_code(404);
+    echo $less_file . " not found";
+    return;
+}
+
+if (preg_match_all ('/'.'panels\\/((?:[a-z][a-z]+))\\/style\\.less'.'/is', $less_file, $matches))
+{
+    $panel=$matches[1][0];
+}
+
+if ($debug && isset($panel))
+    echo "panel:" . $panel."\n";
+
+$cache_name = "lesscache_".md5($less_file."_".filemtime($less_file)).".css";
+$cache_file = $tmp_dir."/".$cache_name;
+
+if (!file_exists($cache_file)) {
+
+    require("less/Less.php");
+    $options = array( 'compress'=>true );
+    $parser = new Less_Parser($options);
+    $parser->parseFile("css/colors.less");
+
+    try {
+        if (!isset($panel)) {
+            $parser->parseFile($less_file);
+        } else {
+            $parser->parse("
+                    [data-template=$panel] {
+                        @import \"$less_file\";
+                    }", "/panels/$panel");
+        }
+        $content = $parser->getCss();
+    }catch(Exception $e) {
+        http_response_code(500);
+        header("content-type:text/plain;charset=utf8");
+        echo $e->getMessage();
+        return;
+    }
+    file_put_contents($cache_file,$content);;
+}
+
+if ($debug) {
+    echo "cache-name: " . $cache_file . "\n";
+    echo "content:\n";
+    if (!isset($content))
+        echo file_get_contents($cache_file)."\n";
+    else
+        echo $content;
+} else {
+    header("Location: ".ROOT_DIR."/$cache_file");
+}
+
diff --git a/less/less/Cache.php b/less/less/Cache.php
new file mode 100644
index 0000000000000000000000000000000000000000..8c8be39530e88ae28a29f262a0dd74f721fb08ed
--- /dev/null
+++ b/less/less/Cache.php
@@ -0,0 +1,316 @@
+<?php
+
+require_once( dirname(__FILE__).'/Version.php');
+
+/**
+ * Utility for handling the generation and caching of css files
+ *
+ * @package Less
+ * @subpackage cache
+ *
+ */
+class Less_Cache{
+
+	// directory less.php can use for storing data
+	public static $cache_dir	= false;
+
+	// prefix for the storing data
+	public static $prefix		= 'lessphp_';
+
+	// prefix for the storing vars
+	public static $prefix_vars	= 'lessphpvars_';
+
+	// specifies the number of seconds after which data created by less.php will be seen as 'garbage' and potentially cleaned up
+	public static $gc_lifetime	= 604800;
+
+
+	/**
+	 * Save and reuse the results of compiled less files.
+	 * The first call to Get() will generate css and save it.
+	 * Subsequent calls to Get() with the same arguments will return the same css filename
+	 *
+	 * @param array $less_files Array of .less files to compile
+	 * @param array $parser_options Array of compiler options
+	 * @param array $modify_vars Array of variables
+	 * @return string Name of the css file
+	 */
+	public static function Get( $less_files, $parser_options = array(), $modify_vars = array() ){
+
+
+		//check $cache_dir
+		if( isset($parser_options['cache_dir']) ){
+			Less_Cache::$cache_dir = $parser_options['cache_dir'];
+		}
+
+		if( empty(Less_Cache::$cache_dir) ){
+			throw new Exception('cache_dir not set');
+		}
+
+		if( isset($parser_options['prefix']) ){
+			Less_Cache::$prefix = $parser_options['prefix'];
+		}
+
+		if( empty(Less_Cache::$prefix) ){
+			throw new Exception('prefix not set');
+		}
+
+		if( isset($parser_options['prefix_vars']) ){
+			Less_Cache::$prefix_vars = $parser_options['prefix_vars'];
+		}
+
+		if( empty(Less_Cache::$prefix_vars) ){
+			throw new Exception('prefix_vars not set');
+		}
+
+		self::CheckCacheDir();
+		$less_files = (array)$less_files;
+
+
+		//create a file for variables
+		if( !empty($modify_vars) ){
+			$lessvars = Less_Parser::serializeVars($modify_vars);
+			$vars_file = Less_Cache::$cache_dir . Less_Cache::$prefix_vars . sha1($lessvars) . '.less';
+
+			if( !file_exists($vars_file) ){
+				file_put_contents($vars_file, $lessvars);
+			}
+
+			$less_files += array($vars_file => '/');
+		}
+
+
+		// generate name for compiled css file
+		$hash = md5(json_encode($less_files));
+ 		$list_file = Less_Cache::$cache_dir . Less_Cache::$prefix . $hash . '.list';
+
+
+ 		// check cached content
+ 		if( !isset($parser_options['use_cache']) || $parser_options['use_cache'] === true ){
+			if( file_exists($list_file) ){
+
+				self::ListFiles($list_file, $list, $cached_name);
+				$compiled_name = self::CompiledName($list);
+
+				// if $cached_name is the same as the $compiled name, don't regenerate
+				if( !$cached_name || $cached_name === $compiled_name ){
+
+					$output_file = self::OutputFile($compiled_name, $parser_options );
+
+					if( $output_file && file_exists($output_file) ){
+						@touch($list_file);
+						return basename($output_file); // for backwards compatibility, we just return the name of the file
+					}
+				}
+			}
+		}
+
+		$compiled = self::Cache( $less_files, $parser_options );
+		if( !$compiled ){
+			return false;
+		}
+
+		$compiled_name = self::CompiledName( $less_files );
+		$output_file = self::OutputFile($compiled_name, $parser_options );
+
+
+		//save the file list
+		$list = $less_files;
+		$list[] = $compiled_name;
+		$cache = implode("\n",$list);
+		file_put_contents( $list_file, $cache );
+
+
+		//save the css
+		file_put_contents( $output_file, $compiled );
+
+
+		//clean up
+		self::CleanCache();
+
+		return basename($output_file);
+	}
+
+	/**
+	 * Force the compiler to regenerate the cached css file
+	 *
+	 * @param array $less_files Array of .less files to compile
+	 * @param array $parser_options Array of compiler options
+	 * @param array $modify_vars Array of variables
+	 * @return string Name of the css file
+	 */
+	public static function Regen( $less_files, $parser_options = array(), $modify_vars = array() ){
+		$parser_options['use_cache'] = false;
+		return self::Get( $less_files, $parser_options, $modify_vars );
+	}
+
+	public static function Cache( &$less_files, $parser_options = array() ){
+
+
+		// get less.php if it exists
+		$file = dirname(__FILE__) . '/Less.php';
+		if( file_exists($file) && !class_exists('Less_Parser') ){
+			require_once($file);
+		}
+
+		$parser_options['cache_dir'] = Less_Cache::$cache_dir;
+		$parser = new Less_Parser($parser_options);
+
+
+		// combine files
+		foreach($less_files as $file_path => $uri_or_less ){
+
+			//treat as less markup if there are newline characters
+			if( strpos($uri_or_less,"\n") !== false ){
+				$parser->Parse( $uri_or_less );
+				continue;
+			}
+
+			$parser->ParseFile( $file_path, $uri_or_less );
+		}
+
+		$compiled = $parser->getCss();
+
+
+		$less_files = $parser->allParsedFiles();
+
+		return $compiled;
+	}
+
+
+	private static function OutputFile( $compiled_name, $parser_options ){
+
+		//custom output file
+		if( !empty($parser_options['output']) ){
+
+			//relative to cache directory?
+			if( preg_match('#[\\\\/]#',$parser_options['output']) ){
+				return $parser_options['output'];
+			}
+
+			return Less_Cache::$cache_dir.$parser_options['output'];
+		}
+
+		return Less_Cache::$cache_dir.$compiled_name;
+	}
+
+
+	private static function CompiledName( $files ){
+
+		//save the file list
+		$temp = array(Less_Version::cache_version);
+		foreach($files as $file){
+			$temp[] = filemtime($file)."\t".filesize($file)."\t".$file;
+		}
+
+		return Less_Cache::$prefix.sha1(json_encode($temp)).'.css';
+	}
+
+
+	public static function SetCacheDir( $dir ){
+		Less_Cache::$cache_dir = $dir;
+	}
+
+	public static function CheckCacheDir(){
+
+		Less_Cache::$cache_dir = str_replace('\\','/',Less_Cache::$cache_dir);
+		Less_Cache::$cache_dir = rtrim(Less_Cache::$cache_dir,'/').'/';
+
+		if( !file_exists(Less_Cache::$cache_dir) ){
+			if( !mkdir(Less_Cache::$cache_dir) ){
+				throw new Less_Exception_Parser('Less.php cache directory couldn\'t be created: '.Less_Cache::$cache_dir);
+			}
+
+		}elseif( !is_dir(Less_Cache::$cache_dir) ){
+			throw new Less_Exception_Parser('Less.php cache directory doesn\'t exist: '.Less_Cache::$cache_dir);
+
+		}elseif( !is_writable(Less_Cache::$cache_dir) ){
+			throw new Less_Exception_Parser('Less.php cache directory isn\'t writable: '.Less_Cache::$cache_dir);
+
+		}
+
+	}
+
+
+	/**
+	 * Delete unused less.php files
+	 *
+	 */
+	public static function CleanCache(){
+		static $clean = false;
+
+		if( $clean ){
+			return;
+		}
+
+		$files = scandir(Less_Cache::$cache_dir);
+		if( $files ){
+			$check_time = time() - self::$gc_lifetime;
+			foreach($files as $file){
+
+				// don't delete if the file wasn't created with less.php
+				if( strpos($file,Less_Cache::$prefix) !== 0 ){
+					continue;
+				}
+
+				$full_path = Less_Cache::$cache_dir . $file;
+
+				// make sure the file still exists
+				// css files may have already been deleted
+				if( !file_exists($full_path) ){
+					continue;
+				}
+				$mtime = filemtime($full_path);
+
+				// don't delete if it's a relatively new file
+				if( $mtime > $check_time ){
+					continue;
+				}
+
+				$parts = explode('.',$file);
+				$type = array_pop($parts);
+
+
+				// delete css files based on the list files
+				if( $type === 'css' ){
+					continue;
+				}
+
+
+				// delete the list file and associated css file
+				if( $type === 'list' ){
+					self::ListFiles($full_path, $list, $css_file_name);
+					if( $css_file_name ){
+						$css_file = Less_Cache::$cache_dir . $css_file_name;
+						if( file_exists($css_file) ){
+							unlink($css_file);
+						}
+					}
+				}
+
+				unlink($full_path);
+			}
+		}
+
+		$clean = true;
+	}
+
+
+	/**
+	 * Get the list of less files and generated css file from a list file
+	 *
+	 */
+	static function ListFiles($list_file, &$list, &$css_file_name ){
+
+		$list = explode("\n",file_get_contents($list_file));
+
+		//pop the cached name that should match $compiled_name
+		$css_file_name = array_pop($list);
+
+		if( !preg_match('/^' . Less_Cache::$prefix . '[a-f0-9]+\.css$/',$css_file_name) ){
+			$list[] = $css_file_name;
+			$css_file_name = false;
+		}
+
+	}
+
+}
diff --git a/less/less/Less.php b/less/less/Less.php
new file mode 100644
index 0000000000000000000000000000000000000000..acdf6037ee7a947b6dedafd501f97135456d880e
--- /dev/null
+++ b/less/less/Less.php
@@ -0,0 +1,10510 @@
+<?php
+
+require_once( dirname(__FILE__).'/Cache.php');
+
+/**
+ * Class for parsing and compiling less files into css
+ *
+ * @package Less
+ * @subpackage parser
+ *
+ */
+class Less_Parser{
+
+
+	/**
+	 * Default parser options
+	 */
+	public static $default_options = array(
+		'compress'				=> false,			// option - whether to compress
+		'strictUnits'			=> false,			// whether units need to evaluate correctly
+		'strictMath'			=> false,			// whether math has to be within parenthesis
+		'relativeUrls'			=> true,			// option - whether to adjust URL's to be relative
+		'urlArgs'				=> array(),			// whether to add args into url tokens
+		'numPrecision'			=> 8,
+
+		'import_dirs'			=> array(),
+		'import_callback'		=> null,
+		'cache_dir'				=> null,
+		'cache_method'			=> 'php', 			// false, 'serialize', 'php', 'var_export', 'callback';
+		'cache_callback_get'	=> null,
+		'cache_callback_set'	=> null,
+
+		'sourceMap'				=> false,			// whether to output a source map
+		'sourceMapBasepath'		=> null,
+		'sourceMapWriteTo'		=> null,
+		'sourceMapURL'			=> null,
+
+		'plugins'				=> array(),
+
+	);
+
+	public static $options = array();
+
+
+	private $input;					// Less input string
+	private $input_len;				// input string length
+	private $pos;					// current index in `input`
+	private $saveStack = array();	// holds state for backtracking
+	private $furthest;
+	private $mb_internal_encoding = ''; // for remember exists value of mbstring.internal_encoding
+
+	/**
+	 * @var Less_Environment
+	 */
+	private $env;
+
+	protected $rules = array();
+
+	private static $imports = array();
+
+	public static $has_extends = false;
+
+	public static $next_id = 0;
+
+	/**
+	 * Filename to contents of all parsed the files
+	 *
+	 * @var array
+	 */
+	public static $contentsMap = array();
+
+
+	/**
+	 * @param Less_Environment|array|null $env
+	 */
+	public function __construct( $env = null ){
+
+		// Top parser on an import tree must be sure there is one "env"
+		// which will then be passed around by reference.
+		if( $env instanceof Less_Environment ){
+			$this->env = $env;
+		}else{
+			$this->SetOptions(Less_Parser::$default_options);
+			$this->Reset( $env );
+		}
+
+		// mbstring.func_overload > 1 bugfix
+		// The encoding value must be set for each source file,
+		// therefore, to conserve resources and improve the speed of this design is taken here
+		if (ini_get('mbstring.func_overload')) {			
+			$this->mb_internal_encoding = ini_get('mbstring.internal_encoding');
+			@ini_set('mbstring.internal_encoding', 'ascii');
+		}
+
+	}
+
+
+	/**
+	 * Reset the parser state completely
+	 *
+	 */
+	public function Reset( $options = null ){
+		$this->rules = array();
+		self::$imports = array();
+		self::$has_extends = false;
+		self::$imports = array();
+		self::$contentsMap = array();
+
+		$this->env = new Less_Environment($options);
+		$this->env->Init();
+
+		//set new options
+		if( is_array($options) ){
+			$this->SetOptions(Less_Parser::$default_options);
+			$this->SetOptions($options);
+		}
+	}
+
+	/**
+	 * Set one or more compiler options
+	 *  options: import_dirs, cache_dir, cache_method
+	 *
+	 */
+	public function SetOptions( $options ){
+		foreach($options as $option => $value){
+			$this->SetOption($option,$value);
+		}
+	}
+
+	/**
+	 * Set one compiler option
+	 *
+	 */
+	public function SetOption($option,$value){
+
+		switch($option){
+
+			case 'import_dirs':
+				$this->SetImportDirs($value);
+			return;
+
+			case 'cache_dir':
+				if( is_string($value) ){
+					Less_Cache::SetCacheDir($value);
+					Less_Cache::CheckCacheDir();
+				}
+			return;
+		}
+
+		Less_Parser::$options[$option] = $value;
+	}
+
+	/**
+	 * Registers a new custom function
+	 *
+	 * @param  string   $name     function name
+	 * @param  callable $callback callback
+	 */
+	public function registerFunction($name, $callback) {
+		$this->env->functions[$name] = $callback;
+	}
+
+	/**
+	 * Removed an already registered function
+	 *
+	 * @param  string $name function name
+	 */
+	public function unregisterFunction($name) {
+		if( isset($this->env->functions[$name]) )
+			unset($this->env->functions[$name]);
+	}
+
+
+	/**
+	 * Get the current css buffer
+	 *
+	 * @return string
+	 */
+	public function getCss(){
+
+		$precision = ini_get('precision');
+		@ini_set('precision',16);
+		$locale = setlocale(LC_NUMERIC, 0);
+		setlocale(LC_NUMERIC, "C");
+
+		try {
+
+	 		$root = new Less_Tree_Ruleset(array(), $this->rules );
+			$root->root = true;
+			$root->firstRoot = true;
+
+
+			$this->PreVisitors($root);
+
+			self::$has_extends = false;
+			$evaldRoot = $root->compile($this->env);
+
+
+
+			$this->PostVisitors($evaldRoot);
+
+			if( Less_Parser::$options['sourceMap'] ){
+				$generator = new Less_SourceMap_Generator($evaldRoot, Less_Parser::$contentsMap, Less_Parser::$options );
+				// will also save file
+				// FIXME: should happen somewhere else?
+				$css = $generator->generateCSS();
+			}else{
+				$css = $evaldRoot->toCSS();
+			}
+
+			if( Less_Parser::$options['compress'] ){
+				$css = preg_replace('/(^(\s)+)|((\s)+$)/', '', $css);
+			}
+
+		} catch (Exception $exc) {
+			// Intentional fall-through so we can reset environment
+		}
+
+		//reset php settings
+		@ini_set('precision',$precision);
+		setlocale(LC_NUMERIC, $locale);
+
+		// If you previously defined $this->mb_internal_encoding 
+		// is required to return the encoding as it was before
+		if ($this->mb_internal_encoding != '') {
+			@ini_set("mbstring.internal_encoding", $this->mb_internal_encoding);
+			$this->mb_internal_encoding = '';
+		}
+
+		// Rethrow exception after we handled resetting the environment
+		if (!empty($exc)) {
+			throw $exc;
+		}
+
+
+
+		return $css;
+	}
+
+	/**
+	 * Run pre-compile visitors
+	 *
+	 */
+	private function PreVisitors($root){
+
+		if( Less_Parser::$options['plugins'] ){
+			foreach(Less_Parser::$options['plugins'] as $plugin){
+				if( !empty($plugin->isPreEvalVisitor) ){
+					$plugin->run($root);
+				}
+			}
+		}
+	}
+
+
+	/**
+	 * Run post-compile visitors
+	 *
+	 */
+	private function PostVisitors($evaldRoot){
+
+		$visitors = array();
+		$visitors[] = new Less_Visitor_joinSelector();
+		if( self::$has_extends ){
+			$visitors[] = new Less_Visitor_processExtends();
+		}
+		$visitors[] = new Less_Visitor_toCSS();
+
+
+		if( Less_Parser::$options['plugins'] ){
+			foreach(Less_Parser::$options['plugins'] as $plugin){
+				if( property_exists($plugin,'isPreEvalVisitor') && $plugin->isPreEvalVisitor ){
+					continue;
+				}
+
+				if( property_exists($plugin,'isPreVisitor') && $plugin->isPreVisitor ){
+					array_unshift( $visitors, $plugin);
+				}else{
+					$visitors[] = $plugin;
+				}
+			}
+		}
+
+
+		for($i = 0; $i < count($visitors); $i++ ){
+			$visitors[$i]->run($evaldRoot);
+		}
+
+	}
+
+
+	/**
+	 * Parse a Less string into css
+	 *
+	 * @param string $str The string to convert
+	 * @param string $uri_root The url of the file
+	 * @return Less_Tree_Ruleset|Less_Parser
+	 */
+	public function parse( $str, $file_uri = null ){
+
+		if( !$file_uri ){
+			$uri_root = '';
+			$filename = 'anonymous-file-'.Less_Parser::$next_id++.'.less';
+		}else{
+			$file_uri = self::WinPath($file_uri);
+			$filename = $file_uri;
+			$uri_root = dirname($file_uri);
+		}
+
+		$previousFileInfo = $this->env->currentFileInfo;
+		$uri_root = self::WinPath($uri_root);
+		$this->SetFileInfo($filename, $uri_root);
+
+		$this->input = $str;
+		$this->_parse();
+
+		if( $previousFileInfo ){
+			$this->env->currentFileInfo = $previousFileInfo;
+		}
+
+		return $this;
+	}
+
+
+	/**
+	 * Parse a Less string from a given file
+	 *
+	 * @throws Less_Exception_Parser
+	 * @param string $filename The file to parse
+	 * @param string $uri_root The url of the file
+	 * @param bool $returnRoot Indicates whether the return value should be a css string a root node
+	 * @return Less_Tree_Ruleset|Less_Parser
+	 */
+	public function parseFile( $filename, $uri_root = '', $returnRoot = false){
+
+		if( !file_exists($filename) ){
+			$this->Error(sprintf('File `%s` not found.', $filename));
+		}
+
+
+		// fix uri_root?
+		// Instead of The mixture of file path for the first argument and directory path for the second argument has bee
+		if( !$returnRoot && !empty($uri_root) && basename($uri_root) == basename($filename) ){
+			$uri_root = dirname($uri_root);
+		}
+
+
+		$previousFileInfo = $this->env->currentFileInfo;
+
+
+		if( $filename ){
+			$filename = self::WinPath(realpath($filename));
+		}
+		$uri_root = self::WinPath($uri_root);
+
+		$this->SetFileInfo($filename, $uri_root);
+
+		self::AddParsedFile($filename);
+
+		if( $returnRoot ){
+			$rules = $this->GetRules( $filename );
+			$return = new Less_Tree_Ruleset(array(), $rules );
+		}else{
+			$this->_parse( $filename );
+			$return = $this;
+		}
+
+		if( $previousFileInfo ){
+			$this->env->currentFileInfo = $previousFileInfo;
+		}
+
+		return $return;
+	}
+
+
+	/**
+	 * Allows a user to set variables values
+	 * @param array $vars
+	 * @return Less_Parser
+	 */
+	public function ModifyVars( $vars ){
+
+		$this->input = Less_Parser::serializeVars( $vars );
+		$this->_parse();
+
+		return $this;
+	}
+
+
+	/**
+	 * @param string $filename
+	 */
+	public function SetFileInfo( $filename, $uri_root = ''){
+
+		$filename = Less_Environment::normalizePath($filename);
+		$dirname = preg_replace('/[^\/\\\\]*$/','',$filename);
+
+		if( !empty($uri_root) ){
+			$uri_root = rtrim($uri_root,'/').'/';
+		}
+
+		$currentFileInfo = array();
+
+		//entry info
+		if( isset($this->env->currentFileInfo) ){
+			$currentFileInfo['entryPath'] = $this->env->currentFileInfo['entryPath'];
+			$currentFileInfo['entryUri'] = $this->env->currentFileInfo['entryUri'];
+			$currentFileInfo['rootpath'] = $this->env->currentFileInfo['rootpath'];
+
+		}else{
+			$currentFileInfo['entryPath'] = $dirname;
+			$currentFileInfo['entryUri'] = $uri_root;
+			$currentFileInfo['rootpath'] = $dirname;
+		}
+
+		$currentFileInfo['currentDirectory'] = $dirname;
+		$currentFileInfo['currentUri'] = $uri_root.basename($filename);
+		$currentFileInfo['filename'] = $filename;
+		$currentFileInfo['uri_root'] = $uri_root;
+
+
+		//inherit reference
+		if( isset($this->env->currentFileInfo['reference']) && $this->env->currentFileInfo['reference'] ){
+			$currentFileInfo['reference'] = true;
+		}
+
+		$this->env->currentFileInfo = $currentFileInfo;
+	}
+
+
+	/**
+	 * @deprecated 1.5.1.2
+	 *
+	 */
+	public function SetCacheDir( $dir ){
+
+		if( !file_exists($dir) ){
+			if( mkdir($dir) ){
+				return true;
+			}
+			throw new Less_Exception_Parser('Less.php cache directory couldn\'t be created: '.$dir);
+
+		}elseif( !is_dir($dir) ){
+			throw new Less_Exception_Parser('Less.php cache directory doesn\'t exist: '.$dir);
+
+		}elseif( !is_writable($dir) ){
+			throw new Less_Exception_Parser('Less.php cache directory isn\'t writable: '.$dir);
+
+		}else{
+			$dir = self::WinPath($dir);
+			Less_Cache::$cache_dir = rtrim($dir,'/').'/';
+			return true;
+		}
+	}
+
+
+	/**
+	 * Set a list of directories or callbacks the parser should use for determining import paths
+	 *
+	 * @param array $dirs
+	 */
+	public function SetImportDirs( $dirs ){
+		Less_Parser::$options['import_dirs'] = array();
+
+		foreach($dirs as $path => $uri_root){
+
+			$path = self::WinPath($path);
+			if( !empty($path) ){
+				$path = rtrim($path,'/').'/';
+			}
+
+			if ( !is_callable($uri_root) ){
+				$uri_root = self::WinPath($uri_root);
+				if( !empty($uri_root) ){
+					$uri_root = rtrim($uri_root,'/').'/';
+				}
+			}
+
+			Less_Parser::$options['import_dirs'][$path] = $uri_root;
+		}
+	}
+
+	/**
+	 * @param string $file_path
+	 */
+	private function _parse( $file_path = null ){
+		$this->rules = array_merge($this->rules, $this->GetRules( $file_path ));
+	}
+
+
+	/**
+	 * Return the results of parsePrimary for $file_path
+	 * Use cache and save cached results if possible
+	 *
+	 * @param string|null $file_path
+	 */
+	private function GetRules( $file_path ){
+
+		$this->SetInput($file_path);
+
+		$cache_file = $this->CacheFile( $file_path );
+		if( $cache_file ){
+			if( Less_Parser::$options['cache_method'] == 'callback' ){
+				if( is_callable(Less_Parser::$options['cache_callback_get']) ){
+					$cache = call_user_func_array(
+						Less_Parser::$options['cache_callback_get'],
+						array($this, $file_path, $cache_file)
+					);
+
+					if( $cache ){
+						$this->UnsetInput();
+						return $cache;
+					}
+				}
+
+			}elseif( file_exists($cache_file) ){
+				switch(Less_Parser::$options['cache_method']){
+
+					// Using serialize
+					// Faster but uses more memory
+					case 'serialize':
+						$cache = unserialize(file_get_contents($cache_file));
+						if( $cache ){
+							touch($cache_file);
+							$this->UnsetInput();
+							return $cache;
+						}
+					break;
+
+
+					// Using generated php code
+					case 'var_export':
+					case 'php':
+					$this->UnsetInput();
+					return include($cache_file);
+				}
+			}
+		}
+
+		$rules = $this->parsePrimary();
+
+		if( $this->pos < $this->input_len ){
+			throw new Less_Exception_Chunk($this->input, null, $this->furthest, $this->env->currentFileInfo);
+		}
+
+		$this->UnsetInput();
+
+
+		//save the cache
+		if( $cache_file ){
+			if( Less_Parser::$options['cache_method'] == 'callback' ){
+				if( is_callable(Less_Parser::$options['cache_callback_set']) ){
+					call_user_func_array(
+						Less_Parser::$options['cache_callback_set'],
+						array($this, $file_path, $cache_file, $rules)
+					);
+				}
+
+			}else{
+				//msg('write cache file');
+				switch(Less_Parser::$options['cache_method']){
+					case 'serialize':
+						file_put_contents( $cache_file, serialize($rules) );
+					break;
+					case 'php':
+						file_put_contents( $cache_file, '<?php return '.self::ArgString($rules).'; ?>' );
+					break;
+					case 'var_export':
+						//Requires __set_state()
+						file_put_contents( $cache_file, '<?php return '.var_export($rules,true).'; ?>' );
+					break;
+				}
+
+				Less_Cache::CleanCache();
+			}
+		}
+
+		return $rules;
+	}
+
+
+	/**
+	 * Set up the input buffer
+	 *
+	 */
+	public function SetInput( $file_path ){
+
+		if( $file_path ){
+			$this->input = file_get_contents( $file_path );
+		}
+
+		$this->pos = $this->furthest = 0;
+
+		// Remove potential UTF Byte Order Mark
+		$this->input = preg_replace('/\\G\xEF\xBB\xBF/', '', $this->input);
+		$this->input_len = strlen($this->input);
+
+
+		if( Less_Parser::$options['sourceMap'] && $this->env->currentFileInfo ){
+			$uri = $this->env->currentFileInfo['currentUri'];
+			Less_Parser::$contentsMap[$uri] = $this->input;
+		}
+
+	}
+
+
+	/**
+	 * Free up some memory
+	 *
+	 */
+	public function UnsetInput(){
+		unset($this->input, $this->pos, $this->input_len, $this->furthest);
+		$this->saveStack = array();
+	}
+
+
+	public function CacheFile( $file_path ){
+
+		if( $file_path && $this->CacheEnabled() ){
+
+			$env = get_object_vars($this->env);
+			unset($env['frames']);
+
+			$parts = array();
+			$parts[] = $file_path;
+			$parts[] = filesize( $file_path );
+			$parts[] = filemtime( $file_path );
+			$parts[] = $env;
+			$parts[] = Less_Version::cache_version;
+			$parts[] = Less_Parser::$options['cache_method'];
+			return Less_Cache::$cache_dir . Less_Cache::$prefix . base_convert( sha1(json_encode($parts) ), 16, 36) . '.lesscache';
+		}
+	}
+
+
+	static function AddParsedFile($file){
+		self::$imports[] = $file;
+	}
+
+	static function AllParsedFiles(){
+		return self::$imports;
+	}
+
+	/**
+	 * @param string $file
+	 */
+	static function FileParsed($file){
+		return in_array($file,self::$imports);
+	}
+
+
+	function save() {
+		$this->saveStack[] = $this->pos;
+	}
+
+	private function restore() {
+		$this->pos = array_pop($this->saveStack);
+	}
+
+	private function forget(){
+		array_pop($this->saveStack);
+	}
+
+
+	private function isWhitespace($offset = 0) {
+		return preg_match('/\s/',$this->input[ $this->pos + $offset]);
+	}
+
+	/**
+	 * Parse from a token, regexp or string, and move forward if match
+	 *
+	 * @param array $toks
+	 * @return array
+	 */
+	private function match($toks){
+
+		// The match is confirmed, add the match length to `this::pos`,
+		// and consume any extra white-space characters (' ' || '\n')
+		// which come after that. The reason for this is that LeSS's
+		// grammar is mostly white-space insensitive.
+		//
+
+		foreach($toks as $tok){
+
+			$char = $tok[0];
+
+			if( $char === '/' ){
+				$match = $this->MatchReg($tok);
+
+				if( $match ){
+					return count($match) === 1 ? $match[0] : $match;
+				}
+
+			}elseif( $char === '#' ){
+				$match = $this->MatchChar($tok[1]);
+
+			}else{
+				// Non-terminal, match using a function call
+				$match = $this->$tok();
+
+			}
+
+			if( $match ){
+				return $match;
+			}
+		}
+	}
+
+	/**
+	 * @param string[] $toks
+	 *
+	 * @return string
+	 */
+	private function MatchFuncs($toks){
+
+		if( $this->pos < $this->input_len ){
+			foreach($toks as $tok){
+				$match = $this->$tok();
+				if( $match ){
+					return $match;
+				}
+			}
+		}
+
+	}
+
+	// Match a single character in the input,
+	private function MatchChar($tok){
+		if( ($this->pos < $this->input_len) && ($this->input[$this->pos] === $tok) ){
+			$this->skipWhitespace(1);
+			return $tok;
+		}
+	}
+
+	// Match a regexp from the current start point
+	private function MatchReg($tok){
+
+		if( preg_match($tok, $this->input, $match, 0, $this->pos) ){
+			$this->skipWhitespace(strlen($match[0]));
+			return $match;
+		}
+	}
+
+
+	/**
+	 * Same as match(), but don't change the state of the parser,
+	 * just return the match.
+	 *
+	 * @param string $tok
+	 * @return integer
+	 */
+	public function PeekReg($tok){
+		return preg_match($tok, $this->input, $match, 0, $this->pos);
+	}
+
+	/**
+	 * @param string $tok
+	 */
+	public function PeekChar($tok){
+		//return ($this->input[$this->pos] === $tok );
+		return ($this->pos < $this->input_len) && ($this->input[$this->pos] === $tok );
+	}
+
+
+	/**
+	 * @param integer $length
+	 */
+	public function skipWhitespace($length){
+
+		$this->pos += $length;
+
+		for(; $this->pos < $this->input_len; $this->pos++ ){
+			$c = $this->input[$this->pos];
+
+			if( ($c !== "\n") && ($c !== "\r") && ($c !== "\t") && ($c !== ' ') ){
+				break;
+			}
+		}
+	}
+
+
+	/**
+	 * @param string $tok
+	 * @param string|null $msg
+	 */
+	public function expect($tok, $msg = NULL) {
+		$result = $this->match( array($tok) );
+		if (!$result) {
+			$this->Error( $msg	? "Expected '" . $tok . "' got '" . $this->input[$this->pos] . "'" : $msg );
+		} else {
+			return $result;
+		}
+	}
+
+	/**
+	 * @param string $tok
+	 */
+	public function expectChar($tok, $msg = null ){
+		$result = $this->MatchChar($tok);
+		if( !$result ){
+			$this->Error( $msg ? "Expected '" . $tok . "' got '" . $this->input[$this->pos] . "'" : $msg );
+		}else{
+			return $result;
+		}
+	}
+
+	//
+	// Here in, the parsing rules/functions
+	//
+	// The basic structure of the syntax tree generated is as follows:
+	//
+	//   Ruleset ->  Rule -> Value -> Expression -> Entity
+	//
+	// Here's some LESS code:
+	//
+	//	.class {
+	//	  color: #fff;
+	//	  border: 1px solid #000;
+	//	  width: @w + 4px;
+	//	  > .child {...}
+	//	}
+	//
+	// And here's what the parse tree might look like:
+	//
+	//	 Ruleset (Selector '.class', [
+	//		 Rule ("color",  Value ([Expression [Color #fff]]))
+	//		 Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]]))
+	//		 Rule ("width",  Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]]))
+	//		 Ruleset (Selector [Element '>', '.child'], [...])
+	//	 ])
+	//
+	//  In general, most rules will try to parse a token with the `$()` function, and if the return
+	//  value is truly, will return a new node, of the relevant type. Sometimes, we need to check
+	//  first, before parsing, that's when we use `peek()`.
+	//
+
+	//
+	// The `primary` rule is the *entry* and *exit* point of the parser.
+	// The rules here can appear at any level of the parse tree.
+	//
+	// The recursive nature of the grammar is an interplay between the `block`
+	// rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule,
+	// as represented by this simplified grammar:
+	//
+	//	 primary  →  (ruleset | rule)+
+	//	 ruleset  →  selector+ block
+	//	 block	→  '{' primary '}'
+	//
+	// Only at one point is the primary rule not called from the
+	// block rule: at the root level.
+	//
+	private function parsePrimary(){
+		$root = array();
+
+		while( true ){
+
+			if( $this->pos >= $this->input_len ){
+				break;
+			}
+
+			$node = $this->parseExtend(true);
+			if( $node ){
+				$root = array_merge($root,$node);
+				continue;
+			}
+
+			//$node = $this->MatchFuncs( array( 'parseMixinDefinition', 'parseRule', 'parseRuleset', 'parseMixinCall', 'parseComment', 'parseDirective'));
+			$node = $this->MatchFuncs( array( 'parseMixinDefinition', 'parseNameValue', 'parseRule', 'parseRuleset', 'parseMixinCall', 'parseComment', 'parseRulesetCall', 'parseDirective'));
+
+			if( $node ){
+				$root[] = $node;
+			}elseif( !$this->MatchReg('/\\G[\s\n;]+/') ){
+				break;
+			}
+
+            if( $this->PeekChar('}') ){
+				break;
+			}
+		}
+
+		return $root;
+	}
+
+
+
+	// We create a Comment node for CSS comments `/* */`,
+	// but keep the LeSS comments `//` silent, by just skipping
+	// over them.
+	private function parseComment(){
+
+		if( $this->input[$this->pos] !== '/' ){
+			return;
+		}
+
+		if( $this->input[$this->pos+1] === '/' ){
+			$match = $this->MatchReg('/\\G\/\/.*/');
+			return $this->NewObj4('Less_Tree_Comment',array($match[0], true, $this->pos, $this->env->currentFileInfo));
+		}
+
+		//$comment = $this->MatchReg('/\\G\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/');
+		$comment = $this->MatchReg('/\\G\/\*(?s).*?\*+\/\n?/');//not the same as less.js to prevent fatal errors
+		if( $comment ){
+			return $this->NewObj4('Less_Tree_Comment',array($comment[0], false, $this->pos, $this->env->currentFileInfo));
+		}
+	}
+
+	private function parseComments(){
+		$comments = array();
+
+		while( $this->pos < $this->input_len ){
+			$comment = $this->parseComment();
+			if( !$comment ){
+				break;
+			}
+
+			$comments[] = $comment;
+		}
+
+		return $comments;
+	}
+
+
+
+	//
+	// A string, which supports escaping " and '
+	//
+	//	 "milky way" 'he\'s the one!'
+	//
+	private function parseEntitiesQuoted() {
+		$j = $this->pos;
+		$e = false;
+		$index = $this->pos;
+
+		if( $this->input[$this->pos] === '~' ){
+			$j++;
+			$e = true; // Escaped strings
+		}
+
+		if( $this->input[$j] != '"' && $this->input[$j] !== "'" ){
+			return;
+		}
+
+		if ($e) {
+			$this->MatchChar('~');
+		}
+
+                // Fix for #124: match escaped newlines
+                //$str = $this->MatchReg('/\\G"((?:[^"\\\\\r\n]|\\\\.)*)"|\'((?:[^\'\\\\\r\n]|\\\\.)*)\'/');
+		$str = $this->MatchReg('/\\G"((?:[^"\\\\\r\n]|\\\\.|\\\\\r\n|\\\\[\n\r\f])*)"|\'((?:[^\'\\\\\r\n]|\\\\.|\\\\\r\n|\\\\[\n\r\f])*)\'/');
+
+		if( $str ){
+			$result = $str[0][0] == '"' ? $str[1] : $str[2];
+			return $this->NewObj5('Less_Tree_Quoted',array($str[0], $result, $e, $index, $this->env->currentFileInfo) );
+		}
+		return;
+	}
+
+
+	//
+	// A catch-all word, such as:
+	//
+	//	 black border-collapse
+	//
+	private function parseEntitiesKeyword(){
+
+		//$k = $this->MatchReg('/\\G[_A-Za-z-][_A-Za-z0-9-]*/');
+		$k = $this->MatchReg('/\\G%|\\G[_A-Za-z-][_A-Za-z0-9-]*/');
+		if( $k ){
+			$k = $k[0];
+			$color = $this->fromKeyword($k);
+			if( $color ){
+				return $color;
+			}
+			return $this->NewObj1('Less_Tree_Keyword',$k);
+		}
+	}
+
+	// duplicate of Less_Tree_Color::FromKeyword
+	private function FromKeyword( $keyword ){
+		$keyword = strtolower($keyword);
+
+		if( Less_Colors::hasOwnProperty($keyword) ){
+			// detect named color
+			return $this->NewObj1('Less_Tree_Color',substr(Less_Colors::color($keyword), 1));
+		}
+
+		if( $keyword === 'transparent' ){
+			return $this->NewObj3('Less_Tree_Color', array( array(0, 0, 0), 0, true));
+		}
+	}
+
+	//
+	// A function call
+	//
+	//	 rgb(255, 0, 255)
+	//
+	// We also try to catch IE's `alpha()`, but let the `alpha` parser
+	// deal with the details.
+	//
+	// The arguments are parsed with the `entities.arguments` parser.
+	//
+	private function parseEntitiesCall(){
+		$index = $this->pos;
+
+		if( !preg_match('/\\G([\w-]+|%|progid:[\w\.]+)\(/', $this->input, $name,0,$this->pos) ){
+			return;
+		}
+		$name = $name[1];
+		$nameLC = strtolower($name);
+
+		if ($nameLC === 'url') {
+			return null;
+		}
+
+		$this->pos += strlen($name);
+
+		if( $nameLC === 'alpha' ){
+			$alpha_ret = $this->parseAlpha();
+			if( $alpha_ret ){
+				return $alpha_ret;
+			}
+		}
+
+		$this->MatchChar('('); // Parse the '(' and consume whitespace.
+
+		$args = $this->parseEntitiesArguments();
+
+		if( !$this->MatchChar(')') ){
+			return;
+		}
+
+		if ($name) {
+			return $this->NewObj4('Less_Tree_Call',array($name, $args, $index, $this->env->currentFileInfo) );
+		}
+	}
+
+	/**
+	 * Parse a list of arguments
+	 *
+	 * @return array
+	 */
+	private function parseEntitiesArguments(){
+
+		$args = array();
+		while( true ){
+			$arg = $this->MatchFuncs( array('parseEntitiesAssignment','parseExpression') );
+			if( !$arg ){
+				break;
+			}
+
+			$args[] = $arg;
+			if( !$this->MatchChar(',') ){
+				break;
+			}
+		}
+		return $args;
+	}
+
+	private function parseEntitiesLiteral(){
+		return $this->MatchFuncs( array('parseEntitiesDimension','parseEntitiesColor','parseEntitiesQuoted','parseUnicodeDescriptor') );
+	}
+
+	// Assignments are argument entities for calls.
+	// They are present in ie filter properties as shown below.
+	//
+	//	 filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* )
+	//
+	private function parseEntitiesAssignment() {
+
+		$key = $this->MatchReg('/\\G\w+(?=\s?=)/');
+		if( !$key ){
+			return;
+		}
+
+		if( !$this->MatchChar('=') ){
+			return;
+		}
+
+		$value = $this->parseEntity();
+		if( $value ){
+			return $this->NewObj2('Less_Tree_Assignment',array($key[0], $value));
+		}
+	}
+
+	//
+	// Parse url() tokens
+	//
+	// We use a specific rule for urls, because they don't really behave like
+	// standard function calls. The difference is that the argument doesn't have
+	// to be enclosed within a string, so it can't be parsed as an Expression.
+	//
+	private function parseEntitiesUrl(){
+
+
+		if( $this->input[$this->pos] !== 'u' || !$this->matchReg('/\\Gurl\(/') ){
+			return;
+		}
+
+		$value = $this->match( array('parseEntitiesQuoted','parseEntitiesVariable','/\\Gdata\:.*?[^\)]+/','/\\G(?:(?:\\\\[\(\)\'"])|[^\(\)\'"])+/') );
+		if( !$value ){
+			$value = '';
+		}
+
+
+		$this->expectChar(')');
+
+
+		if( isset($value->value) || $value instanceof Less_Tree_Variable ){
+			return $this->NewObj2('Less_Tree_Url',array($value, $this->env->currentFileInfo));
+		}
+
+		return $this->NewObj2('Less_Tree_Url', array( $this->NewObj1('Less_Tree_Anonymous',$value), $this->env->currentFileInfo) );
+	}
+
+
+	//
+	// A Variable entity, such as `@fink`, in
+	//
+	//	 width: @fink + 2px
+	//
+	// We use a different parser for variable definitions,
+	// see `parsers.variable`.
+	//
+	private function parseEntitiesVariable(){
+		$index = $this->pos;
+		if ($this->PeekChar('@') && ($name = $this->MatchReg('/\\G@@?[\w-]+/'))) {
+			return $this->NewObj3('Less_Tree_Variable', array( $name[0], $index, $this->env->currentFileInfo));
+		}
+	}
+
+
+	// A variable entity useing the protective {} e.g. @{var}
+	private function parseEntitiesVariableCurly() {
+		$index = $this->pos;
+
+		if( $this->input_len > ($this->pos+1) && $this->input[$this->pos] === '@' && ($curly = $this->MatchReg('/\\G@\{([\w-]+)\}/')) ){
+			return $this->NewObj3('Less_Tree_Variable',array('@'.$curly[1], $index, $this->env->currentFileInfo));
+		}
+	}
+
+	//
+	// A Hexadecimal color
+	//
+	//	 #4F3C2F
+	//
+	// `rgb` and `hsl` colors are parsed through the `entities.call` parser.
+	//
+	private function parseEntitiesColor(){
+		if ($this->PeekChar('#') && ($rgb = $this->MatchReg('/\\G#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/'))) {
+			return $this->NewObj1('Less_Tree_Color',$rgb[1]);
+		}
+	}
+
+	//
+	// A Dimension, that is, a number and a unit
+	//
+	//	 0.5em 95%
+	//
+	private function parseEntitiesDimension(){
+
+		$c = @ord($this->input[$this->pos]);
+
+		//Is the first char of the dimension 0-9, '.', '+' or '-'
+		if (($c > 57 || $c < 43) || $c === 47 || $c == 44){
+			return;
+		}
+
+		$value = $this->MatchReg('/\\G([+-]?\d*\.?\d+)(%|[a-z]+)?/');
+		if( $value ){
+
+			if( isset($value[2]) ){
+				return $this->NewObj2('Less_Tree_Dimension', array($value[1],$value[2]));
+			}
+			return $this->NewObj1('Less_Tree_Dimension',$value[1]);
+		}
+	}
+
+
+	//
+	// A unicode descriptor, as is used in unicode-range
+	//
+	// U+0?? or U+00A1-00A9
+	//
+	function parseUnicodeDescriptor() {
+		$ud = $this->MatchReg('/\\G(U\+[0-9a-fA-F?]+)(\-[0-9a-fA-F?]+)?/');
+		if( $ud ){
+			return $this->NewObj1('Less_Tree_UnicodeDescriptor', $ud[0]);
+		}
+	}
+
+
+	//
+	// JavaScript code to be evaluated
+	//
+	//	 `window.location.href`
+	//
+	private function parseEntitiesJavascript(){
+		$e = false;
+		$j = $this->pos;
+		if( $this->input[$j] === '~' ){
+			$j++;
+			$e = true;
+		}
+		if( $this->input[$j] !== '`' ){
+			return;
+		}
+		if( $e ){
+			$this->MatchChar('~');
+		}
+		$str = $this->MatchReg('/\\G`([^`]*)`/');
+		if( $str ){
+			return $this->NewObj3('Less_Tree_Javascript', array($str[1], $this->pos, $e));
+		}
+	}
+
+
+	//
+	// The variable part of a variable definition. Used in the `rule` parser
+	//
+	//	 @fink:
+	//
+	private function parseVariable(){
+		if ($this->PeekChar('@') && ($name = $this->MatchReg('/\\G(@[\w-]+)\s*:/'))) {
+			return $name[1];
+		}
+	}
+
+
+	//
+	// The variable part of a variable definition. Used in the `rule` parser
+	//
+	// @fink();
+	//
+	private function parseRulesetCall(){
+
+		if( $this->input[$this->pos] === '@' && ($name = $this->MatchReg('/\\G(@[\w-]+)\s*\(\s*\)\s*;/')) ){
+			return $this->NewObj1('Less_Tree_RulesetCall', $name[1] );
+		}
+	}
+
+
+	//
+	// extend syntax - used to extend selectors
+	//
+	function parseExtend($isRule = false){
+
+		$index = $this->pos;
+		$extendList = array();
+
+
+		if( !$this->MatchReg( $isRule ? '/\\G&:extend\(/' : '/\\G:extend\(/' ) ){ return; }
+
+		do{
+			$option = null;
+			$elements = array();
+			while( true ){
+				$option = $this->MatchReg('/\\G(all)(?=\s*(\)|,))/');
+				if( $option ){ break; }
+				$e = $this->parseElement();
+				if( !$e ){ break; }
+				$elements[] = $e;
+			}
+
+			if( $option ){
+				$option = $option[1];
+			}
+
+			$extendList[] = $this->NewObj3('Less_Tree_Extend', array( $this->NewObj1('Less_Tree_Selector',$elements), $option, $index ));
+
+		}while( $this->MatchChar(",") );
+
+		$this->expect('/\\G\)/');
+
+		if( $isRule ){
+			$this->expect('/\\G;/');
+		}
+
+		return $extendList;
+	}
+
+
+	//
+	// A Mixin call, with an optional argument list
+	//
+	//	 #mixins > .square(#fff);
+	//	 .rounded(4px, black);
+	//	 .button;
+	//
+	// The `while` loop is there because mixins can be
+	// namespaced, but we only support the child and descendant
+	// selector for now.
+	//
+	private function parseMixinCall(){
+
+		$char = $this->input[$this->pos];
+		if( $char !== '.' && $char !== '#' ){
+			return;
+		}
+
+		$index = $this->pos;
+		$this->save(); // stop us absorbing part of an invalid selector
+
+		$elements = $this->parseMixinCallElements();
+
+		if( $elements ){
+
+			if( $this->MatchChar('(') ){
+				$returned = $this->parseMixinArgs(true);
+				$args = $returned['args'];
+				$this->expectChar(')');
+			}else{
+				$args = array();
+			}
+
+			$important = $this->parseImportant();
+
+			if( $this->parseEnd() ){
+				$this->forget();
+				return $this->NewObj5('Less_Tree_Mixin_Call', array( $elements, $args, $index, $this->env->currentFileInfo, $important));
+			}
+		}
+
+		$this->restore();
+	}
+
+
+	private function parseMixinCallElements(){
+		$elements = array();
+		$c = null;
+
+		while( true ){
+			$elemIndex = $this->pos;
+			$e = $this->MatchReg('/\\G[#.](?:[\w-]|\\\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/');
+			if( !$e ){
+				break;
+			}
+			$elements[] = $this->NewObj4('Less_Tree_Element', array($c, $e[0], $elemIndex, $this->env->currentFileInfo));
+			$c = $this->MatchChar('>');
+		}
+
+		return $elements;
+	}
+
+
+
+	/**
+	 * @param boolean $isCall
+	 */
+	private function parseMixinArgs( $isCall ){
+		$expressions = array();
+		$argsSemiColon = array();
+		$isSemiColonSeperated = null;
+		$argsComma = array();
+		$expressionContainsNamed = null;
+		$name = null;
+		$returner = array('args'=>array(), 'variadic'=> false);
+
+		$this->save();
+
+		while( true ){
+			if( $isCall ){
+				$arg = $this->MatchFuncs( array( 'parseDetachedRuleset','parseExpression' ) );
+			} else {
+				$this->parseComments();
+				if( $this->input[ $this->pos ] === '.' && $this->MatchReg('/\\G\.{3}/') ){
+					$returner['variadic'] = true;
+					if( $this->MatchChar(";") && !$isSemiColonSeperated ){
+						$isSemiColonSeperated = true;
+					}
+
+					if( $isSemiColonSeperated ){
+						$argsSemiColon[] = array('variadic'=>true);
+					}else{
+						$argsComma[] = array('variadic'=>true);
+					}
+					break;
+				}
+				$arg = $this->MatchFuncs( array('parseEntitiesVariable','parseEntitiesLiteral','parseEntitiesKeyword') );
+			}
+
+			if( !$arg ){
+				break;
+			}
+
+
+			$nameLoop = null;
+			if( $arg instanceof Less_Tree_Expression ){
+				$arg->throwAwayComments();
+			}
+			$value = $arg;
+			$val = null;
+
+			if( $isCall ){
+				// Variable
+				if( property_exists($arg,'value') && count($arg->value) == 1 ){
+					$val = $arg->value[0];
+				}
+			} else {
+				$val = $arg;
+			}
+
+
+			if( $val instanceof Less_Tree_Variable ){
+
+				if( $this->MatchChar(':') ){
+					if( $expressions ){
+						if( $isSemiColonSeperated ){
+							$this->Error('Cannot mix ; and , as delimiter types');
+						}
+						$expressionContainsNamed = true;
+					}
+
+					// we do not support setting a ruleset as a default variable - it doesn't make sense
+					// However if we do want to add it, there is nothing blocking it, just don't error
+					// and remove isCall dependency below
+					$value = null;
+					if( $isCall ){
+						$value = $this->parseDetachedRuleset();
+					}
+					if( !$value ){
+						$value = $this->parseExpression();
+					}
+
+					if( !$value ){
+						if( $isCall ){
+							$this->Error('could not understand value for named argument');
+						} else {
+							$this->restore();
+							$returner['args'] = array();
+							return $returner;
+						}
+					}
+
+					$nameLoop = ($name = $val->name);
+				}elseif( !$isCall && $this->MatchReg('/\\G\.{3}/') ){
+					$returner['variadic'] = true;
+					if( $this->MatchChar(";") && !$isSemiColonSeperated ){
+						$isSemiColonSeperated = true;
+					}
+					if( $isSemiColonSeperated ){
+						$argsSemiColon[] = array('name'=> $arg->name, 'variadic' => true);
+					}else{
+						$argsComma[] = array('name'=> $arg->name, 'variadic' => true);
+					}
+					break;
+				}elseif( !$isCall ){
+					$name = $nameLoop = $val->name;
+					$value = null;
+				}
+			}
+
+			if( $value ){
+				$expressions[] = $value;
+			}
+
+			$argsComma[] = array('name'=>$nameLoop, 'value'=>$value );
+
+			if( $this->MatchChar(',') ){
+				continue;
+			}
+
+			if( $this->MatchChar(';') || $isSemiColonSeperated ){
+
+				if( $expressionContainsNamed ){
+					$this->Error('Cannot mix ; and , as delimiter types');
+				}
+
+				$isSemiColonSeperated = true;
+
+				if( count($expressions) > 1 ){
+					$value = $this->NewObj1('Less_Tree_Value', $expressions);
+				}
+				$argsSemiColon[] = array('name'=>$name, 'value'=>$value );
+
+				$name = null;
+				$expressions = array();
+				$expressionContainsNamed = false;
+			}
+		}
+
+		$this->forget();
+		$returner['args'] = ($isSemiColonSeperated ? $argsSemiColon : $argsComma);
+		return $returner;
+	}
+
+
+
+	//
+	// A Mixin definition, with a list of parameters
+	//
+	//	 .rounded (@radius: 2px, @color) {
+	//		...
+	//	 }
+	//
+	// Until we have a finer grained state-machine, we have to
+	// do a look-ahead, to make sure we don't have a mixin call.
+	// See the `rule` function for more information.
+	//
+	// We start by matching `.rounded (`, and then proceed on to
+	// the argument list, which has optional default values.
+	// We store the parameters in `params`, with a `value` key,
+	// if there is a value, such as in the case of `@radius`.
+	//
+	// Once we've got our params list, and a closing `)`, we parse
+	// the `{...}` block.
+	//
+	private function parseMixinDefinition(){
+		$cond = null;
+
+		$char = $this->input[$this->pos];
+		if( ($char !== '.' && $char !== '#') || ($char === '{' && $this->PeekReg('/\\G[^{]*\}/')) ){
+			return;
+		}
+
+		$this->save();
+
+		$match = $this->MatchReg('/\\G([#.](?:[\w-]|\\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/');
+		if( $match ){
+			$name = $match[1];
+
+			$argInfo = $this->parseMixinArgs( false );
+			$params = $argInfo['args'];
+			$variadic = $argInfo['variadic'];
+
+
+			// .mixincall("@{a}");
+			// looks a bit like a mixin definition..
+			// also
+			// .mixincall(@a: {rule: set;});
+			// so we have to be nice and restore
+			if( !$this->MatchChar(')') ){
+				$this->furthest = $this->pos;
+				$this->restore();
+				return;
+			}
+
+
+			$this->parseComments();
+
+			if ($this->MatchReg('/\\Gwhen/')) { // Guard
+				$cond = $this->expect('parseConditions', 'Expected conditions');
+			}
+
+			$ruleset = $this->parseBlock();
+
+			if( is_array($ruleset) ){
+				$this->forget();
+				return $this->NewObj5('Less_Tree_Mixin_Definition', array( $name, $params, $ruleset, $cond, $variadic));
+			}
+
+			$this->restore();
+		}else{
+			$this->forget();
+		}
+	}
+
+	//
+	// Entities are the smallest recognized token,
+	// and can be found inside a rule's value.
+	//
+	private function parseEntity(){
+
+		return $this->MatchFuncs( array('parseEntitiesLiteral','parseEntitiesVariable','parseEntitiesUrl','parseEntitiesCall','parseEntitiesKeyword','parseEntitiesJavascript','parseComment') );
+	}
+
+	//
+	// A Rule terminator. Note that we use `peek()` to check for '}',
+	// because the `block` rule will be expecting it, but we still need to make sure
+	// it's there, if ';' was ommitted.
+	//
+	private function parseEnd(){
+		return $this->MatchChar(';') || $this->PeekChar('}');
+	}
+
+	//
+	// IE's alpha function
+	//
+	//	 alpha(opacity=88)
+	//
+	private function parseAlpha(){
+
+		if ( ! $this->MatchReg('/\\G\(opacity=/i')) {
+			return;
+		}
+
+		$value = $this->MatchReg('/\\G[0-9]+/');
+		if( $value ){
+			$value = $value[0];
+		}else{
+			$value = $this->parseEntitiesVariable();
+			if( !$value ){
+				return;
+			}
+		}
+
+		$this->expectChar(')');
+		return $this->NewObj1('Less_Tree_Alpha',$value);
+	}
+
+
+	//
+	// A Selector Element
+	//
+	//	 div
+	//	 + h1
+	//	 #socks
+	//	 input[type="text"]
+	//
+	// Elements are the building blocks for Selectors,
+	// they are made out of a `Combinator` (see combinator rule),
+	// and an element name, such as a tag a class, or `*`.
+	//
+	private function parseElement(){
+		$c = $this->parseCombinator();
+		$index = $this->pos;
+
+		$e = $this->match( array('/\\G(?:\d+\.\d+|\d+)%/', '/\\G(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/',
+			'#*', '#&', 'parseAttribute', '/\\G\([^()@]+\)/', '/\\G[\.#](?=@)/', 'parseEntitiesVariableCurly') );
+
+		if( is_null($e) ){
+			$this->save();
+			if( $this->MatchChar('(') ){
+				if( ($v = $this->parseSelector()) && $this->MatchChar(')') ){
+					$e = $this->NewObj1('Less_Tree_Paren',$v);
+					$this->forget();
+				}else{
+					$this->restore();
+				}
+			}else{
+				$this->forget();
+			}
+		}
+
+		if( !is_null($e) ){
+			return $this->NewObj4('Less_Tree_Element',array( $c, $e, $index, $this->env->currentFileInfo));
+		}
+	}
+
+	//
+	// Combinators combine elements together, in a Selector.
+	//
+	// Because our parser isn't white-space sensitive, special care
+	// has to be taken, when parsing the descendant combinator, ` `,
+	// as it's an empty space. We have to check the previous character
+	// in the input, to see if it's a ` ` character.
+	//
+	private function parseCombinator(){
+		if( $this->pos < $this->input_len ){
+			$c = $this->input[$this->pos];
+			if ($c === '>' || $c === '+' || $c === '~' || $c === '|' || $c === '^' ){
+
+				$this->pos++;
+				if( $this->input[$this->pos] === '^' ){
+					$c = '^^';
+					$this->pos++;
+				}
+
+				$this->skipWhitespace(0);
+
+				return $c;
+			}
+
+			if( $this->pos > 0 && $this->isWhitespace(-1) ){
+				return ' ';
+			}
+		}
+	}
+
+	//
+	// A CSS selector (see selector below)
+	// with less extensions e.g. the ability to extend and guard
+	//
+	private function parseLessSelector(){
+		return $this->parseSelector(true);
+	}
+
+	//
+	// A CSS Selector
+	//
+	//	 .class > div + h1
+	//	 li a:hover
+	//
+	// Selectors are made out of one or more Elements, see above.
+	//
+	private function parseSelector( $isLess = false ){
+		$elements = array();
+		$extendList = array();
+		$condition = null;
+		$when = false;
+		$extend = false;
+		$e = null;
+		$c = null;
+		$index = $this->pos;
+
+		while( ($isLess && ($extend = $this->parseExtend())) || ($isLess && ($when = $this->MatchReg('/\\Gwhen/') )) || ($e = $this->parseElement()) ){
+			if( $when ){
+				$condition = $this->expect('parseConditions', 'expected condition');
+			}elseif( $condition ){
+				//error("CSS guard can only be used at the end of selector");
+			}elseif( $extend ){
+				$extendList = array_merge($extendList,$extend);
+			}else{
+				//if( count($extendList) ){
+					//error("Extend can only be used at the end of selector");
+				//}
+				if( $this->pos < $this->input_len ){
+					$c = $this->input[ $this->pos ];
+				}
+				$elements[] = $e;
+				$e = null;
+			}
+
+			if( $c === '{' || $c === '}' || $c === ';' || $c === ',' || $c === ')') { break; }
+		}
+
+		if( $elements ){
+			return $this->NewObj5('Less_Tree_Selector',array($elements, $extendList, $condition, $index, $this->env->currentFileInfo));
+		}
+		if( $extendList ) {
+			$this->Error('Extend must be used to extend a selector, it cannot be used on its own');
+		}
+	}
+
+	private function parseTag(){
+		return ( $tag = $this->MatchReg('/\\G[A-Za-z][A-Za-z-]*[0-9]?/') ) ? $tag : $this->MatchChar('*');
+	}
+
+	private function parseAttribute(){
+
+		$val = null;
+
+		if( !$this->MatchChar('[') ){
+			return;
+		}
+
+		$key = $this->parseEntitiesVariableCurly();
+		if( !$key ){
+			$key = $this->expect('/\\G(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\\\.)+/');
+		}
+
+		$op = $this->MatchReg('/\\G[|~*$^]?=/');
+		if( $op ){
+			$val = $this->match( array('parseEntitiesQuoted','/\\G[0-9]+%/','/\\G[\w-]+/','parseEntitiesVariableCurly') );
+		}
+
+		$this->expectChar(']');
+
+		return $this->NewObj3('Less_Tree_Attribute',array( $key, $op[0], $val));
+	}
+
+	//
+	// The `block` rule is used by `ruleset` and `mixin.definition`.
+	// It's a wrapper around the `primary` rule, with added `{}`.
+	//
+	private function parseBlock(){
+		if( $this->MatchChar('{') ){
+			$content = $this->parsePrimary();
+			if( $this->MatchChar('}') ){
+				return $content;
+			}
+		}
+	}
+
+	private function parseBlockRuleset(){
+		$block = $this->parseBlock();
+
+		if( $block ){
+			$block = $this->NewObj2('Less_Tree_Ruleset',array( null, $block));
+		}
+
+		return $block;
+	}
+
+	private function parseDetachedRuleset(){
+		$blockRuleset = $this->parseBlockRuleset();
+		if( $blockRuleset ){
+			return $this->NewObj1('Less_Tree_DetachedRuleset',$blockRuleset);
+		}
+	}
+
+	//
+	// div, .class, body > p {...}
+	//
+	private function parseRuleset(){
+		$selectors = array();
+
+		$this->save();
+
+		while( true ){
+			$s = $this->parseLessSelector();
+			if( !$s ){
+				break;
+			}
+			$selectors[] = $s;
+			$this->parseComments();
+
+			if( $s->condition && count($selectors) > 1 ){
+				$this->Error('Guards are only currently allowed on a single selector.');
+			}
+
+			if( !$this->MatchChar(',') ){
+				break;
+			}
+			if( $s->condition ){
+				$this->Error('Guards are only currently allowed on a single selector.');
+			}
+			$this->parseComments();
+		}
+
+
+		if( $selectors ){
+			$rules = $this->parseBlock();
+			if( is_array($rules) ){
+				$this->forget();
+				return $this->NewObj2('Less_Tree_Ruleset',array( $selectors, $rules)); //Less_Environment::$strictImports
+			}
+		}
+
+		// Backtrack
+		$this->furthest = $this->pos;
+		$this->restore();
+	}
+
+	/**
+	 * Custom less.php parse function for finding simple name-value css pairs
+	 * ex: width:100px;
+	 *
+	 */
+	private function parseNameValue(){
+
+		$index = $this->pos;
+		$this->save();
+
+
+		//$match = $this->MatchReg('/\\G([a-zA-Z\-]+)\s*:\s*((?:\'")?[a-zA-Z0-9\-% \.,!]+?(?:\'")?)\s*([;}])/');
+		$match = $this->MatchReg('/\\G([a-zA-Z\-]+)\s*:\s*([\'"]?[#a-zA-Z0-9\-%\.,]+?[\'"]?) *(! *important)?\s*([;}])/');
+		if( $match ){
+
+			if( $match[4] == '}' ){
+				$this->pos = $index + strlen($match[0])-1;
+			}
+
+			if( $match[3] ){
+				$match[2] .= ' !important';
+			}
+
+			return $this->NewObj4('Less_Tree_NameValue',array( $match[1], $match[2], $index, $this->env->currentFileInfo));
+		}
+
+		$this->restore();
+	}
+
+
+	private function parseRule( $tryAnonymous = null ){
+
+		$merge = false;
+		$startOfRule = $this->pos;
+
+		$c = $this->input[$this->pos];
+		if( $c === '.' || $c === '#' || $c === '&' ){
+			return;
+		}
+
+		$this->save();
+		$name = $this->MatchFuncs( array('parseVariable','parseRuleProperty'));
+
+		if( $name ){
+
+			$isVariable = is_string($name);
+
+			$value = null;
+			if( $isVariable ){
+				$value = $this->parseDetachedRuleset();
+			}
+
+			$important = null;
+			if( !$value ){
+
+				// prefer to try to parse first if its a variable or we are compressing
+				// but always fallback on the other one
+				//if( !$tryAnonymous && is_string($name) && $name[0] === '@' ){
+				if( !$tryAnonymous && (Less_Parser::$options['compress'] || $isVariable) ){
+					$value = $this->MatchFuncs( array('parseValue','parseAnonymousValue'));
+				}else{
+					$value = $this->MatchFuncs( array('parseAnonymousValue','parseValue'));
+				}
+
+				$important = $this->parseImportant();
+
+				// a name returned by this.ruleProperty() is always an array of the form:
+				// [string-1, ..., string-n, ""] or [string-1, ..., string-n, "+"]
+				// where each item is a tree.Keyword or tree.Variable
+				if( !$isVariable && is_array($name) ){
+					$nm = array_pop($name);
+					if( $nm->value ){
+						$merge = $nm->value;
+					}
+				}
+			}
+
+
+			if( $value && $this->parseEnd() ){
+				$this->forget();
+				return $this->NewObj6('Less_Tree_Rule',array( $name, $value, $important, $merge, $startOfRule, $this->env->currentFileInfo));
+			}else{
+				$this->furthest = $this->pos;
+				$this->restore();
+				if( $value && !$tryAnonymous ){
+					return $this->parseRule(true);
+				}
+			}
+		}else{
+			$this->forget();
+		}
+	}
+
+	function parseAnonymousValue(){
+
+		if( preg_match('/\\G([^@+\/\'"*`(;{}-]*);/',$this->input, $match, 0, $this->pos) ){
+			$this->pos += strlen($match[1]);
+			return $this->NewObj1('Less_Tree_Anonymous',$match[1]);
+		}
+	}
+
+	//
+	// An @import directive
+	//
+	//	 @import "lib";
+	//
+	// Depending on our environment, importing is done differently:
+	// In the browser, it's an XHR request, in Node, it would be a
+	// file-system operation. The function used for importing is
+	// stored in `import`, which we pass to the Import constructor.
+	//
+	private function parseImport(){
+
+		$this->save();
+
+		$dir = $this->MatchReg('/\\G@import?\s+/');
+
+		if( $dir ){
+			$options = $this->parseImportOptions();
+			$path = $this->MatchFuncs( array('parseEntitiesQuoted','parseEntitiesUrl'));
+
+			if( $path ){
+				$features = $this->parseMediaFeatures();
+				if( $this->MatchChar(';') ){
+					if( $features ){
+						$features = $this->NewObj1('Less_Tree_Value',$features);
+					}
+
+					$this->forget();
+					return $this->NewObj5('Less_Tree_Import',array( $path, $features, $options, $this->pos, $this->env->currentFileInfo));
+				}
+			}
+		}
+
+		$this->restore();
+	}
+
+	private function parseImportOptions(){
+
+		$options = array();
+
+		// list of options, surrounded by parens
+		if( !$this->MatchChar('(') ){
+			return $options;
+		}
+		do{
+			$optionName = $this->parseImportOption();
+			if( $optionName ){
+				$value = true;
+				switch( $optionName ){
+					case "css":
+						$optionName = "less";
+						$value = false;
+					break;
+					case "once":
+						$optionName = "multiple";
+						$value = false;
+					break;
+				}
+				$options[$optionName] = $value;
+				if( !$this->MatchChar(',') ){ break; }
+			}
+		}while( $optionName );
+		$this->expectChar(')');
+		return $options;
+	}
+
+	private function parseImportOption(){
+		$opt = $this->MatchReg('/\\G(less|css|multiple|once|inline|reference)/');
+		if( $opt ){
+			return $opt[1];
+		}
+	}
+
+	private function parseMediaFeature() {
+		$nodes = array();
+
+		do{
+			$e = $this->MatchFuncs(array('parseEntitiesKeyword','parseEntitiesVariable'));
+			if( $e ){
+				$nodes[] = $e;
+			} elseif ($this->MatchChar('(')) {
+				$p = $this->parseProperty();
+				$e = $this->parseValue();
+				if ($this->MatchChar(')')) {
+					if ($p && $e) {
+						$r = $this->NewObj7('Less_Tree_Rule', array( $p, $e, null, null, $this->pos, $this->env->currentFileInfo, true));
+						$nodes[] = $this->NewObj1('Less_Tree_Paren',$r);
+					} elseif ($e) {
+						$nodes[] = $this->NewObj1('Less_Tree_Paren',$e);
+					} else {
+						return null;
+					}
+				} else
+					return null;
+			}
+		} while ($e);
+
+		if ($nodes) {
+			return $this->NewObj1('Less_Tree_Expression',$nodes);
+		}
+	}
+
+	private function parseMediaFeatures() {
+		$features = array();
+
+		do{
+			$e = $this->parseMediaFeature();
+			if( $e ){
+				$features[] = $e;
+				if (!$this->MatchChar(',')) break;
+			}else{
+				$e = $this->parseEntitiesVariable();
+				if( $e ){
+					$features[] = $e;
+					if (!$this->MatchChar(',')) break;
+				}
+			}
+		} while ($e);
+
+		return $features ? $features : null;
+	}
+
+	private function parseMedia() {
+		if( $this->MatchReg('/\\G@media/') ){
+			$features = $this->parseMediaFeatures();
+			$rules = $this->parseBlock();
+
+			if( is_array($rules) ){
+				return $this->NewObj4('Less_Tree_Media',array( $rules, $features, $this->pos, $this->env->currentFileInfo));
+			}
+		}
+	}
+
+
+	//
+	// A CSS Directive
+	//
+	// @charset "utf-8";
+	//
+	private function parseDirective(){
+
+		if( !$this->PeekChar('@') ){
+			return;
+		}
+
+		$rules = null;
+		$index = $this->pos;
+		$hasBlock = true;
+		$hasIdentifier = false;
+		$hasExpression = false;
+		$hasUnknown = false;
+
+
+		$value = $this->MatchFuncs(array('parseImport','parseMedia'));
+		if( $value ){
+			return $value;
+		}
+
+		$this->save();
+
+		$name = $this->MatchReg('/\\G@[a-z-]+/');
+
+		if( !$name ) return;
+		$name = $name[0];
+
+
+		$nonVendorSpecificName = $name;
+		$pos = strpos($name,'-', 2);
+		if( $name[1] == '-' && $pos > 0 ){
+			$nonVendorSpecificName = "@" . substr($name, $pos + 1);
+		}
+
+
+		switch( $nonVendorSpecificName ){
+			/*
+			case "@font-face":
+			case "@viewport":
+			case "@top-left":
+			case "@top-left-corner":
+			case "@top-center":
+			case "@top-right":
+			case "@top-right-corner":
+			case "@bottom-left":
+			case "@bottom-left-corner":
+			case "@bottom-center":
+			case "@bottom-right":
+			case "@bottom-right-corner":
+			case "@left-top":
+			case "@left-middle":
+			case "@left-bottom":
+			case "@right-top":
+			case "@right-middle":
+			case "@right-bottom":
+			hasBlock = true;
+			break;
+			*/
+			case "@charset":
+				$hasIdentifier = true;
+				$hasBlock = false;
+				break;
+			case "@namespace":
+				$hasExpression = true;
+				$hasBlock = false;
+				break;
+			case "@keyframes":
+				$hasIdentifier = true;
+				break;
+			case "@host":
+			case "@page":
+			case "@document":
+			case "@supports":
+				$hasUnknown = true;
+				break;
+		}
+
+		if( $hasIdentifier ){
+			$value = $this->parseEntity();
+			if( !$value ){
+				$this->error("expected " . $name . " identifier");
+			}
+		} else if( $hasExpression ){
+			$value = $this->parseExpression();
+			if( !$value ){
+				$this->error("expected " . $name. " expression");
+			}
+		} else if ($hasUnknown) {
+
+			$value = $this->MatchReg('/\\G[^{;]+/');
+			if( $value ){
+				$value = $this->NewObj1('Less_Tree_Anonymous',trim($value[0]));
+			}
+		}
+
+		if( $hasBlock ){
+			$rules = $this->parseBlockRuleset();
+		}
+
+		if( $rules || (!$hasBlock && $value && $this->MatchChar(';'))) {
+			$this->forget();
+			return $this->NewObj5('Less_Tree_Directive',array($name, $value, $rules, $index, $this->env->currentFileInfo));
+		}
+
+		$this->restore();
+	}
+
+
+	//
+	// A Value is a comma-delimited list of Expressions
+	//
+	//	 font-family: Baskerville, Georgia, serif;
+	//
+	// In a Rule, a Value represents everything after the `:`,
+	// and before the `;`.
+	//
+	private function parseValue(){
+		$expressions = array();
+
+		do{
+			$e = $this->parseExpression();
+			if( $e ){
+				$expressions[] = $e;
+				if (! $this->MatchChar(',')) {
+					break;
+				}
+			}
+		}while($e);
+
+		if( $expressions ){
+			return $this->NewObj1('Less_Tree_Value',$expressions);
+		}
+	}
+
+	private function parseImportant (){
+		if( $this->PeekChar('!') && $this->MatchReg('/\\G! *important/') ){
+			return ' !important';
+		}
+	}
+
+	private function parseSub (){
+
+		if( $this->MatchChar('(') ){
+			$a = $this->parseAddition();
+			if( $a ){
+				$this->expectChar(')');
+				return $this->NewObj2('Less_Tree_Expression',array( array($a), true) ); //instead of $e->parens = true so the value is cached
+			}
+		}
+	}
+
+
+	/**
+	 * Parses multiplication operation
+	 *
+	 * @return Less_Tree_Operation|null
+	 */
+	function parseMultiplication(){
+
+		$return = $m = $this->parseOperand();
+		if( $return ){
+			while( true ){
+
+				$isSpaced = $this->isWhitespace( -1 );
+
+				if( $this->PeekReg('/\\G\/[*\/]/') ){
+					break;
+				}
+
+				$op = $this->MatchChar('/');
+				if( !$op ){
+					$op = $this->MatchChar('*');
+					if( !$op ){
+						break;
+					}
+				}
+
+				$a = $this->parseOperand();
+
+				if(!$a) { break; }
+
+				$m->parensInOp = true;
+				$a->parensInOp = true;
+				$return = $this->NewObj3('Less_Tree_Operation',array( $op, array( $return, $a ), $isSpaced) );
+			}
+		}
+		return $return;
+
+	}
+
+
+	/**
+	 * Parses an addition operation
+	 *
+	 * @return Less_Tree_Operation|null
+	 */
+	private function parseAddition (){
+
+		$return = $m = $this->parseMultiplication();
+		if( $return ){
+			while( true ){
+
+				$isSpaced = $this->isWhitespace( -1 );
+
+				$op = $this->MatchReg('/\\G[-+]\s+/');
+				if( $op ){
+					$op = $op[0];
+				}else{
+					if( !$isSpaced ){
+						$op = $this->match(array('#+','#-'));
+					}
+					if( !$op ){
+						break;
+					}
+				}
+
+				$a = $this->parseMultiplication();
+				if( !$a ){
+					break;
+				}
+
+				$m->parensInOp = true;
+				$a->parensInOp = true;
+				$return = $this->NewObj3('Less_Tree_Operation',array($op, array($return, $a), $isSpaced));
+			}
+		}
+
+		return $return;
+	}
+
+
+	/**
+	 * Parses the conditions
+	 *
+	 * @return Less_Tree_Condition|null
+	 */
+	private function parseConditions() {
+		$index = $this->pos;
+		$return = $a = $this->parseCondition();
+		if( $a ){
+			while( true ){
+				if( !$this->PeekReg('/\\G,\s*(not\s*)?\(/') ||  !$this->MatchChar(',') ){
+					break;
+				}
+				$b = $this->parseCondition();
+				if( !$b ){
+					break;
+				}
+
+				$return = $this->NewObj4('Less_Tree_Condition',array('or', $return, $b, $index));
+			}
+			return $return;
+		}
+	}
+
+	private function parseCondition() {
+		$index = $this->pos;
+		$negate = false;
+		$c = null;
+
+		if ($this->MatchReg('/\\Gnot/')) $negate = true;
+		$this->expectChar('(');
+		$a = $this->MatchFuncs(array('parseAddition','parseEntitiesKeyword','parseEntitiesQuoted'));
+
+		if( $a ){
+			$op = $this->MatchReg('/\\G(?:>=|<=|=<|[<=>])/');
+			if( $op ){
+				$b = $this->MatchFuncs(array('parseAddition','parseEntitiesKeyword','parseEntitiesQuoted'));
+				if( $b ){
+					$c = $this->NewObj5('Less_Tree_Condition',array($op[0], $a, $b, $index, $negate));
+				} else {
+					$this->Error('Unexpected expression');
+				}
+			} else {
+				$k = $this->NewObj1('Less_Tree_Keyword','true');
+				$c = $this->NewObj5('Less_Tree_Condition',array('=', $a, $k, $index, $negate));
+			}
+			$this->expectChar(')');
+			return $this->MatchReg('/\\Gand/') ? $this->NewObj3('Less_Tree_Condition',array('and', $c, $this->parseCondition())) : $c;
+		}
+	}
+
+	/**
+	 * An operand is anything that can be part of an operation,
+	 * such as a Color, or a Variable
+	 *
+	 */
+	private function parseOperand (){
+
+		$negate = false;
+		$offset = $this->pos+1;
+		if( $offset >= $this->input_len ){
+			return;
+		}
+		$char = $this->input[$offset];
+		if( $char === '@' || $char === '(' ){
+			$negate = $this->MatchChar('-');
+		}
+
+		$o = $this->MatchFuncs(array('parseSub','parseEntitiesDimension','parseEntitiesColor','parseEntitiesVariable','parseEntitiesCall'));
+
+		if( $negate ){
+			$o->parensInOp = true;
+			$o = $this->NewObj1('Less_Tree_Negative',$o);
+		}
+
+		return $o;
+	}
+
+
+	/**
+	 * Expressions either represent mathematical operations,
+	 * or white-space delimited Entities.
+	 *
+	 *	 1px solid black
+	 *	 @var * 2
+	 *
+	 * @return Less_Tree_Expression|null
+	 */
+	private function parseExpression (){
+		$entities = array();
+
+		do{
+			$e = $this->MatchFuncs(array('parseAddition','parseEntity'));
+			if( $e ){
+				$entities[] = $e;
+				// operations do not allow keyword "/" dimension (e.g. small/20px) so we support that here
+				if( !$this->PeekReg('/\\G\/[\/*]/') ){
+					$delim = $this->MatchChar('/');
+					if( $delim ){
+						$entities[] = $this->NewObj1('Less_Tree_Anonymous',$delim);
+					}
+				}
+			}
+		}while($e);
+
+		if( $entities ){
+			return $this->NewObj1('Less_Tree_Expression',$entities);
+		}
+	}
+
+
+	/**
+	 * Parse a property
+	 * eg: 'min-width', 'orientation', etc
+	 *
+	 * @return string
+	 */
+	private function parseProperty (){
+		$name = $this->MatchReg('/\\G(\*?-?[_a-zA-Z0-9-]+)\s*:/');
+		if( $name ){
+			return $name[1];
+		}
+	}
+
+
+	/**
+	 * Parse a rule property
+	 * eg: 'color', 'width', 'height', etc
+	 *
+	 * @return string
+	 */
+	private function parseRuleProperty(){
+		$offset = $this->pos;
+		$name = array();
+		$index = array();
+		$length = 0;
+
+
+		$this->rulePropertyMatch('/\\G(\*?)/', $offset, $length, $index, $name );
+		while( $this->rulePropertyMatch('/\\G((?:[\w-]+)|(?:@\{[\w-]+\}))/', $offset, $length, $index, $name )); // !
+
+		if( (count($name) > 1) && $this->rulePropertyMatch('/\\G\s*((?:\+_|\+)?)\s*:/', $offset, $length, $index, $name) ){
+			// at last, we have the complete match now. move forward,
+			// convert name particles to tree objects and return:
+			$this->skipWhitespace($length);
+
+			if( $name[0] === '' ){
+				array_shift($name);
+				array_shift($index);
+			}
+			foreach($name as $k => $s ){
+				if( !$s || $s[0] !== '@' ){
+					$name[$k] = $this->NewObj1('Less_Tree_Keyword',$s);
+				}else{
+					$name[$k] = $this->NewObj3('Less_Tree_Variable',array('@' . substr($s,2,-1), $index[$k], $this->env->currentFileInfo));
+				}
+			}
+			return $name;
+		}
+
+
+	}
+
+	private function rulePropertyMatch( $re, &$offset, &$length,  &$index, &$name ){
+		preg_match($re, $this->input, $a, 0, $offset);
+		if( $a ){
+			$index[] = $this->pos + $length;
+			$length += strlen($a[0]);
+			$offset += strlen($a[0]);
+			$name[] = $a[1];
+			return true;
+		}
+	}
+
+	public static function serializeVars( $vars ){
+		$s = '';
+
+		foreach($vars as $name => $value){
+			$s .= (($name[0] === '@') ? '' : '@') . $name .': '. $value . ((substr($value,-1) === ';') ? '' : ';');
+		}
+
+		return $s;
+	}
+
+
+	/**
+	 * Some versions of php have trouble with method_exists($a,$b) if $a is not an object
+	 *
+	 * @param string $b
+	 */
+	public static function is_method($a,$b){
+		return is_object($a) && method_exists($a,$b);
+	}
+
+
+	/**
+	 * Round numbers similarly to javascript
+	 * eg: 1.499999 to 1 instead of 2
+	 *
+	 */
+	public static function round($i, $precision = 0){
+
+		$precision = pow(10,$precision);
+		$i = $i*$precision;
+
+		$ceil = ceil($i);
+		$floor = floor($i);
+		if( ($ceil - $i) <= ($i - $floor) ){
+			return $ceil/$precision;
+		}else{
+			return $floor/$precision;
+		}
+	}
+
+
+	/**
+	 * Create Less_Tree_* objects and optionally generate a cache string
+	 *
+	 * @return mixed
+	 */
+	public function NewObj0($class){
+		$obj = new $class();
+		if( $this->CacheEnabled() ){
+			$obj->cache_string = ' new '.$class.'()';
+		}
+		return $obj;
+	}
+
+	public function NewObj1($class, $arg){
+		$obj = new $class( $arg );
+		if( $this->CacheEnabled() ){
+			$obj->cache_string = ' new '.$class.'('.Less_Parser::ArgString($arg).')';
+		}
+		return $obj;
+	}
+
+	public function NewObj2($class, $args){
+		$obj = new $class( $args[0], $args[1] );
+		if( $this->CacheEnabled() ){
+			$this->ObjCache( $obj, $class, $args);
+		}
+		return $obj;
+	}
+
+	public function NewObj3($class, $args){
+		$obj = new $class( $args[0], $args[1], $args[2] );
+		if( $this->CacheEnabled() ){
+			$this->ObjCache( $obj, $class, $args);
+		}
+		return $obj;
+	}
+
+	public function NewObj4($class, $args){
+		$obj = new $class( $args[0], $args[1], $args[2], $args[3] );
+		if( $this->CacheEnabled() ){
+			$this->ObjCache( $obj, $class, $args);
+		}
+		return $obj;
+	}
+
+	public function NewObj5($class, $args){
+		$obj = new $class( $args[0], $args[1], $args[2], $args[3], $args[4] );
+		if( $this->CacheEnabled() ){
+			$this->ObjCache( $obj, $class, $args);
+		}
+		return $obj;
+	}
+
+	public function NewObj6($class, $args){
+		$obj = new $class( $args[0], $args[1], $args[2], $args[3], $args[4], $args[5] );
+		if( $this->CacheEnabled() ){
+			$this->ObjCache( $obj, $class, $args);
+		}
+		return $obj;
+	}
+
+	public function NewObj7($class, $args){
+		$obj = new $class( $args[0], $args[1], $args[2], $args[3], $args[4], $args[5], $args[6] );
+		if( $this->CacheEnabled() ){
+			$this->ObjCache( $obj, $class, $args);
+		}
+		return $obj;
+	}
+
+	//caching
+	public function ObjCache($obj, $class, $args=array()){
+		$obj->cache_string = ' new '.$class.'('. self::ArgCache($args).')';
+	}
+
+	public function ArgCache($args){
+		return implode(',',array_map( array('Less_Parser','ArgString'),$args));
+	}
+
+
+	/**
+	 * Convert an argument to a string for use in the parser cache
+	 *
+	 * @return string
+	 */
+	public static function ArgString($arg){
+
+		$type = gettype($arg);
+
+		if( $type === 'object'){
+			$string = $arg->cache_string;
+			unset($arg->cache_string);
+			return $string;
+
+		}elseif( $type === 'array' ){
+			$string = ' Array(';
+			foreach($arg as $k => $a){
+				$string .= var_export($k,true).' => '.self::ArgString($a).',';
+			}
+			return $string . ')';
+		}
+
+		return var_export($arg,true);
+	}
+
+	public function Error($msg){
+		throw new Less_Exception_Parser($msg, null, $this->furthest, $this->env->currentFileInfo);
+	}
+
+	public static function WinPath($path){
+		return str_replace('\\', '/', $path);
+	}
+
+	public function CacheEnabled(){
+		return (Less_Parser::$options['cache_method'] && (Less_Cache::$cache_dir || (Less_Parser::$options['cache_method'] == 'callback')));
+	}
+
+}
+
+
+ 
+
+/**
+ * Utility for css colors
+ *
+ * @package Less
+ * @subpackage color
+ */
+class Less_Colors {
+
+	public static $colors = array(
+			'aliceblue'=>'#f0f8ff',
+			'antiquewhite'=>'#faebd7',
+			'aqua'=>'#00ffff',
+			'aquamarine'=>'#7fffd4',
+			'azure'=>'#f0ffff',
+			'beige'=>'#f5f5dc',
+			'bisque'=>'#ffe4c4',
+			'black'=>'#000000',
+			'blanchedalmond'=>'#ffebcd',
+			'blue'=>'#0000ff',
+			'blueviolet'=>'#8a2be2',
+			'brown'=>'#a52a2a',
+			'burlywood'=>'#deb887',
+			'cadetblue'=>'#5f9ea0',
+			'chartreuse'=>'#7fff00',
+			'chocolate'=>'#d2691e',
+			'coral'=>'#ff7f50',
+			'cornflowerblue'=>'#6495ed',
+			'cornsilk'=>'#fff8dc',
+			'crimson'=>'#dc143c',
+			'cyan'=>'#00ffff',
+			'darkblue'=>'#00008b',
+			'darkcyan'=>'#008b8b',
+			'darkgoldenrod'=>'#b8860b',
+			'darkgray'=>'#a9a9a9',
+			'darkgrey'=>'#a9a9a9',
+			'darkgreen'=>'#006400',
+			'darkkhaki'=>'#bdb76b',
+			'darkmagenta'=>'#8b008b',
+			'darkolivegreen'=>'#556b2f',
+			'darkorange'=>'#ff8c00',
+			'darkorchid'=>'#9932cc',
+			'darkred'=>'#8b0000',
+			'darksalmon'=>'#e9967a',
+			'darkseagreen'=>'#8fbc8f',
+			'darkslateblue'=>'#483d8b',
+			'darkslategray'=>'#2f4f4f',
+			'darkslategrey'=>'#2f4f4f',
+			'darkturquoise'=>'#00ced1',
+			'darkviolet'=>'#9400d3',
+			'deeppink'=>'#ff1493',
+			'deepskyblue'=>'#00bfff',
+			'dimgray'=>'#696969',
+			'dimgrey'=>'#696969',
+			'dodgerblue'=>'#1e90ff',
+			'firebrick'=>'#b22222',
+			'floralwhite'=>'#fffaf0',
+			'forestgreen'=>'#228b22',
+			'fuchsia'=>'#ff00ff',
+			'gainsboro'=>'#dcdcdc',
+			'ghostwhite'=>'#f8f8ff',
+			'gold'=>'#ffd700',
+			'goldenrod'=>'#daa520',
+			'gray'=>'#808080',
+			'grey'=>'#808080',
+			'green'=>'#008000',
+			'greenyellow'=>'#adff2f',
+			'honeydew'=>'#f0fff0',
+			'hotpink'=>'#ff69b4',
+			'indianred'=>'#cd5c5c',
+			'indigo'=>'#4b0082',
+			'ivory'=>'#fffff0',
+			'khaki'=>'#f0e68c',
+			'lavender'=>'#e6e6fa',
+			'lavenderblush'=>'#fff0f5',
+			'lawngreen'=>'#7cfc00',
+			'lemonchiffon'=>'#fffacd',
+			'lightblue'=>'#add8e6',
+			'lightcoral'=>'#f08080',
+			'lightcyan'=>'#e0ffff',
+			'lightgoldenrodyellow'=>'#fafad2',
+			'lightgray'=>'#d3d3d3',
+			'lightgrey'=>'#d3d3d3',
+			'lightgreen'=>'#90ee90',
+			'lightpink'=>'#ffb6c1',
+			'lightsalmon'=>'#ffa07a',
+			'lightseagreen'=>'#20b2aa',
+			'lightskyblue'=>'#87cefa',
+			'lightslategray'=>'#778899',
+			'lightslategrey'=>'#778899',
+			'lightsteelblue'=>'#b0c4de',
+			'lightyellow'=>'#ffffe0',
+			'lime'=>'#00ff00',
+			'limegreen'=>'#32cd32',
+			'linen'=>'#faf0e6',
+			'magenta'=>'#ff00ff',
+			'maroon'=>'#800000',
+			'mediumaquamarine'=>'#66cdaa',
+			'mediumblue'=>'#0000cd',
+			'mediumorchid'=>'#ba55d3',
+			'mediumpurple'=>'#9370d8',
+			'mediumseagreen'=>'#3cb371',
+			'mediumslateblue'=>'#7b68ee',
+			'mediumspringgreen'=>'#00fa9a',
+			'mediumturquoise'=>'#48d1cc',
+			'mediumvioletred'=>'#c71585',
+			'midnightblue'=>'#191970',
+			'mintcream'=>'#f5fffa',
+			'mistyrose'=>'#ffe4e1',
+			'moccasin'=>'#ffe4b5',
+			'navajowhite'=>'#ffdead',
+			'navy'=>'#000080',
+			'oldlace'=>'#fdf5e6',
+			'olive'=>'#808000',
+			'olivedrab'=>'#6b8e23',
+			'orange'=>'#ffa500',
+			'orangered'=>'#ff4500',
+			'orchid'=>'#da70d6',
+			'palegoldenrod'=>'#eee8aa',
+			'palegreen'=>'#98fb98',
+			'paleturquoise'=>'#afeeee',
+			'palevioletred'=>'#d87093',
+			'papayawhip'=>'#ffefd5',
+			'peachpuff'=>'#ffdab9',
+			'peru'=>'#cd853f',
+			'pink'=>'#ffc0cb',
+			'plum'=>'#dda0dd',
+			'powderblue'=>'#b0e0e6',
+			'purple'=>'#800080',
+			'red'=>'#ff0000',
+			'rosybrown'=>'#bc8f8f',
+			'royalblue'=>'#4169e1',
+			'saddlebrown'=>'#8b4513',
+			'salmon'=>'#fa8072',
+			'sandybrown'=>'#f4a460',
+			'seagreen'=>'#2e8b57',
+			'seashell'=>'#fff5ee',
+			'sienna'=>'#a0522d',
+			'silver'=>'#c0c0c0',
+			'skyblue'=>'#87ceeb',
+			'slateblue'=>'#6a5acd',
+			'slategray'=>'#708090',
+			'slategrey'=>'#708090',
+			'snow'=>'#fffafa',
+			'springgreen'=>'#00ff7f',
+			'steelblue'=>'#4682b4',
+			'tan'=>'#d2b48c',
+			'teal'=>'#008080',
+			'thistle'=>'#d8bfd8',
+			'tomato'=>'#ff6347',
+			'turquoise'=>'#40e0d0',
+			'violet'=>'#ee82ee',
+			'wheat'=>'#f5deb3',
+			'white'=>'#ffffff',
+			'whitesmoke'=>'#f5f5f5',
+			'yellow'=>'#ffff00',
+			'yellowgreen'=>'#9acd32'
+		);
+
+	public static function hasOwnProperty($color) {
+		return isset(self::$colors[$color]);
+	}
+
+
+	public static function color($color) {
+		return self::$colors[$color];
+	}
+
+}
+ 
+
+
+/**
+ * Environment
+ *
+ * @package Less
+ * @subpackage environment
+ */
+class Less_Environment{
+
+	//public $paths = array();				// option - unmodified - paths to search for imports on
+	//public static $files = array();		// list of files that have been imported, used for import-once
+	//public $rootpath;						// option - rootpath to append to URL's
+	//public static $strictImports = null;	// option -
+	//public $insecure;						// option - whether to allow imports from insecure ssl hosts
+	//public $processImports;				// option - whether to process imports. if false then imports will not be imported
+	//public $javascriptEnabled;			// option - whether JavaScript is enabled. if undefined, defaults to true
+	//public $useFileCache;					// browser only - whether to use the per file session cache
+	public $currentFileInfo;				// information about the current file - for error reporting and importing and making urls relative etc.
+
+	public $importMultiple = false; 		// whether we are currently importing multiple copies
+
+
+	/**
+	 * @var array
+	 */
+	public $frames = array();
+
+	/**
+	 * @var array
+	 */
+	public $mediaBlocks = array();
+
+	/**
+	 * @var array
+	 */
+	public $mediaPath = array();
+
+	public static $parensStack = 0;
+
+	public static $tabLevel = 0;
+
+	public static $lastRule = false;
+
+	public static $_outputMap;
+
+	public static $mixin_stack = 0;
+
+	/**
+	 * @var array
+	 */
+	public $functions = array();
+
+
+	public function Init(){
+
+		self::$parensStack = 0;
+		self::$tabLevel = 0;
+		self::$lastRule = false;
+		self::$mixin_stack = 0;
+
+		if( Less_Parser::$options['compress'] ){
+
+			Less_Environment::$_outputMap = array(
+				','	=> ',',
+				': ' => ':',
+				''  => '',
+				' ' => ' ',
+				':' => ' :',
+				'+' => '+',
+				'~' => '~',
+				'>' => '>',
+				'|' => '|',
+		        '^' => '^',
+		        '^^' => '^^'
+			);
+
+		}else{
+
+			Less_Environment::$_outputMap = array(
+				','	=> ', ',
+				': ' => ': ',
+				''  => '',
+				' ' => ' ',
+				':' => ' :',
+				'+' => ' + ',
+				'~' => ' ~ ',
+				'>' => ' > ',
+				'|' => '|',
+		        '^' => ' ^ ',
+		        '^^' => ' ^^ '
+			);
+
+		}
+	}
+
+
+	public function copyEvalEnv($frames = array() ){
+		$new_env = new Less_Environment();
+		$new_env->frames = $frames;
+		return $new_env;
+	}
+
+
+	public static function isMathOn(){
+		return !Less_Parser::$options['strictMath'] || Less_Environment::$parensStack;
+	}
+
+	public static function isPathRelative($path){
+		return !preg_match('/^(?:[a-z-]+:|\/)/',$path);
+	}
+
+
+	/**
+	 * Canonicalize a path by resolving references to '/./', '/../'
+	 * Does not remove leading "../"
+	 * @param string path or url
+	 * @return string Canonicalized path
+	 *
+	 */
+	public static function normalizePath($path){
+
+		$segments = explode('/',$path);
+		$segments = array_reverse($segments);
+
+		$path = array();
+		$path_len = 0;
+
+		while( $segments ){
+			$segment = array_pop($segments);
+			switch( $segment ) {
+
+				case '.':
+				break;
+
+				case '..':
+					if( !$path_len || ( $path[$path_len-1] === '..') ){
+						$path[] = $segment;
+						$path_len++;
+					}else{
+						array_pop($path);
+						$path_len--;
+					}
+				break;
+
+				default:
+					$path[] = $segment;
+					$path_len++;
+				break;
+			}
+		}
+
+		return implode('/',$path);
+	}
+
+
+	public function unshiftFrame($frame){
+		array_unshift($this->frames, $frame);
+	}
+
+	public function shiftFrame(){
+		return array_shift($this->frames);
+	}
+
+}
+ 
+
+/**
+ * Builtin functions
+ *
+ * @package Less
+ * @subpackage function
+ * @see http://lesscss.org/functions/
+ */
+class Less_Functions{
+
+	public $env;
+	public $currentFileInfo;
+
+	function __construct($env, $currentFileInfo = null ){
+		$this->env = $env;
+		$this->currentFileInfo = $currentFileInfo;
+	}
+
+	/**
+	 * @param string $op
+	 */
+	public static function operate( $op, $a, $b ){
+		switch ($op) {
+			case '+': return $a + $b;
+			case '-': return $a - $b;
+			case '*': return $a * $b;
+			case '/': return $a / $b;
+		}
+	}
+
+	public static function clamp($val, $max = 1){
+		return min( max($val, 0), $max);
+	}
+
+	public static function fround( $value ){
+
+		if( $value === 0 ){
+			return $value;
+		}
+
+		if( Less_Parser::$options['numPrecision'] ){
+			$p = pow(10, Less_Parser::$options['numPrecision']);
+			return round( $value * $p) / $p;
+		}
+		return $value;
+	}
+
+	public static function number($n){
+
+		if ($n instanceof Less_Tree_Dimension) {
+			return floatval( $n->unit->is('%') ? $n->value / 100 : $n->value);
+		} else if (is_numeric($n)) {
+			return $n;
+		} else {
+			throw new Less_Exception_Compiler("color functions take numbers as parameters");
+		}
+	}
+
+	public static function scaled($n, $size = 255 ){
+		if( $n instanceof Less_Tree_Dimension && $n->unit->is('%') ){
+			return (float)$n->value * $size / 100;
+		} else {
+			return Less_Functions::number($n);
+		}
+	}
+
+	public function rgb ($r = null, $g = null, $b = null){
+		if (is_null($r) || is_null($g) || is_null($b)) {
+			throw new Less_Exception_Compiler("rgb expects three parameters");
+		}
+		return $this->rgba($r, $g, $b, 1.0);
+	}
+
+	public function rgba($r = null, $g = null, $b = null, $a = null){
+		$rgb = array($r, $g, $b);
+		$rgb = array_map(array('Less_Functions','scaled'),$rgb);
+
+		$a = self::number($a);
+		return new Less_Tree_Color($rgb, $a);
+	}
+
+	public function hsl($h, $s, $l){
+		return $this->hsla($h, $s, $l, 1.0);
+	}
+
+	public function hsla($h, $s, $l, $a){
+
+		$h = fmod(self::number($h), 360) / 360; // Classic % operator will change float to int
+		$s = self::clamp(self::number($s));
+		$l = self::clamp(self::number($l));
+		$a = self::clamp(self::number($a));
+
+		$m2 = $l <= 0.5 ? $l * ($s + 1) : $l + $s - $l * $s;
+
+		$m1 = $l * 2 - $m2;
+
+		return $this->rgba( self::hsla_hue($h + 1/3, $m1, $m2) * 255,
+							self::hsla_hue($h, $m1, $m2) * 255,
+							self::hsla_hue($h - 1/3, $m1, $m2) * 255,
+							$a);
+	}
+
+	/**
+	 * @param double $h
+	 */
+	public function hsla_hue($h, $m1, $m2){
+		$h = $h < 0 ? $h + 1 : ($h > 1 ? $h - 1 : $h);
+		if	  ($h * 6 < 1) return $m1 + ($m2 - $m1) * $h * 6;
+		else if ($h * 2 < 1) return $m2;
+		else if ($h * 3 < 2) return $m1 + ($m2 - $m1) * (2/3 - $h) * 6;
+		else				 return $m1;
+	}
+
+	public function hsv($h, $s, $v) {
+		return $this->hsva($h, $s, $v, 1.0);
+	}
+
+	/**
+	 * @param double $a
+	 */
+	public function hsva($h, $s, $v, $a) {
+		$h = ((Less_Functions::number($h) % 360) / 360 ) * 360;
+		$s = Less_Functions::number($s);
+		$v = Less_Functions::number($v);
+		$a = Less_Functions::number($a);
+
+		$i = floor(($h / 60) % 6);
+		$f = ($h / 60) - $i;
+
+		$vs = array( $v,
+				  $v * (1 - $s),
+				  $v * (1 - $f * $s),
+				  $v * (1 - (1 - $f) * $s));
+
+		$perm = array(array(0, 3, 1),
+					array(2, 0, 1),
+					array(1, 0, 3),
+					array(1, 2, 0),
+					array(3, 1, 0),
+					array(0, 1, 2));
+
+		return $this->rgba($vs[$perm[$i][0]] * 255,
+						 $vs[$perm[$i][1]] * 255,
+						 $vs[$perm[$i][2]] * 255,
+						 $a);
+	}
+
+	public function hue($color = null){
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to hue must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		$c = $color->toHSL();
+		return new Less_Tree_Dimension(Less_Parser::round($c['h']));
+	}
+
+	public function saturation($color = null){
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to saturation must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		$c = $color->toHSL();
+		return new Less_Tree_Dimension(Less_Parser::round($c['s'] * 100), '%');
+	}
+
+	public function lightness($color = null){
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to lightness must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		$c = $color->toHSL();
+		return new Less_Tree_Dimension(Less_Parser::round($c['l'] * 100), '%');
+	}
+
+	public function hsvhue( $color = null ){
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to hsvhue must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		$hsv = $color->toHSV();
+		return new Less_Tree_Dimension( Less_Parser::round($hsv['h']) );
+	}
+
+
+	public function hsvsaturation( $color = null ){
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to hsvsaturation must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		$hsv = $color->toHSV();
+		return new Less_Tree_Dimension( Less_Parser::round($hsv['s'] * 100), '%' );
+	}
+
+	public function hsvvalue( $color = null ){
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to hsvvalue must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		$hsv = $color->toHSV();
+		return new Less_Tree_Dimension( Less_Parser::round($hsv['v'] * 100), '%' );
+	}
+
+	public function red($color = null) {
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to red must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		return new Less_Tree_Dimension( $color->rgb[0] );
+	}
+
+	public function green($color = null) {
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to green must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		return new Less_Tree_Dimension( $color->rgb[1] );
+	}
+
+	public function blue($color = null) {
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to blue must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		return new Less_Tree_Dimension( $color->rgb[2] );
+	}
+
+	public function alpha($color = null){
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to alpha must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		$c = $color->toHSL();
+		return new Less_Tree_Dimension($c['a']);
+	}
+
+	public function luma ($color = null) {
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to luma must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		return new Less_Tree_Dimension(Less_Parser::round( $color->luma() * $color->alpha * 100), '%');
+	}
+
+	public function luminance( $color = null ){
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to luminance must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		$luminance =
+			(0.2126 * $color->rgb[0] / 255)
+		  + (0.7152 * $color->rgb[1] / 255)
+		  + (0.0722 * $color->rgb[2] / 255);
+
+		return new Less_Tree_Dimension(Less_Parser::round( $luminance * $color->alpha * 100), '%');
+	}
+
+	public function saturate($color = null, $amount = null){
+		// filter: saturate(3.2);
+		// should be kept as is, so check for color
+		if ($color instanceof Less_Tree_Dimension) {
+			return null;
+		}
+
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to saturate must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$amount instanceof Less_Tree_Dimension) {
+			throw new Less_Exception_Compiler('The second argument to saturate must be a percentage' . ($amount instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		$hsl = $color->toHSL();
+
+		$hsl['s'] += $amount->value / 100;
+		$hsl['s'] = self::clamp($hsl['s']);
+
+		return $this->hsla($hsl['h'], $hsl['s'], $hsl['l'], $hsl['a']);
+	}
+
+	/**
+	 * @param Less_Tree_Dimension $amount
+	 */
+	public function desaturate($color = null, $amount = null){
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to desaturate must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$amount instanceof Less_Tree_Dimension) {
+			throw new Less_Exception_Compiler('The second argument to desaturate must be a percentage' . ($amount instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		$hsl = $color->toHSL();
+
+		$hsl['s'] -= $amount->value / 100;
+		$hsl['s'] = self::clamp($hsl['s']);
+
+		return $this->hsla($hsl['h'], $hsl['s'], $hsl['l'], $hsl['a']);
+	}
+
+
+
+	public function lighten($color = null, $amount=null){
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to lighten must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$amount instanceof Less_Tree_Dimension) {
+			throw new Less_Exception_Compiler('The second argument to lighten must be a percentage' . ($amount instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		$hsl = $color->toHSL();
+
+		$hsl['l'] += $amount->value / 100;
+		$hsl['l'] = self::clamp($hsl['l']);
+
+		return $this->hsla($hsl['h'], $hsl['s'], $hsl['l'], $hsl['a']);
+	}
+
+	public function darken($color = null, $amount = null){
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to darken must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$amount instanceof Less_Tree_Dimension) {
+			throw new Less_Exception_Compiler('The second argument to darken must be a percentage' . ($amount instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		$hsl = $color->toHSL();
+		$hsl['l'] -= $amount->value / 100;
+		$hsl['l'] = self::clamp($hsl['l']);
+
+		return $this->hsla($hsl['h'], $hsl['s'], $hsl['l'], $hsl['a']);
+	}
+
+	public function fadein($color = null, $amount = null){
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to fadein must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$amount instanceof Less_Tree_Dimension) {
+			throw new Less_Exception_Compiler('The second argument to fadein must be a percentage' . ($amount instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		$hsl = $color->toHSL();
+		$hsl['a'] += $amount->value / 100;
+		$hsl['a'] = self::clamp($hsl['a']);
+		return $this->hsla($hsl['h'], $hsl['s'], $hsl['l'], $hsl['a']);
+	}
+
+	public function fadeout($color = null, $amount = null){
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to fadeout must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$amount instanceof Less_Tree_Dimension) {
+			throw new Less_Exception_Compiler('The second argument to fadeout must be a percentage' . ($amount instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		$hsl = $color->toHSL();
+		$hsl['a'] -= $amount->value / 100;
+		$hsl['a'] = self::clamp($hsl['a']);
+		return $this->hsla($hsl['h'], $hsl['s'], $hsl['l'], $hsl['a']);
+	}
+
+	public function fade($color = null, $amount = null){
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to fade must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$amount instanceof Less_Tree_Dimension) {
+			throw new Less_Exception_Compiler('The second argument to fade must be a percentage' . ($amount instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		$hsl = $color->toHSL();
+
+		$hsl['a'] = $amount->value / 100;
+		$hsl['a'] = self::clamp($hsl['a']);
+		return $this->hsla($hsl['h'], $hsl['s'], $hsl['l'], $hsl['a']);
+	}
+
+
+
+	public function spin($color = null, $amount = null){
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to spin must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$amount instanceof Less_Tree_Dimension) {
+			throw new Less_Exception_Compiler('The second argument to spin must be a number' . ($amount instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		$hsl = $color->toHSL();
+		$hue = fmod($hsl['h'] + $amount->value, 360);
+
+		$hsl['h'] = $hue < 0 ? 360 + $hue : $hue;
+
+		return $this->hsla($hsl['h'], $hsl['s'], $hsl['l'], $hsl['a']);
+	}
+
+	//
+	// Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein
+	// http://sass-lang.com
+	//
+
+	/**
+	 * @param Less_Tree_Color $color1
+	 */
+	public function mix($color1 = null, $color2 = null, $weight = null){
+		if (!$color1 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to mix must be a color' . ($color1 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$color2 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The second argument to mix must be a color' . ($color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$weight) {
+			$weight = new Less_Tree_Dimension('50', '%');
+		}
+		if (!$weight instanceof Less_Tree_Dimension) {
+			throw new Less_Exception_Compiler('The third argument to contrast must be a percentage' . ($weight instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		$p = $weight->value / 100.0;
+		$w = $p * 2 - 1;
+		$hsl1 = $color1->toHSL();
+		$hsl2 = $color2->toHSL();
+		$a = $hsl1['a'] - $hsl2['a'];
+
+		$w1 = (((($w * $a) == -1) ? $w : ($w + $a) / (1 + $w * $a)) + 1) / 2;
+		$w2 = 1 - $w1;
+
+		$rgb = array($color1->rgb[0] * $w1 + $color2->rgb[0] * $w2,
+					 $color1->rgb[1] * $w1 + $color2->rgb[1] * $w2,
+					 $color1->rgb[2] * $w1 + $color2->rgb[2] * $w2);
+
+		$alpha = $color1->alpha * $p + $color2->alpha * (1 - $p);
+
+		return new Less_Tree_Color($rgb, $alpha);
+	}
+
+	public function greyscale($color){
+		return $this->desaturate($color, new Less_Tree_Dimension(100,'%'));
+	}
+
+
+	public function contrast( $color, $dark = null, $light = null, $threshold = null){
+		// filter: contrast(3.2);
+		// should be kept as is, so check for color
+		if (!$color instanceof Less_Tree_Color) {
+			return null;
+		}
+		if( !$light ){
+			$light = $this->rgba(255, 255, 255, 1.0);
+		}
+		if( !$dark ){
+			$dark = $this->rgba(0, 0, 0, 1.0);
+		}
+
+		if (!$dark instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The second argument to contrast must be a color' . ($dark instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$light instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The third argument to contrast must be a color' . ($light instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		//Figure out which is actually light and dark!
+		if( $dark->luma() > $light->luma() ){
+			$t = $light;
+			$light = $dark;
+			$dark = $t;
+		}
+		if( !$threshold ){
+			$threshold = 0.43;
+		} else {
+			$threshold = Less_Functions::number($threshold);
+		}
+
+		if( $color->luma() < $threshold ){
+			return $light;
+		} else {
+			return $dark;
+		}
+	}
+
+	public function e ($str){
+		if( is_string($str) ){
+			return new Less_Tree_Anonymous($str);
+		}
+		return new Less_Tree_Anonymous($str instanceof Less_Tree_JavaScript ? $str->expression : $str->value);
+	}
+
+	public function escape ($str){
+
+		$revert = array('%21'=>'!', '%2A'=>'*', '%27'=>"'",'%3F'=>'?','%26'=>'&','%2C'=>',','%2F'=>'/','%40'=>'@','%2B'=>'+','%24'=>'$');
+
+		return new Less_Tree_Anonymous(strtr(rawurlencode($str->value), $revert));
+	}
+
+
+	/**
+	 * todo: This function will need some additional work to make it work the same as less.js
+	 *
+	 */
+	public function replace( $string, $pattern, $replacement, $flags = null ){
+		$result = $string->value;
+
+		$expr = '/'.str_replace('/','\\/',$pattern->value).'/';
+		if( $flags && $flags->value){
+			$expr .= self::replace_flags($flags->value);
+		}
+
+		$result = preg_replace($expr,$replacement->value,$result);
+
+
+		if( property_exists($string,'quote') ){
+			return new Less_Tree_Quoted( $string->quote, $result, $string->escaped);
+		}
+		return new Less_Tree_Quoted( '', $result );
+	}
+
+	public static function replace_flags($flags){
+		$flags = str_split($flags,1);
+		$new_flags = '';
+
+		foreach($flags as $flag){
+			switch($flag){
+				case 'e':
+				case 'g':
+				break;
+
+				default:
+				$new_flags .= $flag;
+				break;
+			}
+		}
+
+		return $new_flags;
+	}
+
+	public function _percent(){
+		$string = func_get_arg(0);
+
+		$args = func_get_args();
+		array_shift($args);
+		$result = $string->value;
+
+		foreach($args as $arg){
+			if( preg_match('/%[sda]/i',$result, $token) ){
+				$token = $token[0];
+				$value = stristr($token, 's') ? $arg->value : $arg->toCSS();
+				$value = preg_match('/[A-Z]$/', $token) ? urlencode($value) : $value;
+				$result = preg_replace('/%[sda]/i',$value, $result, 1);
+			}
+		}
+		$result = str_replace('%%', '%', $result);
+
+		return new Less_Tree_Quoted( $string->quote , $result, $string->escaped);
+	}
+
+	public function unit( $val, $unit = null) {
+		if( !($val instanceof Less_Tree_Dimension) ){
+			throw new Less_Exception_Compiler('The first argument to unit must be a number' . ($val instanceof Less_Tree_Operation ? '. Have you forgotten parenthesis?' : '.') );
+		}
+
+		if( $unit ){
+			if( $unit instanceof Less_Tree_Keyword ){
+				$unit = $unit->value;
+			} else {
+				$unit = $unit->toCSS();
+			}
+		} else {
+			$unit = "";
+		}
+		return new Less_Tree_Dimension($val->value, $unit );
+	}
+
+	public function convert($val, $unit){
+		return $val->convertTo($unit->value);
+	}
+
+	public function round($n, $f = false) {
+
+		$fraction = 0;
+		if( $f !== false ){
+			$fraction = $f->value;
+		}
+
+		return $this->_math('Less_Parser::round',null, $n, $fraction);
+	}
+
+	public function pi(){
+		return new Less_Tree_Dimension(M_PI);
+	}
+
+	public function mod($a, $b) {
+		return new Less_Tree_Dimension( $a->value % $b->value, $a->unit);
+	}
+
+
+
+	public function pow($x, $y) {
+		if( is_numeric($x) && is_numeric($y) ){
+			$x = new Less_Tree_Dimension($x);
+			$y = new Less_Tree_Dimension($y);
+		}elseif( !($x instanceof Less_Tree_Dimension) || !($y instanceof Less_Tree_Dimension) ){
+			throw new Less_Exception_Compiler('Arguments must be numbers');
+		}
+
+		return new Less_Tree_Dimension( pow($x->value, $y->value), $x->unit );
+	}
+
+	// var mathFunctions = [{name:"ce ...
+	public function ceil( $n ){		return $this->_math('ceil', null, $n); }
+	public function floor( $n ){	return $this->_math('floor', null, $n); }
+	public function sqrt( $n ){		return $this->_math('sqrt', null, $n); }
+	public function abs( $n ){		return $this->_math('abs', null, $n); }
+
+	public function tan( $n ){		return $this->_math('tan', '', $n);	}
+	public function sin( $n ){		return $this->_math('sin', '', $n);	}
+	public function cos( $n ){		return $this->_math('cos', '', $n);	}
+
+	public function atan( $n ){		return $this->_math('atan', 'rad', $n);	}
+	public function asin( $n ){		return $this->_math('asin', 'rad', $n);	}
+	public function acos( $n ){		return $this->_math('acos', 'rad', $n);	}
+
+	private function _math() {
+		$args = func_get_args();
+		$fn = array_shift($args);
+		$unit = array_shift($args);
+
+		if ($args[0] instanceof Less_Tree_Dimension) {
+
+			if( $unit === null ){
+				$unit = $args[0]->unit;
+			}else{
+				$args[0] = $args[0]->unify();
+			}
+			$args[0] = (float)$args[0]->value;
+			return new Less_Tree_Dimension( call_user_func_array($fn, $args), $unit);
+		} else if (is_numeric($args[0])) {
+			return call_user_func_array($fn,$args);
+		} else {
+			throw new Less_Exception_Compiler("math functions take numbers as parameters");
+		}
+	}
+
+	/**
+	 * @param boolean $isMin
+	 */
+	private function _minmax( $isMin, $args ){
+
+		$arg_count = count($args);
+
+		if( $arg_count < 1 ){
+			throw new Less_Exception_Compiler( 'one or more arguments required');
+		}
+
+		$j = null;
+		$unitClone = null;
+		$unitStatic = null;
+
+
+		$order = array();	// elems only contains original argument values.
+		$values = array();	// key is the unit.toString() for unified tree.Dimension values,
+							// value is the index into the order array.
+
+
+		for( $i = 0; $i < $arg_count; $i++ ){
+			$current = $args[$i];
+			if( !($current instanceof Less_Tree_Dimension) ){
+				if( is_array($args[$i]->value) ){
+					$args[] = $args[$i]->value;
+				}
+				continue;
+			}
+
+			if( $current->unit->toString() === '' && !$unitClone ){
+				$temp = new Less_Tree_Dimension($current->value, $unitClone);
+				$currentUnified = $temp->unify();
+			}else{
+				$currentUnified = $current->unify();
+			}
+
+			if( $currentUnified->unit->toString() === "" && !$unitStatic ){
+				$unit = $unitStatic;
+			}else{
+				$unit = $currentUnified->unit->toString();
+			}
+
+			if( $unit !== '' && !$unitStatic || $unit !== '' && $order[0]->unify()->unit->toString() === "" ){
+				$unitStatic = $unit;
+			}
+
+			if( $unit != '' && !$unitClone ){
+				$unitClone = $current->unit->toString();
+			}
+
+			if( isset($values['']) && $unit !== '' && $unit === $unitStatic ){
+				$j = $values[''];
+			}elseif( isset($values[$unit]) ){
+				$j = $values[$unit];
+			}else{
+
+				if( $unitStatic && $unit !== $unitStatic ){
+					throw new Less_Exception_Compiler( 'incompatible types');
+				}
+				$values[$unit] = count($order);
+				$order[] = $current;
+				continue;
+			}
+
+
+			if( $order[$j]->unit->toString() === "" && $unitClone ){
+				$temp = new Less_Tree_Dimension( $order[$j]->value, $unitClone);
+				$referenceUnified = $temp->unify();
+			}else{
+				$referenceUnified = $order[$j]->unify();
+			}
+			if( ($isMin && $currentUnified->value < $referenceUnified->value) || (!$isMin && $currentUnified->value > $referenceUnified->value) ){
+				$order[$j] = $current;
+			}
+		}
+
+		if( count($order) == 1 ){
+			return $order[0];
+		}
+		$args = array();
+		foreach($order as $a){
+			$args[] = $a->toCSS($this->env);
+		}
+		return new Less_Tree_Anonymous( ($isMin?'min(':'max(') . implode(Less_Environment::$_outputMap[','],$args).')');
+	}
+
+	public function min(){
+		$args = func_get_args();
+		return $this->_minmax( true, $args );
+	}
+
+	public function max(){
+		$args = func_get_args();
+		return $this->_minmax( false, $args );
+	}
+
+	public function getunit($n){
+		return new Less_Tree_Anonymous($n->unit);
+	}
+
+	public function argb($color) {
+		if (!$color instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to argb must be a color' . ($dark instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		return new Less_Tree_Anonymous($color->toARGB());
+	}
+
+	public function percentage($n) {
+		return new Less_Tree_Dimension($n->value * 100, '%');
+	}
+
+	public function color($n) {
+
+		if( $n instanceof Less_Tree_Quoted ){
+			$colorCandidate = $n->value;
+			$returnColor = Less_Tree_Color::fromKeyword($colorCandidate);
+			if( $returnColor ){
+				return $returnColor;
+			}
+			if( preg_match('/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/',$colorCandidate) ){
+				return new Less_Tree_Color(substr($colorCandidate, 1));
+			}
+			throw new Less_Exception_Compiler("argument must be a color keyword or 3/6 digit hex e.g. #FFF");
+		} else {
+			throw new Less_Exception_Compiler("argument must be a string");
+		}
+	}
+
+
+	public function iscolor($n) {
+		return $this->_isa($n, 'Less_Tree_Color');
+	}
+
+	public function isnumber($n) {
+		return $this->_isa($n, 'Less_Tree_Dimension');
+	}
+
+	public function isstring($n) {
+		return $this->_isa($n, 'Less_Tree_Quoted');
+	}
+
+	public function iskeyword($n) {
+		return $this->_isa($n, 'Less_Tree_Keyword');
+	}
+
+	public function isurl($n) {
+		return $this->_isa($n, 'Less_Tree_Url');
+	}
+
+	public function ispixel($n) {
+		return $this->isunit($n, 'px');
+	}
+
+	public function ispercentage($n) {
+		return $this->isunit($n, '%');
+	}
+
+	public function isem($n) {
+		return $this->isunit($n, 'em');
+	}
+
+	/**
+	 * @param string $unit
+	 */
+	public function isunit( $n, $unit ){
+		return ($n instanceof Less_Tree_Dimension) && $n->unit->is( ( property_exists($unit,'value') ? $unit->value : $unit) ) ? new Less_Tree_Keyword('true') : new Less_Tree_Keyword('false');
+	}
+
+	/**
+	 * @param string $type
+	 */
+	private function _isa($n, $type) {
+		return is_a($n, $type) ? new Less_Tree_Keyword('true') : new Less_Tree_Keyword('false');
+	}
+
+	public function tint($color, $amount) {
+		return $this->mix( $this->rgb(255,255,255), $color, $amount);
+	}
+
+	public function shade($color, $amount) {
+		return $this->mix($this->rgb(0, 0, 0), $color, $amount);
+	}
+
+	public function extract($values, $index ){
+		$index = (int)$index->value - 1; // (1-based index)
+		// handle non-array values as an array of length 1
+		// return 'undefined' if index is invalid
+		if( property_exists($values,'value') && is_array($values->value) ){
+			if( isset($values->value[$index]) ){
+				return $values->value[$index];
+			}
+			return null;
+
+		}elseif( (int)$index === 0 ){
+			return $values;
+		}
+
+		return null;
+	}
+
+	public function length($values){
+		$n = (property_exists($values,'value') && is_array($values->value)) ? count($values->value) : 1;
+		return new Less_Tree_Dimension($n);
+	}
+
+	public function datauri($mimetypeNode, $filePathNode = null ) {
+
+		$filePath = ( $filePathNode ? $filePathNode->value : null );
+		$mimetype = $mimetypeNode->value;
+
+		$args = 2;
+		if( !$filePath ){
+			$filePath = $mimetype;
+			$args = 1;
+		}
+
+		$filePath = str_replace('\\','/',$filePath);
+		if( Less_Environment::isPathRelative($filePath) ){
+
+			if( Less_Parser::$options['relativeUrls'] ){
+				$temp = $this->currentFileInfo['currentDirectory'];
+			} else {
+				$temp = $this->currentFileInfo['entryPath'];
+			}
+
+			if( !empty($temp) ){
+				$filePath = Less_Environment::normalizePath(rtrim($temp,'/').'/'.$filePath);
+			}
+
+		}
+
+
+		// detect the mimetype if not given
+		if( $args < 2 ){
+
+			/* incomplete
+			$mime = require('mime');
+			mimetype = mime.lookup(path);
+
+			// use base 64 unless it's an ASCII or UTF-8 format
+			var charset = mime.charsets.lookup(mimetype);
+			useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0;
+			if (useBase64) mimetype += ';base64';
+			*/
+
+			$mimetype = Less_Mime::lookup($filePath);
+
+			$charset = Less_Mime::charsets_lookup($mimetype);
+			$useBase64 = !in_array($charset,array('US-ASCII', 'UTF-8'));
+			if( $useBase64 ){ $mimetype .= ';base64'; }
+
+		}else{
+			$useBase64 = preg_match('/;base64$/',$mimetype);
+		}
+
+
+		if( file_exists($filePath) ){
+			$buf = @file_get_contents($filePath);
+		}else{
+			$buf = false;
+		}
+
+
+		// IE8 cannot handle a data-uri larger than 32KB. If this is exceeded
+		// and the --ieCompat flag is enabled, return a normal url() instead.
+		$DATA_URI_MAX_KB = 32;
+		$fileSizeInKB = round( strlen($buf) / 1024 );
+		if( $fileSizeInKB >= $DATA_URI_MAX_KB ){
+			$url = new Less_Tree_Url( ($filePathNode ? $filePathNode : $mimetypeNode), $this->currentFileInfo);
+			return $url->compile($this);
+		}
+
+		if( $buf ){
+			$buf = $useBase64 ? base64_encode($buf) : rawurlencode($buf);
+			$filePath = '"data:' . $mimetype . ',' . $buf . '"';
+		}
+
+		return new Less_Tree_Url( new Less_Tree_Anonymous($filePath) );
+	}
+
+	//svg-gradient
+	public function svggradient( $direction ){
+
+		$throw_message = 'svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]';
+		$arguments = func_get_args();
+
+		if( count($arguments) < 3 ){
+			throw new Less_Exception_Compiler( $throw_message );
+		}
+
+		$stops = array_slice($arguments,1);
+		$gradientType = 'linear';
+		$rectangleDimension = 'x="0" y="0" width="1" height="1"';
+		$useBase64 = true;
+		$directionValue = $direction->toCSS();
+
+
+		switch( $directionValue ){
+			case "to bottom":
+				$gradientDirectionSvg = 'x1="0%" y1="0%" x2="0%" y2="100%"';
+				break;
+			case "to right":
+				$gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="0%"';
+				break;
+			case "to bottom right":
+				$gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="100%"';
+				break;
+			case "to top right":
+				$gradientDirectionSvg = 'x1="0%" y1="100%" x2="100%" y2="0%"';
+				break;
+			case "ellipse":
+			case "ellipse at center":
+				$gradientType = "radial";
+				$gradientDirectionSvg = 'cx="50%" cy="50%" r="75%"';
+				$rectangleDimension = 'x="-50" y="-50" width="101" height="101"';
+				break;
+			default:
+				throw new Less_Exception_Compiler( "svg-gradient direction must be 'to bottom', 'to right', 'to bottom right', 'to top right' or 'ellipse at center'" );
+		}
+
+		$returner = '<?xml version="1.0" ?>' .
+			'<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">' .
+			'<' . $gradientType . 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' . $gradientDirectionSvg . '>';
+
+		for( $i = 0; $i < count($stops); $i++ ){
+			if( is_object($stops[$i]) && property_exists($stops[$i],'value') ){
+				$color = $stops[$i]->value[0];
+				$position = $stops[$i]->value[1];
+			}else{
+				$color = $stops[$i];
+				$position = null;
+			}
+
+			if( !($color instanceof Less_Tree_Color) || (!(($i === 0 || $i+1 === count($stops)) && $position === null) && !($position instanceof Less_Tree_Dimension)) ){
+				throw new Less_Exception_Compiler( $throw_message );
+			}
+			if( $position ){
+				$positionValue = $position->toCSS();
+			}elseif( $i === 0 ){
+				$positionValue = '0%';
+			}else{
+				$positionValue = '100%';
+			}
+			$alpha = $color->alpha;
+			$returner .= '<stop offset="' . $positionValue . '" stop-color="' . $color->toRGB() . '"' . ($alpha < 1 ? ' stop-opacity="' . $alpha . '"' : '') . '/>';
+		}
+
+		$returner .= '</' . $gradientType . 'Gradient><rect ' . $rectangleDimension . ' fill="url(#gradient)" /></svg>';
+
+
+		if( $useBase64 ){
+			$returner = "'data:image/svg+xml;base64,".base64_encode($returner)."'";
+		}else{
+			$returner = "'data:image/svg+xml,".$returner."'";
+		}
+
+		return new Less_Tree_URL( new Less_Tree_Anonymous( $returner ) );
+	}
+
+
+	/**
+	 * Php version of javascript's `encodeURIComponent` function
+	 *
+	 * @param string $string The string to encode
+	 * @return string The encoded string
+	 */
+	public static function encodeURIComponent($string){
+		$revert = array('%21' => '!', '%2A' => '*', '%27' => "'", '%28' => '(', '%29' => ')');
+		return strtr(rawurlencode($string), $revert);
+	}
+
+
+	// Color Blending
+	// ref: http://www.w3.org/TR/compositing-1
+
+	public function colorBlend( $mode, $color1, $color2 ){
+		$ab = $color1->alpha;	// backdrop
+		$as = $color2->alpha;	// source
+		$r = array();			// result
+
+		$ar = $as + $ab * (1 - $as);
+		for( $i = 0; $i < 3; $i++ ){
+			$cb = $color1->rgb[$i] / 255;
+			$cs = $color2->rgb[$i] / 255;
+			$cr = call_user_func( $mode, $cb, $cs );
+			if( $ar ){
+				$cr = ($as * $cs + $ab * ($cb - $as * ($cb + $cs - $cr))) / $ar;
+			}
+			$r[$i] = $cr * 255;
+		}
+
+		return new Less_Tree_Color($r, $ar);
+	}
+
+	public function multiply($color1 = null, $color2 = null ){
+		if (!$color1 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to multiply must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$color2 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The second argument to multiply must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		return $this->colorBlend( array($this,'colorBlendMultiply'),  $color1, $color2 );
+	}
+
+	private function colorBlendMultiply($cb, $cs){
+		return $cb * $cs;
+	}
+
+	public function screen($color1 = null, $color2 = null ){
+		if (!$color1 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to screen must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$color2 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The second argument to screen must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		return $this->colorBlend( array($this,'colorBlendScreen'),  $color1, $color2 );
+	}
+
+	private function colorBlendScreen( $cb, $cs){
+		return $cb + $cs - $cb * $cs;
+	}
+
+	public function overlay($color1 = null, $color2 = null){
+		if (!$color1 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to overlay must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$color2 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The second argument to overlay must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		return $this->colorBlend( array($this,'colorBlendOverlay'),  $color1, $color2 );
+	}
+
+	private function colorBlendOverlay($cb, $cs ){
+		$cb *= 2;
+		return ($cb <= 1)
+			? $this->colorBlendMultiply($cb, $cs)
+			: $this->colorBlendScreen($cb - 1, $cs);
+	}
+
+	public function softlight($color1 = null, $color2 = null){
+		if (!$color1 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to softlight must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$color2 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The second argument to softlight must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		return $this->colorBlend( array($this,'colorBlendSoftlight'),  $color1, $color2 );
+	}
+
+	private function colorBlendSoftlight($cb, $cs ){
+		$d = 1;
+		$e = $cb;
+		if( $cs > 0.5 ){
+			$e = 1;
+			$d = ($cb > 0.25) ? sqrt($cb)
+				: ((16 * $cb - 12) * $cb + 4) * $cb;
+		}
+		return $cb - (1 - 2 * $cs) * $e * ($d - $cb);
+	}
+
+	public function hardlight($color1 = null, $color2 = null){
+		if (!$color1 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to hardlight must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$color2 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The second argument to hardlight must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		return $this->colorBlend( array($this,'colorBlendHardlight'),  $color1, $color2 );
+	}
+
+	private function colorBlendHardlight( $cb, $cs ){
+		return $this->colorBlendOverlay($cs, $cb);
+	}
+
+	public function difference($color1 = null, $color2 = null) {
+		if (!$color1 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to difference must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$color2 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The second argument to difference must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		return $this->colorBlend( array($this,'colorBlendDifference'),  $color1, $color2 );
+	}
+
+	private function colorBlendDifference( $cb, $cs ){
+		return abs($cb - $cs);
+	}
+
+	public function exclusion( $color1 = null, $color2 = null ){
+		if (!$color1 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to exclusion must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$color2 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The second argument to exclusion must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		return $this->colorBlend( array($this,'colorBlendExclusion'),  $color1, $color2 );
+	}
+
+	private function colorBlendExclusion( $cb, $cs ){
+		return $cb + $cs - 2 * $cb * $cs;
+	}
+
+	public function average($color1 = null, $color2 = null){
+		if (!$color1 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to average must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$color2 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The second argument to average must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		return $this->colorBlend( array($this,'colorBlendAverage'),  $color1, $color2 );
+	}
+
+	// non-w3c functions:
+	public function colorBlendAverage($cb, $cs ){
+		return ($cb + $cs) / 2;
+	}
+
+	public function negation($color1 = null, $color2 = null ){
+		if (!$color1 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The first argument to negation must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+		if (!$color2 instanceof Less_Tree_Color) {
+			throw new Less_Exception_Compiler('The second argument to negation must be a color' . ($color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '') );
+		}
+
+		return $this->colorBlend( array($this,'colorBlendNegation'),  $color1, $color2 );
+	}
+
+	public function colorBlendNegation($cb, $cs){
+		return 1 - abs($cb + $cs - 1);
+	}
+
+	// ~ End of Color Blending
+
+}
+ 
+
+/**
+ * Mime lookup
+ *
+ * @package Less
+ * @subpackage node
+ */
+class Less_Mime{
+
+	// this map is intentionally incomplete
+	// if you want more, install 'mime' dep
+	static $_types = array(
+	        '.htm' => 'text/html',
+	        '.html'=> 'text/html',
+	        '.gif' => 'image/gif',
+	        '.jpg' => 'image/jpeg',
+	        '.jpeg'=> 'image/jpeg',
+	        '.png' => 'image/png',
+	        '.ttf' => 'application/x-font-ttf',
+	        '.otf' => 'application/x-font-otf',
+	        '.eot' => 'application/vnd.ms-fontobject',
+	        '.woff' => 'application/x-font-woff',
+	        '.svg' => 'image/svg+xml',
+	        );
+
+	public static function lookup( $filepath ){
+		$parts = explode('.',$filepath);
+		$ext = '.'.strtolower(array_pop($parts));
+
+		if( !isset(self::$_types[$ext]) ){
+			return null;
+		}
+		return self::$_types[$ext];
+	}
+
+	public static function charsets_lookup( $type = null ){
+		// assumes all text types are UTF-8
+		return $type && preg_match('/^text\//',$type) ? 'UTF-8' : '';
+	}
+}
+ 
+
+/**
+ * Tree
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree{
+
+	public $cache_string;
+
+	public function toCSS(){
+		$output = new Less_Output();
+		$this->genCSS($output);
+		return $output->toString();
+	}
+
+
+    /**
+     * Generate CSS by adding it to the output object
+     *
+     * @param Less_Output $output The output
+     * @return void
+     */
+    public function genCSS($output){}
+
+
+	/**
+	 * @param Less_Tree_Ruleset[] $rules
+	 */
+	public static function outputRuleset( $output, $rules ){
+
+		$ruleCnt = count($rules);
+		Less_Environment::$tabLevel++;
+
+
+		// Compressed
+		if( Less_Parser::$options['compress'] ){
+			$output->add('{');
+			for( $i = 0; $i < $ruleCnt; $i++ ){
+				$rules[$i]->genCSS( $output );
+			}
+
+			$output->add( '}' );
+			Less_Environment::$tabLevel--;
+			return;
+		}
+
+
+		// Non-compressed
+		$tabSetStr = "\n".str_repeat( '  ' , Less_Environment::$tabLevel-1 );
+		$tabRuleStr = $tabSetStr.'  ';
+
+		$output->add( " {" );
+		for($i = 0; $i < $ruleCnt; $i++ ){
+			$output->add( $tabRuleStr );
+			$rules[$i]->genCSS( $output );
+		}
+		Less_Environment::$tabLevel--;
+		$output->add( $tabSetStr.'}' );
+
+	}
+
+	public function accept($visitor){}
+
+
+	public static function ReferencedArray($rules){
+		foreach($rules as $rule){
+			if( method_exists($rule, 'markReferenced') ){
+				$rule->markReferenced();
+			}
+		}
+	}
+
+
+	/**
+	 * Requires php 5.3+
+	 */
+	public static function __set_state($args){
+
+		$class = get_called_class();
+		$obj = new $class(null,null,null,null);
+		foreach($args as $key => $val){
+			$obj->$key = $val;
+		}
+		return $obj;
+	}
+
+} 
+
+/**
+ * Parser output
+ *
+ * @package Less
+ * @subpackage output
+ */
+class Less_Output{
+
+	/**
+	 * Output holder
+	 *
+	 * @var string
+	 */
+	protected $strs = array();
+
+	/**
+	 * Adds a chunk to the stack
+	 *
+	 * @param string $chunk The chunk to output
+	 * @param Less_FileInfo $fileInfo The file information
+	 * @param integer $index The index
+	 * @param mixed $mapLines
+	 */
+	public function add($chunk, $fileInfo = null, $index = 0, $mapLines = null){
+		$this->strs[] = $chunk;
+	}
+
+	/**
+	 * Is the output empty?
+	 *
+	 * @return boolean
+	 */
+	public function isEmpty(){
+		return count($this->strs) === 0;
+	}
+
+
+	/**
+	 * Converts the output to string
+	 *
+	 * @return string
+	 */
+	public function toString(){
+		return implode('',$this->strs);
+	}
+
+} 
+
+/**
+ * Visitor
+ *
+ * @package Less
+ * @subpackage visitor
+ */
+class Less_Visitor{
+
+	protected $methods = array();
+	protected $_visitFnCache = array();
+
+	public function __construct(){
+		$this->_visitFnCache = get_class_methods(get_class($this));
+		$this->_visitFnCache = array_flip($this->_visitFnCache);
+	}
+
+	public function visitObj( $node ){
+
+		$funcName = 'visit'.$node->type;
+		if( isset($this->_visitFnCache[$funcName]) ){
+
+			$visitDeeper = true;
+			$this->$funcName( $node, $visitDeeper );
+
+			if( $visitDeeper ){
+				$node->accept($this);
+			}
+
+			$funcName = $funcName . "Out";
+			if( isset($this->_visitFnCache[$funcName]) ){
+				$this->$funcName( $node );
+			}
+
+		}else{
+			$node->accept($this);
+		}
+
+		return $node;
+	}
+
+	public function visitArray( $nodes ){
+
+		array_map( array($this,'visitObj'), $nodes);
+		return $nodes;
+	}
+}
+
+ 
+
+/**
+ * Replacing Visitor
+ *
+ * @package Less
+ * @subpackage visitor
+ */
+class Less_VisitorReplacing extends Less_Visitor{
+
+	public function visitObj( $node ){
+
+		$funcName = 'visit'.$node->type;
+		if( isset($this->_visitFnCache[$funcName]) ){
+
+			$visitDeeper = true;
+			$node = $this->$funcName( $node, $visitDeeper );
+
+			if( $node ){
+				if( $visitDeeper && is_object($node) ){
+					$node->accept($this);
+				}
+
+				$funcName = $funcName . "Out";
+				if( isset($this->_visitFnCache[$funcName]) ){
+					$this->$funcName( $node );
+				}
+			}
+
+		}else{
+			$node->accept($this);
+		}
+
+		return $node;
+	}
+
+	public function visitArray( $nodes ){
+
+		$newNodes = array();
+		foreach($nodes as $node){
+			$evald = $this->visitObj($node);
+			if( $evald ){
+				if( is_array($evald) ){
+					self::flatten($evald,$newNodes);
+				}else{
+					$newNodes[] = $evald;
+				}
+			}
+		}
+		return $newNodes;
+	}
+
+	public function flatten( $arr, &$out ){
+
+		foreach($arr as $item){
+			if( !is_array($item) ){
+				$out[] = $item;
+				continue;
+			}
+
+			foreach($item as $nestedItem){
+				if( is_array($nestedItem) ){
+					self::flatten( $nestedItem, $out);
+				}else{
+					$out[] = $nestedItem;
+				}
+			}
+		}
+
+		return $out;
+	}
+
+}
+
+
+ 
+
+/**
+ * Configurable
+ *
+ * @package Less
+ * @subpackage Core
+ */
+abstract class Less_Configurable {
+
+	/**
+	 * Array of options
+	 *
+	 * @var array
+	 */
+	protected $options = array();
+
+	/**
+	 * Array of default options
+	 *
+	 * @var array
+	 */
+	protected $defaultOptions = array();
+
+
+	/**
+	 * Set options
+	 *
+	 * If $options is an object it will be converted into an array by called
+	 * it's toArray method.
+	 *
+	 * @throws Exception
+	 * @param array|object $options
+	 *
+	 */
+	public function setOptions($options){
+		$options = array_intersect_key($options,$this->defaultOptions);
+		$this->options = array_merge($this->defaultOptions, $this->options, $options);
+	}
+
+
+	/**
+	 * Get an option value by name
+	 *
+	 * If the option is empty or not set a NULL value will be returned.
+	 *
+	 * @param string $name
+	 * @param mixed $default Default value if confiuration of $name is not present
+	 * @return mixed
+	 */
+	public function getOption($name, $default = null){
+		if(isset($this->options[$name])){
+			return $this->options[$name];
+		}
+		return $default;
+	}
+
+
+	/**
+	 * Set an option
+	 *
+	 * @param string $name
+	 * @param mixed $value
+	 */
+	public function setOption($name, $value){
+		$this->options[$name] = $value;
+	}
+
+} 
+
+/**
+ * Alpha
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Alpha extends Less_Tree{
+	public $value;
+	public $type = 'Alpha';
+
+	public function __construct($val){
+		$this->value = $val;
+	}
+
+	//function accept( $visitor ){
+	//	$this->value = $visitor->visit( $this->value );
+	//}
+
+	public function compile($env){
+
+		if( is_object($this->value) ){
+			$this->value = $this->value->compile($env);
+		}
+
+		return $this;
+	}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+	public function genCSS( $output ){
+
+		$output->add( "alpha(opacity=" );
+
+		if( is_string($this->value) ){
+			$output->add( $this->value );
+		}else{
+			$this->value->genCSS( $output);
+		}
+
+		$output->add( ')' );
+	}
+
+	public function toCSS(){
+		return "alpha(opacity=" . (is_string($this->value) ? $this->value : $this->value->toCSS()) . ")";
+	}
+
+
+} 
+
+/**
+ * Anonymous
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Anonymous extends Less_Tree{
+	public $value;
+	public $quote;
+	public $index;
+	public $mapLines;
+	public $currentFileInfo;
+	public $type = 'Anonymous';
+
+	/**
+	 * @param integer $index
+	 * @param boolean $mapLines
+	 */
+	public function __construct($value, $index = null, $currentFileInfo = null, $mapLines = null ){
+		$this->value = $value;
+		$this->index = $index;
+		$this->mapLines = $mapLines;
+		$this->currentFileInfo = $currentFileInfo;
+	}
+
+	public function compile(){
+		return new Less_Tree_Anonymous($this->value, $this->index, $this->currentFileInfo, $this->mapLines);
+	}
+
+    public function compare($x){
+		if( !is_object($x) ){
+			return -1;
+		}
+
+		$left = $this->toCSS();
+		$right = $x->toCSS();
+
+		if( $left === $right ){
+			return 0;
+		}
+
+		return $left < $right ? -1 : 1;
+	}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+	public function genCSS( $output ){
+		$output->add( $this->value, $this->currentFileInfo, $this->index, $this->mapLines );
+	}
+
+	public function toCSS(){
+		return $this->value;
+	}
+
+}
+ 
+
+/**
+ * Assignment
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Assignment extends Less_Tree{
+
+	public $key;
+	public $value;
+	public $type = 'Assignment';
+
+    public function __construct($key, $val) {
+		$this->key = $key;
+		$this->value = $val;
+	}
+
+    public function accept( $visitor ){
+		$this->value = $visitor->visitObj( $this->value );
+	}
+
+	public function compile($env) {
+		return new Less_Tree_Assignment( $this->key, $this->value->compile($env));
+	}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+	public function genCSS( $output ){
+		$output->add( $this->key . '=' );
+		$this->value->genCSS( $output );
+	}
+
+	public function toCss(){
+		return $this->key . '=' . $this->value->toCSS();
+	}
+}
+ 
+
+/**
+ * Attribute
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Attribute extends Less_Tree{
+
+	public $key;
+	public $op;
+	public $value;
+	public $type = 'Attribute';
+
+    public function __construct($key, $op, $value){
+		$this->key = $key;
+		$this->op = $op;
+		$this->value = $value;
+	}
+
+    public function compile($env){
+
+		$key_obj = is_object($this->key);
+		$val_obj = is_object($this->value);
+
+		if( !$key_obj && !$val_obj ){
+			return $this;
+		}
+
+		return new Less_Tree_Attribute(
+			$key_obj ? $this->key->compile($env) : $this->key ,
+			$this->op,
+			$val_obj ? $this->value->compile($env) : $this->value);
+	}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+    public function genCSS( $output ){
+		$output->add( $this->toCSS() );
+	}
+
+    public function toCSS(){
+		$value = $this->key;
+
+		if( $this->op ){
+			$value .= $this->op;
+			$value .= (is_object($this->value) ? $this->value->toCSS() : $this->value);
+		}
+
+		return '[' . $value . ']';
+	}
+} 
+
+
+/**
+ * Call
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Call extends Less_Tree{
+    public $value;
+
+    protected $name;
+    protected $args;
+    protected $index;
+    protected $currentFileInfo;
+    public $type = 'Call';
+
+	public function __construct($name, $args, $index, $currentFileInfo = null ){
+		$this->name = $name;
+		$this->args = $args;
+		$this->index = $index;
+		$this->currentFileInfo = $currentFileInfo;
+	}
+
+    public function accept( $visitor ){
+		$this->args = $visitor->visitArray( $this->args );
+	}
+
+    //
+    // When evaluating a function call,
+    // we either find the function in `tree.functions` [1],
+    // in which case we call it, passing the  evaluated arguments,
+    // or we simply print it out as it appeared originally [2].
+    //
+    // The *functions.js* file contains the built-in functions.
+    //
+    // The reason why we evaluate the arguments, is in the case where
+    // we try to pass a variable to a function, like: `saturate(@color)`.
+    // The function should receive the value, not the variable.
+    //
+    public function compile($env=null){
+		$args = array();
+		foreach($this->args as $a){
+			$args[] = $a->compile($env);
+		}
+
+		$nameLC = strtolower($this->name);
+		switch($nameLC){
+			case '%':
+			$nameLC = '_percent';
+			break;
+
+			case 'get-unit':
+			$nameLC = 'getunit';
+			break;
+
+			case 'data-uri':
+			$nameLC = 'datauri';
+			break;
+
+			case 'svg-gradient':
+			$nameLC = 'svggradient';
+			break;
+		}
+
+		$result = null;
+		if( $nameLC === 'default' ){
+			$result = Less_Tree_DefaultFunc::compile();
+
+		}else{
+
+			if( method_exists('Less_Functions',$nameLC) ){ // 1.
+				try {
+
+					$func = new Less_Functions($env, $this->currentFileInfo);
+					$result = call_user_func_array( array($func,$nameLC),$args);
+
+				} catch (Exception $e) {
+					throw new Less_Exception_Compiler('error evaluating function `' . $this->name . '` '.$e->getMessage().' index: '. $this->index);
+				}
+			} elseif( isset( $env->functions[$nameLC] ) && is_callable( $env->functions[$nameLC] ) ) {
+				try {
+					$result = call_user_func_array( $env->functions[$nameLC], $args );
+				} catch (Exception $e) {
+					throw new Less_Exception_Compiler('error evaluating function `' . $this->name . '` '.$e->getMessage().' index: '. $this->index);
+				}
+			}
+		}
+
+		if( $result !== null ){
+			return $result;
+		}
+
+
+		return new Less_Tree_Call( $this->name, $args, $this->index, $this->currentFileInfo );
+    }
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+	public function genCSS( $output ){
+
+		$output->add( $this->name . '(', $this->currentFileInfo, $this->index );
+		$args_len = count($this->args);
+		for($i = 0; $i < $args_len; $i++ ){
+			$this->args[$i]->genCSS( $output );
+			if( $i + 1 < $args_len ){
+				$output->add( ', ' );
+			}
+		}
+
+		$output->add( ')' );
+	}
+
+
+    //public function toCSS(){
+    //    return $this->compile()->toCSS();
+    //}
+
+}
+ 
+
+/**
+ * Color
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Color extends Less_Tree{
+	public $rgb;
+	public $alpha;
+	public $isTransparentKeyword;
+	public $type = 'Color';
+
+	public function __construct($rgb, $a = 1, $isTransparentKeyword = null ){
+
+		if( $isTransparentKeyword ){
+			$this->rgb = $rgb;
+			$this->alpha = $a;
+			$this->isTransparentKeyword = true;
+			return;
+		}
+
+		$this->rgb = array();
+		if( is_array($rgb) ){
+			$this->rgb = $rgb;
+		}else if( strlen($rgb) == 6 ){
+			foreach(str_split($rgb, 2) as $c){
+				$this->rgb[] = hexdec($c);
+			}
+		}else{
+			foreach(str_split($rgb, 1) as $c){
+				$this->rgb[] = hexdec($c.$c);
+			}
+		}
+		$this->alpha = is_numeric($a) ? $a : 1;
+	}
+
+	public function compile(){
+		return $this;
+	}
+
+	public function luma(){
+		$r = $this->rgb[0] / 255;
+		$g = $this->rgb[1] / 255;
+		$b = $this->rgb[2] / 255;
+
+		$r = ($r <= 0.03928) ? $r / 12.92 : pow((($r + 0.055) / 1.055), 2.4);
+		$g = ($g <= 0.03928) ? $g / 12.92 : pow((($g + 0.055) / 1.055), 2.4);
+		$b = ($b <= 0.03928) ? $b / 12.92 : pow((($b + 0.055) / 1.055), 2.4);
+
+		return 0.2126 * $r + 0.7152 * $g + 0.0722 * $b;
+	}
+
+	/**
+	 * @see Less_Tree::genCSS
+	 */
+	public function genCSS( $output ){
+		$output->add( $this->toCSS() );
+	}
+
+	public function toCSS( $doNotCompress = false ){
+		$compress = Less_Parser::$options['compress'] && !$doNotCompress;
+		$alpha = Less_Functions::fround( $this->alpha );
+
+
+		//
+		// If we have some transparency, the only way to represent it
+		// is via `rgba`. Otherwise, we use the hex representation,
+		// which has better compatibility with older browsers.
+		// Values are capped between `0` and `255`, rounded and zero-padded.
+		//
+		if( $alpha < 1 ){
+			if( ( $alpha === 0 || $alpha === 0.0 ) && isset($this->isTransparentKeyword) && $this->isTransparentKeyword ){
+				return 'transparent';
+			}
+
+			$values = array();
+			foreach($this->rgb as $c){
+				$values[] = Less_Functions::clamp( round($c), 255);
+			}
+			$values[] = $alpha;
+
+			$glue = ($compress ? ',' : ', ');
+			return "rgba(" . implode($glue, $values) . ")";
+		}else{
+
+			$color = $this->toRGB();
+
+			if( $compress ){
+
+				// Convert color to short format
+				if( $color[1] === $color[2] && $color[3] === $color[4] && $color[5] === $color[6]) {
+					$color = '#'.$color[1] . $color[3] . $color[5];
+				}
+			}
+
+			return $color;
+		}
+	}
+
+	//
+	// Operations have to be done per-channel, if not,
+	// channels will spill onto each other. Once we have
+	// our result, in the form of an integer triplet,
+	// we create a new Color node to hold the result.
+	//
+
+	/**
+	 * @param string $op
+	 */
+	public function operate( $op, $other) {
+		$rgb = array();
+		$alpha = $this->alpha * (1 - $other->alpha) + $other->alpha;
+		for ($c = 0; $c < 3; $c++) {
+			$rgb[$c] = Less_Functions::operate( $op, $this->rgb[$c], $other->rgb[$c]);
+		}
+		return new Less_Tree_Color($rgb, $alpha);
+	}
+
+	public function toRGB(){
+		return $this->toHex($this->rgb);
+	}
+
+	public function toHSL(){
+		$r = $this->rgb[0] / 255;
+		$g = $this->rgb[1] / 255;
+		$b = $this->rgb[2] / 255;
+		$a = $this->alpha;
+
+		$max = max($r, $g, $b);
+		$min = min($r, $g, $b);
+		$l = ($max + $min) / 2;
+		$d = $max - $min;
+
+		$h = $s = 0;
+		if( $max !== $min ){
+			$s = $l > 0.5 ? $d / (2 - $max - $min) : $d / ($max + $min);
+
+			switch ($max) {
+				case $r: $h = ($g - $b) / $d + ($g < $b ? 6 : 0); break;
+				case $g: $h = ($b - $r) / $d + 2;				 break;
+				case $b: $h = ($r - $g) / $d + 4;				 break;
+			}
+			$h /= 6;
+		}
+		return array('h' => $h * 360, 's' => $s, 'l' => $l, 'a' => $a );
+	}
+
+	//Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
+    public function toHSV() {
+		$r = $this->rgb[0] / 255;
+		$g = $this->rgb[1] / 255;
+		$b = $this->rgb[2] / 255;
+		$a = $this->alpha;
+
+		$max = max($r, $g, $b);
+		$min = min($r, $g, $b);
+
+		$v = $max;
+
+		$d = $max - $min;
+		if ($max === 0) {
+			$s = 0;
+		} else {
+			$s = $d / $max;
+		}
+
+		$h = 0;
+		if( $max !== $min ){
+			switch($max){
+				case $r: $h = ($g - $b) / $d + ($g < $b ? 6 : 0); break;
+				case $g: $h = ($b - $r) / $d + 2; break;
+				case $b: $h = ($r - $g) / $d + 4; break;
+			}
+			$h /= 6;
+		}
+		return array('h'=> $h * 360, 's'=> $s, 'v'=> $v, 'a' => $a );
+	}
+
+	public function toARGB(){
+		$argb = array_merge( (array) Less_Parser::round($this->alpha * 255), $this->rgb);
+		return $this->toHex( $argb );
+	}
+
+	public function compare($x){
+
+		if( !property_exists( $x, 'rgb' ) ){
+			return -1;
+		}
+
+
+		return ($x->rgb[0] === $this->rgb[0] &&
+			$x->rgb[1] === $this->rgb[1] &&
+			$x->rgb[2] === $this->rgb[2] &&
+			$x->alpha === $this->alpha) ? 0 : -1;
+	}
+
+    public function toHex( $v ){
+
+		$ret = '#';
+		foreach($v as $c){
+			$c = Less_Functions::clamp( Less_Parser::round($c), 255);
+			if( $c < 16 ){
+				$ret .= '0';
+			}
+			$ret .= dechex($c);
+		}
+
+		return $ret;
+	}
+
+
+	/**
+	 * @param string $keyword
+	 */
+	public static function fromKeyword( $keyword ){
+		$keyword = strtolower($keyword);
+
+		if( Less_Colors::hasOwnProperty($keyword) ){
+			// detect named color
+			return new Less_Tree_Color(substr(Less_Colors::color($keyword), 1));
+		}
+
+		if( $keyword === 'transparent' ){
+			return new Less_Tree_Color( array(0, 0, 0), 0, true);
+		}
+	}
+
+}
+ 
+
+/**
+ * Comment
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Comment extends Less_Tree{
+
+	public $value;
+	public $silent;
+	public $isReferenced;
+	public $currentFileInfo;
+	public $type = 'Comment';
+
+	public function __construct($value, $silent, $index = null, $currentFileInfo = null ){
+		$this->value = $value;
+		$this->silent = !! $silent;
+		$this->currentFileInfo = $currentFileInfo;
+	}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+	public function genCSS( $output ){
+		//if( $this->debugInfo ){
+			//$output->add( tree.debugInfo($env, $this), $this->currentFileInfo, $this->index);
+		//}
+		$output->add( trim($this->value) );//TODO shouldn't need to trim, we shouldn't grab the \n
+	}
+
+	public function toCSS(){
+		return Less_Parser::$options['compress'] ? '' : $this->value;
+	}
+
+	public function isSilent(){
+		$isReference = ($this->currentFileInfo && isset($this->currentFileInfo['reference']) && (!isset($this->isReferenced) || !$this->isReferenced) );
+		$isCompressed = Less_Parser::$options['compress'] && !preg_match('/^\/\*!/', $this->value);
+		return $this->silent || $isReference || $isCompressed;
+	}
+
+	public function compile(){
+		return $this;
+	}
+
+	public function markReferenced(){
+		$this->isReferenced = true;
+	}
+
+}
+ 
+
+/**
+ * Condition
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Condition extends Less_Tree{
+
+	public $op;
+	public $lvalue;
+	public $rvalue;
+	public $index;
+	public $negate;
+	public $type = 'Condition';
+
+	public function __construct($op, $l, $r, $i = 0, $negate = false) {
+		$this->op = trim($op);
+		$this->lvalue = $l;
+		$this->rvalue = $r;
+		$this->index = $i;
+		$this->negate = $negate;
+	}
+
+	public function accept($visitor){
+		$this->lvalue = $visitor->visitObj( $this->lvalue );
+		$this->rvalue = $visitor->visitObj( $this->rvalue );
+	}
+
+    public function compile($env) {
+		$a = $this->lvalue->compile($env);
+		$b = $this->rvalue->compile($env);
+
+		switch( $this->op ){
+			case 'and':
+				$result = $a && $b;
+			break;
+
+			case 'or':
+				$result = $a || $b;
+			break;
+
+			default:
+				if( Less_Parser::is_method($a, 'compare') ){
+					$result = $a->compare($b);
+				}elseif( Less_Parser::is_method($b, 'compare') ){
+					$result = $b->compare($a);
+				}else{
+					throw new Less_Exception_Compiler('Unable to perform comparison', null, $this->index);
+				}
+
+				switch ($result) {
+					case -1:
+					$result = $this->op === '<' || $this->op === '=<' || $this->op === '<=';
+					break;
+
+					case  0:
+					$result = $this->op === '=' || $this->op === '>=' || $this->op === '=<' || $this->op === '<=';
+					break;
+
+					case  1:
+					$result = $this->op === '>' || $this->op === '>=';
+					break;
+				}
+			break;
+		}
+
+		return $this->negate ? !$result : $result;
+    }
+
+}
+ 
+
+/**
+ * DefaultFunc
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_DefaultFunc{
+
+	static $error_;
+	static $value_;
+
+    public static function compile(){
+		if( self::$error_ ){
+			throw new Exception(self::$error_);
+		}
+		if( self::$value_ !== null ){
+			return self::$value_ ? new Less_Tree_Keyword('true') : new Less_Tree_Keyword('false');
+		}
+	}
+
+    public static function value( $v ){
+		self::$value_ = $v;
+	}
+
+    public static function error( $e ){
+		self::$error_ = $e;
+	}
+
+    public static function reset(){
+		self::$value_ = self::$error_ = null;
+	}
+} 
+
+/**
+ * DetachedRuleset
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_DetachedRuleset extends Less_Tree{
+
+	public $ruleset;
+	public $frames;
+	public $type = 'DetachedRuleset';
+
+    public function __construct( $ruleset, $frames = null ){
+		$this->ruleset = $ruleset;
+		$this->frames = $frames;
+	}
+
+    public function accept($visitor) {
+		$this->ruleset = $visitor->visitObj($this->ruleset);
+	}
+
+    public function compile($env){
+		if( $this->frames ){
+			$frames = $this->frames;
+		}else{
+			$frames = $env->frames;
+		}
+		return new Less_Tree_DetachedRuleset($this->ruleset, $frames);
+	}
+
+    public function callEval($env) {
+		if( $this->frames ){
+			return $this->ruleset->compile( $env->copyEvalEnv( array_merge($this->frames,$env->frames) ) );
+		}
+		return $this->ruleset->compile( $env );
+	}
+}
+
+ 
+
+/**
+ * Dimension
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Dimension extends Less_Tree{
+
+	public $value;
+	public $unit;
+	public $type = 'Dimension';
+
+    public function __construct($value, $unit = null){
+        $this->value = floatval($value);
+
+		if( $unit && ($unit instanceof Less_Tree_Unit) ){
+			$this->unit = $unit;
+		}elseif( $unit ){
+			$this->unit = new Less_Tree_Unit( array($unit) );
+		}else{
+			$this->unit = new Less_Tree_Unit( );
+		}
+    }
+
+    public function accept( $visitor ){
+		$this->unit = $visitor->visitObj( $this->unit );
+	}
+
+    public function compile(){
+        return $this;
+    }
+
+    public function toColor() {
+        return new Less_Tree_Color(array($this->value, $this->value, $this->value));
+    }
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+	public function genCSS( $output ){
+
+		if( Less_Parser::$options['strictUnits'] && !$this->unit->isSingular() ){
+			throw new Less_Exception_Compiler("Multiple units in dimension. Correct the units or use the unit function. Bad unit: ".$this->unit->toString());
+		}
+
+		$value = Less_Functions::fround( $this->value );
+		$strValue = (string)$value;
+
+		if( $value !== 0 && $value < 0.000001 && $value > -0.000001 ){
+			// would be output 1e-6 etc.
+			$strValue = number_format($strValue,10);
+			$strValue = preg_replace('/\.?0+$/','', $strValue);
+		}
+
+		if( Less_Parser::$options['compress'] ){
+			// Zero values doesn't need a unit
+			if( $value === 0 && $this->unit->isLength() ){
+				$output->add( $strValue );
+				return $strValue;
+			}
+
+			// Float values doesn't need a leading zero
+			if( $value > 0 && $value < 1 && $strValue[0] === '0' ){
+				$strValue = substr($strValue,1);
+			}
+		}
+
+		$output->add( $strValue );
+		$this->unit->genCSS( $output );
+	}
+
+    public function __toString(){
+        return $this->toCSS();
+    }
+
+    // In an operation between two Dimensions,
+    // we default to the first Dimension's unit,
+    // so `1px + 2em` will yield `3px`.
+
+    /**
+     * @param string $op
+     */
+    public function operate( $op, $other){
+
+		$value = Less_Functions::operate( $op, $this->value, $other->value);
+		$unit = clone $this->unit;
+
+		if( $op === '+' || $op === '-' ){
+
+			if( !$unit->numerator && !$unit->denominator ){
+				$unit->numerator = $other->unit->numerator;
+				$unit->denominator = $other->unit->denominator;
+			}elseif( !$other->unit->numerator && !$other->unit->denominator ){
+				// do nothing
+			}else{
+				$other = $other->convertTo( $this->unit->usedUnits());
+
+				if( Less_Parser::$options['strictUnits'] && $other->unit->toString() !== $unit->toCSS() ){
+					throw new Less_Exception_Compiler("Incompatible units. Change the units or use the unit function. Bad units: '".$unit->toString() . "' and ".$other->unit->toString()+"'.");
+				}
+
+				$value = Less_Functions::operate( $op, $this->value, $other->value);
+			}
+		}elseif( $op === '*' ){
+			$unit->numerator = array_merge($unit->numerator, $other->unit->numerator);
+			$unit->denominator = array_merge($unit->denominator, $other->unit->denominator);
+			sort($unit->numerator);
+			sort($unit->denominator);
+			$unit->cancel();
+		}elseif( $op === '/' ){
+			$unit->numerator = array_merge($unit->numerator, $other->unit->denominator);
+			$unit->denominator = array_merge($unit->denominator, $other->unit->numerator);
+			sort($unit->numerator);
+			sort($unit->denominator);
+			$unit->cancel();
+		}
+		return new Less_Tree_Dimension( $value, $unit);
+    }
+
+	public function compare($other) {
+		if ($other instanceof Less_Tree_Dimension) {
+
+			if( $this->unit->isEmpty() || $other->unit->isEmpty() ){
+				$a = $this;
+				$b = $other;
+			} else {
+				$a = $this->unify();
+				$b = $other->unify();
+				if( $a->unit->compare($b->unit) !== 0 ){
+					return -1;
+				}
+			}
+			$aValue = $a->value;
+			$bValue = $b->value;
+
+			if ($bValue > $aValue) {
+				return -1;
+			} elseif ($bValue < $aValue) {
+				return 1;
+			} else {
+				return 0;
+			}
+		} else {
+			return -1;
+		}
+	}
+
+    public function unify() {
+		return $this->convertTo(array('length'=> 'px', 'duration'=> 's', 'angle' => 'rad' ));
+	}
+
+    public function convertTo($conversions) {
+		$value = $this->value;
+		$unit = clone $this->unit;
+
+		if( is_string($conversions) ){
+			$derivedConversions = array();
+			foreach( Less_Tree_UnitConversions::$groups as $i ){
+				if( isset(Less_Tree_UnitConversions::${$i}[$conversions]) ){
+					$derivedConversions = array( $i => $conversions);
+				}
+			}
+			$conversions = $derivedConversions;
+		}
+
+
+		foreach($conversions as $groupName => $targetUnit){
+			$group = Less_Tree_UnitConversions::${$groupName};
+
+			//numerator
+			foreach($unit->numerator as $i => $atomicUnit){
+				$atomicUnit = $unit->numerator[$i];
+				if( !isset($group[$atomicUnit]) ){
+					continue;
+				}
+
+				$value = $value * ($group[$atomicUnit] / $group[$targetUnit]);
+
+				$unit->numerator[$i] = $targetUnit;
+			}
+
+			//denominator
+			foreach($unit->denominator as $i => $atomicUnit){
+				$atomicUnit = $unit->denominator[$i];
+				if( !isset($group[$atomicUnit]) ){
+					continue;
+				}
+
+				$value = $value / ($group[$atomicUnit] / $group[$targetUnit]);
+
+				$unit->denominator[$i] = $targetUnit;
+			}
+		}
+
+		$unit->cancel();
+
+		return new Less_Tree_Dimension( $value, $unit);
+    }
+}
+ 
+
+/**
+ * Directive
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Directive extends Less_Tree{
+
+	public $name;
+	public $value;
+	public $rules;
+	public $index;
+	public $isReferenced;
+	public $currentFileInfo;
+	public $debugInfo;
+	public $type = 'Directive';
+
+	public function __construct($name, $value = null, $rules, $index = null, $currentFileInfo = null, $debugInfo = null ){
+		$this->name = $name;
+		$this->value = $value;
+		if( $rules ){
+			$this->rules = $rules;
+			$this->rules->allowImports = true;
+		}
+
+		$this->index = $index;
+		$this->currentFileInfo = $currentFileInfo;
+		$this->debugInfo = $debugInfo;
+	}
+
+
+    public function accept( $visitor ){
+		if( $this->rules ){
+			$this->rules = $visitor->visitObj( $this->rules );
+		}
+		if( $this->value ){
+			$this->value = $visitor->visitObj( $this->value );
+		}
+	}
+
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+    public function genCSS( $output ){
+		$value = $this->value;
+		$rules = $this->rules;
+		$output->add( $this->name, $this->currentFileInfo, $this->index );
+		if( $this->value ){
+			$output->add(' ');
+			$this->value->genCSS($output);
+		}
+		if( $this->rules ){
+			Less_Tree::outputRuleset( $output, array($this->rules));
+		} else {
+			$output->add(';');
+		}
+	}
+
+	public function compile($env){
+
+		$value = $this->value;
+		$rules = $this->rules;
+		if( $value ){
+			$value = $value->compile($env);
+		}
+
+		if( $rules ){
+			$rules = $rules->compile($env);
+			$rules->root = true;
+		}
+
+		return new Less_Tree_Directive( $this->name, $value, $rules, $this->index, $this->currentFileInfo, $this->debugInfo );
+	}
+
+
+	public function variable($name){
+		if( $this->rules ){
+			return $this->rules->variable($name);
+		}
+	}
+
+	public function find($selector){
+		if( $this->rules ){
+			return $this->rules->find($selector, $this);
+		}
+	}
+
+	//rulesets: function () { if (this.rules) return tree.Ruleset.prototype.rulesets.apply(this.rules); },
+
+	public function markReferenced(){
+		$this->isReferenced = true;
+		if( $this->rules ){
+			Less_Tree::ReferencedArray($this->rules->rules);
+		}
+	}
+
+}
+ 
+
+/**
+ * Element
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Element extends Less_Tree{
+
+	public $combinator = '';
+	public $value = '';
+	public $index;
+	public $currentFileInfo;
+	public $type = 'Element';
+
+	public $value_is_object = false;
+
+	public function __construct($combinator, $value, $index = null, $currentFileInfo = null ){
+
+		$this->value = $value;
+		$this->value_is_object = is_object($value);
+
+		if( $combinator ){
+			$this->combinator = $combinator;
+		}
+
+		$this->index = $index;
+		$this->currentFileInfo = $currentFileInfo;
+	}
+
+    public function accept( $visitor ){
+		if( $this->value_is_object ){ //object or string
+			$this->value = $visitor->visitObj( $this->value );
+		}
+	}
+
+	public function compile($env){
+
+		if( Less_Environment::$mixin_stack ){
+			return new Less_Tree_Element($this->combinator, ($this->value_is_object ? $this->value->compile($env) : $this->value), $this->index, $this->currentFileInfo );
+		}
+
+		if( $this->value_is_object ){
+			$this->value = $this->value->compile($env);
+		}
+
+		return $this;
+	}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+	public function genCSS( $output ){
+		$output->add( $this->toCSS(), $this->currentFileInfo, $this->index );
+	}
+
+	public function toCSS(){
+
+		if( $this->value_is_object ){
+			$value = $this->value->toCSS();
+		}else{
+			$value = $this->value;
+		}
+
+
+		if( $value === '' && $this->combinator && $this->combinator === '&' ){
+			return '';
+		}
+
+
+		return Less_Environment::$_outputMap[$this->combinator] . $value;
+	}
+
+}
+ 
+
+/**
+ * Expression
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Expression extends Less_Tree{
+
+	public $value = array();
+	public $parens = false;
+	public $parensInOp = false;
+	public $type = 'Expression';
+
+	public function __construct( $value, $parens = null ){
+		$this->value = $value;
+		$this->parens = $parens;
+	}
+
+    public function accept( $visitor ){
+		$this->value = $visitor->visitArray( $this->value );
+	}
+
+	public function compile($env) {
+
+		$doubleParen = false;
+
+		if( $this->parens && !$this->parensInOp ){
+			Less_Environment::$parensStack++;
+		}
+
+		$returnValue = null;
+		if( $this->value ){
+
+			$count = count($this->value);
+
+			if( $count > 1 ){
+
+				$ret = array();
+				foreach($this->value as $e){
+					$ret[] = $e->compile($env);
+				}
+				$returnValue = new Less_Tree_Expression($ret);
+
+			}else{
+
+				if( ($this->value[0] instanceof Less_Tree_Expression) && $this->value[0]->parens && !$this->value[0]->parensInOp ){
+					$doubleParen = true;
+				}
+
+				$returnValue = $this->value[0]->compile($env);
+			}
+
+		} else {
+			$returnValue = $this;
+		}
+
+		if( $this->parens ){
+			if( !$this->parensInOp ){
+				Less_Environment::$parensStack--;
+
+			}elseif( !Less_Environment::isMathOn() && !$doubleParen ){
+				$returnValue = new Less_Tree_Paren($returnValue);
+
+			}
+		}
+		return $returnValue;
+	}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+    public function genCSS( $output ){
+		$val_len = count($this->value);
+		for( $i = 0; $i < $val_len; $i++ ){
+			$this->value[$i]->genCSS( $output );
+			if( $i + 1 < $val_len ){
+				$output->add( ' ' );
+			}
+		}
+	}
+
+    public function throwAwayComments() {
+
+		if( is_array($this->value) ){
+			$new_value = array();
+			foreach($this->value as $v){
+				if( $v instanceof Less_Tree_Comment ){
+					continue;
+				}
+				$new_value[] = $v;
+			}
+			$this->value = $new_value;
+		}
+	}
+}
+ 
+
+/**
+ * Extend
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Extend extends Less_Tree{
+
+	public $selector;
+	public $option;
+	public $index;
+	public $selfSelectors = array();
+	public $allowBefore;
+	public $allowAfter;
+	public $firstExtendOnThisSelectorPath;
+	public $type = 'Extend';
+	public $ruleset;
+
+
+	public $object_id;
+	public $parent_ids = array();
+
+	/**
+	 * @param integer $index
+	 */
+    public function __construct($selector, $option, $index){
+		static $i = 0;
+		$this->selector = $selector;
+		$this->option = $option;
+		$this->index = $index;
+
+		switch($option){
+			case "all":
+				$this->allowBefore = true;
+				$this->allowAfter = true;
+			break;
+			default:
+				$this->allowBefore = false;
+				$this->allowAfter = false;
+			break;
+		}
+
+		$this->object_id = $i++;
+		$this->parent_ids = array($this->object_id);
+	}
+
+    public function accept( $visitor ){
+		$this->selector = $visitor->visitObj( $this->selector );
+	}
+
+    public function compile( $env ){
+		Less_Parser::$has_extends = true;
+		$this->selector = $this->selector->compile($env);
+		return $this;
+		//return new Less_Tree_Extend( $this->selector->compile($env), $this->option, $this->index);
+	}
+
+    public function findSelfSelectors( $selectors ){
+		$selfElements = array();
+
+
+		for( $i = 0, $selectors_len = count($selectors); $i < $selectors_len; $i++ ){
+			$selectorElements = $selectors[$i]->elements;
+			// duplicate the logic in genCSS function inside the selector node.
+			// future TODO - move both logics into the selector joiner visitor
+			if( $i && $selectorElements && $selectorElements[0]->combinator === "") {
+				$selectorElements[0]->combinator = ' ';
+			}
+			$selfElements = array_merge( $selfElements, $selectors[$i]->elements );
+		}
+
+		$this->selfSelectors = array(new Less_Tree_Selector($selfElements));
+	}
+
+} 
+
+/**
+ * CSS @import node
+ *
+ * The general strategy here is that we don't want to wait
+ * for the parsing to be completed, before we start importing
+ * the file. That's because in the context of a browser,
+ * most of the time will be spent waiting for the server to respond.
+ *
+ * On creation, we push the import path to our import queue, though
+ * `import,push`, we also pass it a callback, which it'll call once
+ * the file has been fetched, and parsed.
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Import extends Less_Tree{
+
+	public $options;
+	public $index;
+	public $path;
+	public $features;
+	public $currentFileInfo;
+	public $css;
+	public $skip;
+	public $root;
+	public $type = 'Import';
+
+    public function __construct($path, $features, $options, $index, $currentFileInfo = null ){
+		$this->options = $options;
+		$this->index = $index;
+		$this->path = $path;
+		$this->features = $features;
+		$this->currentFileInfo = $currentFileInfo;
+
+		if( is_array($options) ){
+			$this->options += array('inline'=>false);
+
+			if( isset($this->options['less']) || $this->options['inline'] ){
+				$this->css = !isset($this->options['less']) || !$this->options['less'] || $this->options['inline'];
+			} else {
+				$pathValue = $this->getPath();
+				if( $pathValue && preg_match('/css([\?;].*)?$/',$pathValue) ){
+					$this->css = true;
+				}
+			}
+		}
+	}
+
+//
+// The actual import node doesn't return anything, when converted to CSS.
+// The reason is that it's used at the evaluation stage, so that the rules
+// it imports can be treated like any other rules.
+//
+// In `eval`, we make sure all Import nodes get evaluated, recursively, so
+// we end up with a flat structure, which can easily be imported in the parent
+// ruleset.
+//
+
+    public function accept($visitor){
+
+		if( $this->features ){
+			$this->features = $visitor->visitObj($this->features);
+		}
+		$this->path = $visitor->visitObj($this->path);
+
+		if( !$this->options['inline'] && $this->root ){
+			$this->root = $visitor->visit($this->root);
+		}
+	}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+    public function genCSS( $output ){
+		if( $this->css ){
+
+			$output->add( '@import ', $this->currentFileInfo, $this->index );
+
+			$this->path->genCSS( $output );
+			if( $this->features ){
+				$output->add( ' ' );
+				$this->features->genCSS( $output );
+			}
+			$output->add( ';' );
+		}
+	}
+
+    public function toCSS(){
+		$features = $this->features ? ' ' . $this->features->toCSS() : '';
+
+		if ($this->css) {
+			return "@import " . $this->path->toCSS() . $features . ";\n";
+		} else {
+			return "";
+		}
+	}
+
+	/**
+	 * @return string
+	 */
+    public function getPath(){
+		if ($this->path instanceof Less_Tree_Quoted) {
+			$path = $this->path->value;
+			$path = ( isset($this->css) || preg_match('/(\.[a-z]*$)|([\?;].*)$/',$path)) ? $path : $path . '.less';
+		} else if ($this->path instanceof Less_Tree_URL) {
+			$path = $this->path->value->value;
+		}else{
+			return null;
+		}
+
+		//remove query string and fragment
+		return preg_replace('/[\?#][^\?]*$/','',$path);
+	}
+
+    public function compileForImport( $env ){
+		return new Less_Tree_Import( $this->path->compile($env), $this->features, $this->options, $this->index, $this->currentFileInfo);
+	}
+
+    public function compilePath($env) {
+		$path = $this->path->compile($env);
+		$rootpath = '';
+		if( $this->currentFileInfo && $this->currentFileInfo['rootpath'] ){
+			$rootpath = $this->currentFileInfo['rootpath'];
+		}
+
+
+		if( !($path instanceof Less_Tree_URL) ){
+			if( $rootpath ){
+				$pathValue = $path->value;
+				// Add the base path if the import is relative
+				if( $pathValue && Less_Environment::isPathRelative($pathValue) ){
+					$path->value = $this->currentFileInfo['uri_root'].$pathValue;
+				}
+			}
+			$path->value = Less_Environment::normalizePath($path->value);
+		}
+
+
+
+		return $path;
+	}
+
+    public function compile( $env ){
+
+		$evald = $this->compileForImport($env);
+
+		//get path & uri
+		$path_and_uri = null;
+		if( is_callable(Less_Parser::$options['import_callback']) ){
+			$path_and_uri = call_user_func(Less_Parser::$options['import_callback'],$evald);
+		}
+
+		if( !$path_and_uri ){
+			$path_and_uri = $evald->PathAndUri();
+		}
+
+		if( $path_and_uri ){
+			list($full_path, $uri) = $path_and_uri;
+		}else{
+			$full_path = $uri = $evald->getPath();
+		}
+
+
+		//import once
+		if( $evald->skip( $full_path, $env) ){
+			return array();
+		}
+
+		if( $this->options['inline'] ){
+			//todo needs to reference css file not import
+			//$contents = new Less_Tree_Anonymous($this->root, 0, array('filename'=>$this->importedFilename), true );
+
+			Less_Parser::AddParsedFile($full_path);
+			$contents = new Less_Tree_Anonymous( file_get_contents($full_path), 0, array(), true );
+
+			if( $this->features ){
+				return new Less_Tree_Media( array($contents), $this->features->value );
+			}
+
+			return array( $contents );
+		}
+
+
+		// css ?
+		if( $evald->css ){
+			$features = ( $evald->features ? $evald->features->compile($env) : null );
+			return new Less_Tree_Import( $this->compilePath( $env), $features, $this->options, $this->index);
+		}
+
+
+		return $this->ParseImport( $full_path, $uri, $env );
+	}
+
+
+	/**
+	 * Using the import directories, get the full absolute path and uri of the import
+	 *
+	 * @param Less_Tree_Import $evald
+	 */
+    public function PathAndUri(){
+
+		$evald_path = $this->getPath();
+
+		if( $evald_path ){
+
+			$import_dirs = array();
+
+			if( Less_Environment::isPathRelative($evald_path) ){
+				//if the path is relative, the file should be in the current directory
+				$import_dirs[ $this->currentFileInfo['currentDirectory'] ] = $this->currentFileInfo['uri_root'];
+
+			}else{
+				//otherwise, the file should be relative to the server root
+				$import_dirs[ $this->currentFileInfo['entryPath'] ] = $this->currentFileInfo['entryUri'];
+
+				//if the user supplied entryPath isn't the actual root
+				$import_dirs[ $_SERVER['DOCUMENT_ROOT'] ] = '';
+
+			}
+
+			// always look in user supplied import directories
+			$import_dirs = array_merge( $import_dirs, Less_Parser::$options['import_dirs'] );
+
+
+			foreach( $import_dirs as $rootpath => $rooturi){
+				if( is_callable($rooturi) ){
+					list($path, $uri) = call_user_func($rooturi, $evald_path);
+					if( is_string($path) ){
+						$full_path = $path;
+						return array( $full_path, $uri );
+					}
+				}elseif( !empty($rootpath) ){
+
+
+					if( $rooturi ){
+						if( strpos($evald_path,$rooturi) === 0 ){
+							$evald_path = substr( $evald_path, strlen($rooturi) );
+						}
+					}
+
+					$path = rtrim($rootpath,'/\\').'/'.ltrim($evald_path,'/\\');
+
+					if( file_exists($path) ){
+						$full_path = Less_Environment::normalizePath($path);
+						$uri = Less_Environment::normalizePath(dirname($rooturi.$evald_path));
+						return array( $full_path, $uri );
+					} elseif( file_exists($path.'.less') ){
+						$full_path = Less_Environment::normalizePath($path.'.less');
+						$uri = Less_Environment::normalizePath(dirname($rooturi.$evald_path.'.less'));
+						return array( $full_path, $uri );
+					}
+				}
+			}
+		}
+	}
+
+
+	/**
+	 * Parse the import url and return the rules
+	 *
+	 * @return Less_Tree_Media|array
+	 */
+    public function ParseImport( $full_path, $uri, $env ){
+
+		$import_env = clone $env;
+		if( (isset($this->options['reference']) && $this->options['reference']) || isset($this->currentFileInfo['reference']) ){
+			$import_env->currentFileInfo['reference'] = true;
+		}
+
+		if( (isset($this->options['multiple']) && $this->options['multiple']) ){
+			$import_env->importMultiple = true;
+		}
+
+		$parser = new Less_Parser($import_env);
+		$root = $parser->parseFile($full_path, $uri, true);
+
+
+		$ruleset = new Less_Tree_Ruleset(array(), $root->rules );
+		$ruleset->evalImports($import_env);
+
+		return $this->features ? new Less_Tree_Media($ruleset->rules, $this->features->value) : $ruleset->rules;
+	}
+
+
+	/**
+	 * Should the import be skipped?
+	 *
+	 * @return boolean|null
+	 */
+	private function Skip($path, $env){
+
+		$path = Less_Parser::winPath(realpath($path));
+
+		if( $path && Less_Parser::FileParsed($path) ){
+
+			if( isset($this->currentFileInfo['reference']) ){
+				return true;
+			}
+
+			return !isset($this->options['multiple']) && !$env->importMultiple;
+		}
+
+	}
+}
+
+ 
+
+/**
+ * Javascript
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Javascript extends Less_Tree{
+
+	public $type = 'Javascript';
+	public $escaped;
+	public $expression;
+	public $index;
+
+	/**
+	 * @param boolean $index
+	 * @param boolean $escaped
+	 */
+	public function __construct($string, $index, $escaped){
+		$this->escaped = $escaped;
+		$this->expression = $string;
+		$this->index = $index;
+	}
+
+	public function compile(){
+		return new Less_Tree_Anonymous('/* Sorry, can not do JavaScript evaluation in PHP... :( */');
+	}
+
+}
+ 
+
+/**
+ * Keyword
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Keyword extends Less_Tree{
+
+	public $value;
+	public $type = 'Keyword';
+
+	/**
+	 * @param string $value
+	 */
+	public function __construct($value){
+		$this->value = $value;
+	}
+
+	public function compile(){
+		return $this;
+	}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+	public function genCSS( $output ){
+
+		if( $this->value === '%') {
+			throw new Less_Exception_Compiler("Invalid % without number");
+		}
+
+		$output->add( $this->value );
+	}
+
+	public function compare($other) {
+		if ($other instanceof Less_Tree_Keyword) {
+			return $other->value === $this->value ? 0 : 1;
+		} else {
+			return -1;
+		}
+	}
+}
+ 
+
+/**
+ * Media
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Media extends Less_Tree{
+
+	public $features;
+	public $rules;
+	public $index;
+	public $currentFileInfo;
+	public $isReferenced;
+	public $type = 'Media';
+
+	public function __construct($value = array(), $features = array(), $index = null, $currentFileInfo = null ){
+
+		$this->index = $index;
+		$this->currentFileInfo = $currentFileInfo;
+
+		$selectors = $this->emptySelectors();
+
+		$this->features = new Less_Tree_Value($features);
+
+		$this->rules = array(new Less_Tree_Ruleset($selectors, $value));
+		$this->rules[0]->allowImports = true;
+	}
+
+    public function accept( $visitor ){
+		$this->features = $visitor->visitObj($this->features);
+		$this->rules = $visitor->visitArray($this->rules);
+	}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+    public function genCSS( $output ){
+
+		$output->add( '@media ', $this->currentFileInfo, $this->index );
+		$this->features->genCSS( $output );
+		Less_Tree::outputRuleset( $output, $this->rules);
+
+	}
+
+	public function compile($env) {
+
+		$media = new Less_Tree_Media(array(), array(), $this->index, $this->currentFileInfo );
+
+		$strictMathBypass = false;
+		if( Less_Parser::$options['strictMath'] === false) {
+			$strictMathBypass = true;
+			Less_Parser::$options['strictMath'] = true;
+		}
+
+		$media->features = $this->features->compile($env);
+
+		if( $strictMathBypass ){
+			Less_Parser::$options['strictMath'] = false;
+		}
+
+		$env->mediaPath[] = $media;
+		$env->mediaBlocks[] = $media;
+
+		array_unshift($env->frames, $this->rules[0]);
+		$media->rules = array($this->rules[0]->compile($env));
+		array_shift($env->frames);
+
+		array_pop($env->mediaPath);
+
+		return !$env->mediaPath ? $media->compileTop($env) : $media->compileNested($env);
+	}
+
+	public function variable($name) {
+		return $this->rules[0]->variable($name);
+	}
+
+	public function find($selector) {
+		return $this->rules[0]->find($selector, $this);
+	}
+
+	public function emptySelectors(){
+		$el = new Less_Tree_Element('','&', $this->index, $this->currentFileInfo );
+		$sels = array( new Less_Tree_Selector(array($el), array(), null, $this->index, $this->currentFileInfo) );
+		$sels[0]->mediaEmpty = true;
+        return $sels;
+	}
+
+	public function markReferenced(){
+		$this->rules[0]->markReferenced();
+		$this->isReferenced = true;
+		Less_Tree::ReferencedArray($this->rules[0]->rules);
+	}
+
+	// evaltop
+	public function compileTop($env) {
+		$result = $this;
+
+		if (count($env->mediaBlocks) > 1) {
+			$selectors = $this->emptySelectors();
+			$result = new Less_Tree_Ruleset($selectors, $env->mediaBlocks);
+			$result->multiMedia = true;
+		}
+
+		$env->mediaBlocks = array();
+		$env->mediaPath = array();
+
+		return $result;
+	}
+
+	public function compileNested($env) {
+		$path = array_merge($env->mediaPath, array($this));
+
+		// Extract the media-query conditions separated with `,` (OR).
+		foreach ($path as $key => $p) {
+			$value = $p->features instanceof Less_Tree_Value ? $p->features->value : $p->features;
+			$path[$key] = is_array($value) ? $value : array($value);
+		}
+
+		// Trace all permutations to generate the resulting media-query.
+		//
+		// (a, b and c) with nested (d, e) ->
+		//	a and d
+		//	a and e
+		//	b and c and d
+		//	b and c and e
+
+		$permuted = $this->permute($path);
+		$expressions = array();
+		foreach($permuted as $path){
+
+			for( $i=0, $len=count($path); $i < $len; $i++){
+				$path[$i] = Less_Parser::is_method($path[$i], 'toCSS') ? $path[$i] : new Less_Tree_Anonymous($path[$i]);
+			}
+
+			for( $i = count($path) - 1; $i > 0; $i-- ){
+				array_splice($path, $i, 0, array(new Less_Tree_Anonymous('and')));
+			}
+
+			$expressions[] = new Less_Tree_Expression($path);
+		}
+		$this->features = new Less_Tree_Value($expressions);
+
+
+
+		// Fake a tree-node that doesn't output anything.
+		return new Less_Tree_Ruleset(array(), array());
+	}
+
+	public function permute($arr) {
+		if (!$arr)
+			return array();
+
+		if (count($arr) == 1)
+			return $arr[0];
+
+		$result = array();
+		$rest = $this->permute(array_slice($arr, 1));
+		foreach ($rest as $r) {
+			foreach ($arr[0] as $a) {
+				$result[] = array_merge(
+					is_array($a) ? $a : array($a),
+					is_array($r) ? $r : array($r)
+				);
+			}
+		}
+
+		return $result;
+	}
+
+    public function bubbleSelectors($selectors) {
+
+		if( !$selectors) return;
+
+		$this->rules = array(new Less_Tree_Ruleset( $selectors, array($this->rules[0])));
+	}
+
+}
+ 
+
+/**
+ * A simple css name-value pair
+ * ex: width:100px;
+ *
+ * In bootstrap, there are about 600-1,000 simple name-value pairs (depending on how forgiving the match is) -vs- 6,020 dynamic rules (Less_Tree_Rule)
+ * Using the name-value object can speed up bootstrap compilation slightly, but it breaks color keyword interpretation: color:red -> color:#FF0000;
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_NameValue extends Less_Tree{
+
+	public $name;
+	public $value;
+	public $index;
+	public $currentFileInfo;
+	public $type = 'NameValue';
+
+	public function __construct($name, $value = null, $index = null, $currentFileInfo = null ){
+		$this->name = $name;
+		$this->value = $value;
+		$this->index = $index;
+		$this->currentFileInfo = $currentFileInfo;
+	}
+
+    public function genCSS( $output ){
+
+		$output->add(
+			$this->name
+			. Less_Environment::$_outputMap[': ']
+			. $this->value
+			. (((Less_Environment::$lastRule && Less_Parser::$options['compress'])) ? "" : ";")
+			, $this->currentFileInfo, $this->index);
+	}
+
+	public function compile ($env){
+		return $this;
+	}
+}
+ 
+
+/**
+ * Negative
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Negative extends Less_Tree{
+
+	public $value;
+	public $type = 'Negative';
+
+    public function __construct($node){
+		$this->value = $node;
+	}
+
+	//function accept($visitor) {
+	//	$this->value = $visitor->visit($this->value);
+	//}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+    public function genCSS( $output ){
+		$output->add( '-' );
+		$this->value->genCSS( $output );
+	}
+
+    public function compile($env) {
+		if( Less_Environment::isMathOn() ){
+			$ret = new Less_Tree_Operation('*', array( new Less_Tree_Dimension(-1), $this->value ) );
+			return $ret->compile($env);
+		}
+		return new Less_Tree_Negative( $this->value->compile($env) );
+	}
+} 
+
+/**
+ * Operation
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Operation extends Less_Tree{
+
+	public $op;
+	public $operands;
+	public $isSpaced;
+	public $type = 'Operation';
+
+	/**
+	 * @param string $op
+	 */
+	public function __construct($op, $operands, $isSpaced = false){
+		$this->op = trim($op);
+		$this->operands = $operands;
+		$this->isSpaced = $isSpaced;
+	}
+
+    public function accept($visitor) {
+		$this->operands = $visitor->visitArray($this->operands);
+	}
+
+	public function compile($env){
+		$a = $this->operands[0]->compile($env);
+		$b = $this->operands[1]->compile($env);
+
+
+		if( Less_Environment::isMathOn() ){
+
+			if( $a instanceof Less_Tree_Dimension && $b instanceof Less_Tree_Color ){
+				$a = $a->toColor();
+
+			}elseif( $b instanceof Less_Tree_Dimension && $a instanceof Less_Tree_Color ){
+				$b = $b->toColor();
+
+			}
+
+			if( !method_exists($a,'operate') ){
+				throw new Less_Exception_Compiler("Operation on an invalid type");
+			}
+
+			return $a->operate( $this->op, $b);
+		}
+
+		return new Less_Tree_Operation($this->op, array($a, $b), $this->isSpaced );
+	}
+
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+    public function genCSS( $output ){
+		$this->operands[0]->genCSS( $output );
+		if( $this->isSpaced ){
+			$output->add( " " );
+		}
+		$output->add( $this->op );
+		if( $this->isSpaced ){
+			$output->add( ' ' );
+		}
+		$this->operands[1]->genCSS( $output );
+	}
+
+}
+ 
+
+/**
+ * Paren
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Paren extends Less_Tree{
+
+	public $value;
+	public $type = 'Paren';
+
+	public function __construct($value) {
+		$this->value = $value;
+	}
+
+    public function accept($visitor){
+		$this->value = $visitor->visitObj($this->value);
+	}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+    public function genCSS( $output ){
+		$output->add( '(' );
+		$this->value->genCSS( $output );
+		$output->add( ')' );
+	}
+
+	public function compile($env) {
+		return new Less_Tree_Paren($this->value->compile($env));
+	}
+
+}
+ 
+
+/**
+ * Quoted
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Quoted extends Less_Tree{
+	public $escaped;
+	public $value;
+	public $quote;
+	public $index;
+	public $currentFileInfo;
+	public $type = 'Quoted';
+
+	/**
+	 * @param string $str
+	 */
+	public function __construct($str, $content = '', $escaped = false, $index = false, $currentFileInfo = null ){
+		$this->escaped = $escaped;
+		$this->value = $content;
+		if( $str ){
+			$this->quote = $str[0];
+		}
+		$this->index = $index;
+		$this->currentFileInfo = $currentFileInfo;
+	}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+    public function genCSS( $output ){
+		if( !$this->escaped ){
+			$output->add( $this->quote, $this->currentFileInfo, $this->index );
+        }
+        $output->add( $this->value );
+        if( !$this->escaped ){
+			$output->add( $this->quote );
+        }
+    }
+
+	public function compile($env){
+
+		$value = $this->value;
+		if( preg_match_all('/`([^`]+)`/', $this->value, $matches) ){
+			foreach($matches as $i => $match){
+				$js = new Less_Tree_JavaScript($matches[1], $this->index, true);
+				$js = $js->compile()->value;
+				$value = str_replace($matches[0][$i], $js, $value);
+			}
+		}
+
+		if( preg_match_all('/@\{([\w-]+)\}/',$value,$matches) ){
+			foreach($matches[1] as $i => $match){
+				$v = new Less_Tree_Variable('@' . $match, $this->index, $this->currentFileInfo );
+				$v = $v->compile($env);
+				$v = ($v instanceof Less_Tree_Quoted) ? $v->value : $v->toCSS();
+				$value = str_replace($matches[0][$i], $v, $value);
+			}
+		}
+
+		return new Less_Tree_Quoted($this->quote . $value . $this->quote, $value, $this->escaped, $this->index, $this->currentFileInfo);
+	}
+
+    public function compare($x) {
+
+		if( !Less_Parser::is_method($x, 'toCSS') ){
+			return -1;
+		}
+
+		$left = $this->toCSS();
+		$right = $x->toCSS();
+
+		if ($left === $right) {
+			return 0;
+		}
+
+		return $left < $right ? -1 : 1;
+	}
+}
+ 
+
+/**
+ * Rule
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Rule extends Less_Tree{
+
+	public $name;
+	public $value;
+	public $important;
+	public $merge;
+	public $index;
+	public $inline;
+	public $variable;
+	public $currentFileInfo;
+	public $type = 'Rule';
+
+	/**
+	 * @param string $important
+	 */
+	public function __construct($name, $value = null, $important = null, $merge = null, $index = null, $currentFileInfo = null,  $inline = false){
+		$this->name = $name;
+		$this->value = ($value instanceof Less_Tree_Value || $value instanceof Less_Tree_Ruleset) ? $value : new Less_Tree_Value(array($value));
+		$this->important = $important ? ' ' . trim($important) : '';
+		$this->merge = $merge;
+		$this->index = $index;
+		$this->currentFileInfo = $currentFileInfo;
+		$this->inline = $inline;
+		$this->variable = ( is_string($name) && $name[0] === '@');
+	}
+
+    public function accept($visitor) {
+		$this->value = $visitor->visitObj( $this->value );
+	}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+    public function genCSS( $output ){
+
+		$output->add( $this->name . Less_Environment::$_outputMap[': '], $this->currentFileInfo, $this->index);
+		try{
+			$this->value->genCSS( $output);
+
+		}catch( Less_Exception_Parser $e ){
+			$e->index = $this->index;
+			$e->currentFile = $this->currentFileInfo;
+			throw $e;
+		}
+		$output->add( $this->important . (($this->inline || (Less_Environment::$lastRule && Less_Parser::$options['compress'])) ? "" : ";"), $this->currentFileInfo, $this->index);
+	}
+
+	public function compile ($env){
+
+		$name = $this->name;
+		if( is_array($name) ){
+			// expand 'primitive' name directly to get
+			// things faster (~10% for benchmark.less):
+			if( count($name) === 1 && $name[0] instanceof Less_Tree_Keyword ){
+				$name = $name[0]->value;
+			}else{
+				$name = $this->CompileName($env,$name);
+			}
+		}
+
+		$strictMathBypass = Less_Parser::$options['strictMath'];
+		if( $name === "font" && !Less_Parser::$options['strictMath'] ){
+			Less_Parser::$options['strictMath'] = true;
+		}
+
+		try {
+			$evaldValue = $this->value->compile($env);
+
+			if( !$this->variable && $evaldValue->type === "DetachedRuleset") {
+				throw new Less_Exception_Compiler("Rulesets cannot be evaluated on a property.", null, $this->index, $this->currentFileInfo);
+			}
+
+			if( Less_Environment::$mixin_stack ){
+				$return = new Less_Tree_Rule($name, $evaldValue, $this->important, $this->merge, $this->index, $this->currentFileInfo, $this->inline);
+			}else{
+				$this->name = $name;
+				$this->value = $evaldValue;
+				$return = $this;
+			}
+
+		}catch( Less_Exception_Parser $e ){
+			if( !is_numeric($e->index) ){
+				$e->index = $this->index;
+				$e->currentFile = $this->currentFileInfo;
+			}
+			throw $e;
+		}
+
+		Less_Parser::$options['strictMath'] = $strictMathBypass;
+
+		return $return;
+	}
+
+
+    public function CompileName( $env, $name ){
+		$output = new Less_Output();
+		foreach($name as $n){
+			$n->compile($env)->genCSS($output);
+		}
+		return $output->toString();
+	}
+
+    public function makeImportant(){
+		return new Less_Tree_Rule($this->name, $this->value, '!important', $this->merge, $this->index, $this->currentFileInfo, $this->inline);
+	}
+
+}
+ 
+
+/**
+ * Ruleset
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Ruleset extends Less_Tree{
+
+	protected $lookups;
+	public $_variables;
+	public $_rulesets;
+
+	public $strictImports;
+
+	public $selectors;
+	public $rules;
+	public $root;
+	public $allowImports;
+	public $paths;
+	public $firstRoot;
+	public $type = 'Ruleset';
+	public $multiMedia;
+	public $allExtends;
+
+	public $ruleset_id;
+	public $originalRuleset;
+
+	public $first_oelements;
+
+	public function SetRulesetIndex(){
+		$this->ruleset_id = Less_Parser::$next_id++;
+		$this->originalRuleset = $this->ruleset_id;
+
+		if( $this->selectors ){
+			foreach($this->selectors as $sel){
+				if( $sel->_oelements ){
+					$this->first_oelements[$sel->_oelements[0]] = true;
+				}
+			}
+		}
+	}
+
+	public function __construct($selectors, $rules, $strictImports = null){
+		$this->selectors = $selectors;
+		$this->rules = $rules;
+		$this->lookups = array();
+		$this->strictImports = $strictImports;
+		$this->SetRulesetIndex();
+	}
+
+	public function accept( $visitor ){
+		if( $this->paths ){
+			$paths_len = count($this->paths);
+			for($i = 0,$paths_len; $i < $paths_len; $i++ ){
+				$this->paths[$i] = $visitor->visitArray($this->paths[$i]);
+			}
+		}elseif( $this->selectors ){
+			$this->selectors = $visitor->visitArray($this->selectors);
+		}
+
+		if( $this->rules ){
+			$this->rules = $visitor->visitArray($this->rules);
+		}
+	}
+
+	public function compile($env){
+
+		$ruleset = $this->PrepareRuleset($env);
+
+
+		// Store the frames around mixin definitions,
+		// so they can be evaluated like closures when the time comes.
+		$rsRuleCnt = count($ruleset->rules);
+		for( $i = 0; $i < $rsRuleCnt; $i++ ){
+			if( $ruleset->rules[$i] instanceof Less_Tree_Mixin_Definition || $ruleset->rules[$i] instanceof Less_Tree_DetachedRuleset ){
+				$ruleset->rules[$i] = $ruleset->rules[$i]->compile($env);
+			}
+		}
+
+		$mediaBlockCount = 0;
+		if( $env instanceof Less_Environment ){
+			$mediaBlockCount = count($env->mediaBlocks);
+		}
+
+		// Evaluate mixin calls.
+		$this->EvalMixinCalls( $ruleset, $env, $rsRuleCnt );
+
+
+		// Evaluate everything else
+		for( $i=0; $i<$rsRuleCnt; $i++ ){
+			if(! ($ruleset->rules[$i] instanceof Less_Tree_Mixin_Definition || $ruleset->rules[$i] instanceof Less_Tree_DetachedRuleset) ){
+				$ruleset->rules[$i] = $ruleset->rules[$i]->compile($env);
+			}
+		}
+
+        // Evaluate everything else
+		for( $i=0; $i<$rsRuleCnt; $i++ ){
+			$rule = $ruleset->rules[$i];
+
+            // for rulesets, check if it is a css guard and can be removed
+			if( $rule instanceof Less_Tree_Ruleset && $rule->selectors && count($rule->selectors) === 1 ){
+
+                // check if it can be folded in (e.g. & where)
+				if( $rule->selectors[0]->isJustParentSelector() ){
+					array_splice($ruleset->rules,$i--,1);
+					$rsRuleCnt--;
+
+					for($j = 0; $j < count($rule->rules); $j++ ){
+						$subRule = $rule->rules[$j];
+						if( !($subRule instanceof Less_Tree_Rule) || !$subRule->variable ){
+							array_splice($ruleset->rules, ++$i, 0, array($subRule));
+							$rsRuleCnt++;
+						}
+					}
+
+                }
+            }
+        }
+
+
+		// Pop the stack
+		$env->shiftFrame();
+
+		if ($mediaBlockCount) {
+			$len = count($env->mediaBlocks);
+			for($i = $mediaBlockCount; $i < $len; $i++ ){
+				$env->mediaBlocks[$i]->bubbleSelectors($ruleset->selectors);
+			}
+		}
+
+		return $ruleset;
+	}
+
+	/**
+	 * Compile Less_Tree_Mixin_Call objects
+	 *
+	 * @param Less_Tree_Ruleset $ruleset
+	 * @param integer $rsRuleCnt
+	 */
+	private function EvalMixinCalls( $ruleset, $env, &$rsRuleCnt ){
+		for($i=0; $i < $rsRuleCnt; $i++){
+			$rule = $ruleset->rules[$i];
+
+			if( $rule instanceof Less_Tree_Mixin_Call ){
+				$rule = $rule->compile($env);
+
+				$temp = array();
+				foreach($rule as $r){
+					if( ($r instanceof Less_Tree_Rule) && $r->variable ){
+						// do not pollute the scope if the variable is
+						// already there. consider returning false here
+						// but we need a way to "return" variable from mixins
+						if( !$ruleset->variable($r->name) ){
+							$temp[] = $r;
+						}
+					}else{
+						$temp[] = $r;
+					}
+				}
+				$temp_count = count($temp)-1;
+				array_splice($ruleset->rules, $i, 1, $temp);
+				$rsRuleCnt += $temp_count;
+				$i += $temp_count;
+				$ruleset->resetCache();
+
+			}elseif( $rule instanceof Less_Tree_RulesetCall ){
+
+				$rule = $rule->compile($env);
+				$rules = array();
+				foreach($rule->rules as $r){
+					if( ($r instanceof Less_Tree_Rule) && $r->variable ){
+						continue;
+					}
+					$rules[] = $r;
+				}
+
+				array_splice($ruleset->rules, $i, 1, $rules);
+				$temp_count = count($rules);
+				$rsRuleCnt += $temp_count - 1;
+				$i += $temp_count-1;
+				$ruleset->resetCache();
+			}
+
+		}
+	}
+
+
+	/**
+	 * Compile the selectors and create a new ruleset object for the compile() method
+	 *
+	 */
+	private function PrepareRuleset($env){
+
+		$hasOnePassingSelector = false;
+		$selectors = array();
+		if( $this->selectors ){
+			Less_Tree_DefaultFunc::error("it is currently only allowed in parametric mixin guards,");
+
+			foreach($this->selectors as $s){
+				$selector = $s->compile($env);
+				$selectors[] = $selector;
+				if( $selector->evaldCondition ){
+					$hasOnePassingSelector = true;
+				}
+			}
+
+			Less_Tree_DefaultFunc::reset();
+		} else {
+			$hasOnePassingSelector = true;
+		}
+
+		if( $this->rules && $hasOnePassingSelector ){
+			$rules = $this->rules;
+		}else{
+			$rules = array();
+		}
+
+		$ruleset = new Less_Tree_Ruleset($selectors, $rules, $this->strictImports);
+
+		$ruleset->originalRuleset = $this->ruleset_id;
+
+		$ruleset->root = $this->root;
+		$ruleset->firstRoot = $this->firstRoot;
+		$ruleset->allowImports = $this->allowImports;
+
+
+		// push the current ruleset to the frames stack
+		$env->unshiftFrame($ruleset);
+
+
+		// Evaluate imports
+		if( $ruleset->root || $ruleset->allowImports || !$ruleset->strictImports ){
+			$ruleset->evalImports($env);
+		}
+
+		return $ruleset;
+	}
+
+	function evalImports($env) {
+
+		$rules_len = count($this->rules);
+		for($i=0; $i < $rules_len; $i++){
+			$rule = $this->rules[$i];
+
+			if( $rule instanceof Less_Tree_Import ){
+				$rules = $rule->compile($env);
+				if( is_array($rules) ){
+					array_splice($this->rules, $i, 1, $rules);
+					$temp_count = count($rules)-1;
+					$i += $temp_count;
+					$rules_len += $temp_count;
+				}else{
+					array_splice($this->rules, $i, 1, array($rules));
+				}
+
+				$this->resetCache();
+			}
+		}
+	}
+
+	function makeImportant(){
+
+		$important_rules = array();
+		foreach($this->rules as $rule){
+			if( $rule instanceof Less_Tree_Rule || $rule instanceof Less_Tree_Ruleset ){
+				$important_rules[] = $rule->makeImportant();
+			}else{
+				$important_rules[] = $rule;
+			}
+		}
+
+		return new Less_Tree_Ruleset($this->selectors, $important_rules, $this->strictImports );
+	}
+
+	public function matchArgs($args){
+		return !$args;
+	}
+
+	// lets you call a css selector with a guard
+	public function matchCondition( $args, $env ){
+		$lastSelector = end($this->selectors);
+
+		if( !$lastSelector->evaldCondition ){
+			return false;
+		}
+		if( $lastSelector->condition && !$lastSelector->condition->compile( $env->copyEvalEnv( $env->frames ) ) ){
+			return false;
+		}
+		return true;
+	}
+
+	function resetCache(){
+		$this->_rulesets = null;
+		$this->_variables = null;
+		$this->lookups = array();
+	}
+
+	public function variables(){
+		$this->_variables = array();
+		foreach( $this->rules as $r){
+			if ($r instanceof Less_Tree_Rule && $r->variable === true) {
+				$this->_variables[$r->name] = $r;
+			}
+		}
+	}
+
+	public function variable($name){
+
+		if( is_null($this->_variables) ){
+			$this->variables();
+		}
+		return isset($this->_variables[$name]) ? $this->_variables[$name] : null;
+	}
+
+	public function find( $selector, $self = null ){
+
+		$key = implode(' ',$selector->_oelements);
+
+		if( !isset($this->lookups[$key]) ){
+
+			if( !$self ){
+				$self = $this->ruleset_id;
+			}
+
+			$this->lookups[$key] = array();
+
+			$first_oelement = $selector->_oelements[0];
+
+			foreach($this->rules as $rule){
+				if( $rule instanceof Less_Tree_Ruleset && $rule->ruleset_id != $self ){
+
+					if( isset($rule->first_oelements[$first_oelement]) ){
+
+						foreach( $rule->selectors as $ruleSelector ){
+							$match = $selector->match($ruleSelector);
+							if( $match ){
+								if( $selector->elements_len > $match ){
+									$this->lookups[$key] = array_merge($this->lookups[$key], $rule->find( new Less_Tree_Selector(array_slice($selector->elements, $match)), $self));
+								} else {
+									$this->lookups[$key][] = $rule;
+								}
+								break;
+							}
+						}
+					}
+				}
+			}
+		}
+
+		return $this->lookups[$key];
+	}
+
+
+	/**
+	 * @see Less_Tree::genCSS
+	 */
+	public function genCSS( $output ){
+
+		if( !$this->root ){
+			Less_Environment::$tabLevel++;
+		}
+
+		$tabRuleStr = $tabSetStr = '';
+		if( !Less_Parser::$options['compress'] ){
+			if( Less_Environment::$tabLevel ){
+				$tabRuleStr = "\n".str_repeat( '  ' , Less_Environment::$tabLevel );
+				$tabSetStr = "\n".str_repeat( '  ' , Less_Environment::$tabLevel-1 );
+			}else{
+				$tabSetStr = $tabRuleStr = "\n";
+			}
+		}
+
+
+		$ruleNodes = array();
+		$rulesetNodes = array();
+		foreach($this->rules as $rule){
+
+			$class = get_class($rule);
+			if( ($class === 'Less_Tree_Media') || ($class === 'Less_Tree_Directive') || ($this->root && $class === 'Less_Tree_Comment') || ($class === 'Less_Tree_Ruleset' && $rule->rules) ){
+				$rulesetNodes[] = $rule;
+			}else{
+				$ruleNodes[] = $rule;
+			}
+		}
+
+		// If this is the root node, we don't render
+		// a selector, or {}.
+		if( !$this->root ){
+
+			/*
+			debugInfo = tree.debugInfo(env, this, tabSetStr);
+
+			if (debugInfo) {
+				output.add(debugInfo);
+				output.add(tabSetStr);
+			}
+			*/
+
+			$paths_len = count($this->paths);
+			for( $i = 0; $i < $paths_len; $i++ ){
+				$path = $this->paths[$i];
+				$firstSelector = true;
+
+				foreach($path as $p){
+					$p->genCSS( $output, $firstSelector );
+					$firstSelector = false;
+				}
+
+				if( $i + 1 < $paths_len ){
+					$output->add( ',' . $tabSetStr );
+				}
+			}
+
+			$output->add( (Less_Parser::$options['compress'] ? '{' : " {") . $tabRuleStr );
+		}
+
+		// Compile rules and rulesets
+		$ruleNodes_len = count($ruleNodes);
+		$rulesetNodes_len = count($rulesetNodes);
+		for( $i = 0; $i < $ruleNodes_len; $i++ ){
+			$rule = $ruleNodes[$i];
+
+			// @page{ directive ends up with root elements inside it, a mix of rules and rulesets
+			// In this instance we do not know whether it is the last property
+			if( $i + 1 === $ruleNodes_len && (!$this->root || $rulesetNodes_len === 0 || $this->firstRoot ) ){
+				Less_Environment::$lastRule = true;
+			}
+
+			$rule->genCSS( $output );
+
+			if( !Less_Environment::$lastRule ){
+				$output->add( $tabRuleStr );
+			}else{
+				Less_Environment::$lastRule = false;
+			}
+		}
+
+		if( !$this->root ){
+			$output->add( $tabSetStr . '}' );
+			Less_Environment::$tabLevel--;
+		}
+
+		$firstRuleset = true;
+		$space = ($this->root ? $tabRuleStr : $tabSetStr);
+		for( $i = 0; $i < $rulesetNodes_len; $i++ ){
+
+			if( $ruleNodes_len && $firstRuleset ){
+				$output->add( $space );
+			}elseif( !$firstRuleset ){
+				$output->add( $space );
+			}
+			$firstRuleset = false;
+			$rulesetNodes[$i]->genCSS( $output);
+		}
+
+		if( !Less_Parser::$options['compress'] && $this->firstRoot ){
+			$output->add( "\n" );
+		}
+
+	}
+
+
+	function markReferenced(){
+		if( !$this->selectors ){
+			return;
+		}
+		foreach($this->selectors as $selector){
+			$selector->markReferenced();
+		}
+	}
+
+	public function joinSelectors( $context, $selectors ){
+		$paths = array();
+		if( is_array($selectors) ){
+			foreach($selectors as $selector) {
+				$this->joinSelector( $paths, $context, $selector);
+			}
+		}
+		return $paths;
+	}
+
+	public function joinSelector( &$paths, $context, $selector){
+
+		$hasParentSelector = false;
+
+		foreach($selector->elements as $el) {
+			if( $el->value === '&') {
+				$hasParentSelector = true;
+			}
+		}
+
+		if( !$hasParentSelector ){
+			if( $context ){
+				foreach($context as $context_el){
+					$paths[] = array_merge($context_el, array($selector) );
+				}
+			}else {
+				$paths[] = array($selector);
+			}
+			return;
+		}
+
+
+		// The paths are [[Selector]]
+		// The first list is a list of comma seperated selectors
+		// The inner list is a list of inheritance seperated selectors
+		// e.g.
+		// .a, .b {
+		//   .c {
+		//   }
+		// }
+		// == [[.a] [.c]] [[.b] [.c]]
+		//
+
+		// the elements from the current selector so far
+		$currentElements = array();
+		// the current list of new selectors to add to the path.
+		// We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
+		// by the parents
+		$newSelectors = array(array());
+
+
+		foreach( $selector->elements as $el){
+
+			// non parent reference elements just get added
+			if( $el->value !== '&' ){
+				$currentElements[] = $el;
+			} else {
+				// the new list of selectors to add
+				$selectorsMultiplied = array();
+
+				// merge the current list of non parent selector elements
+				// on to the current list of selectors to add
+				if( $currentElements ){
+					$this->mergeElementsOnToSelectors( $currentElements, $newSelectors);
+				}
+
+				// loop through our current selectors
+				foreach($newSelectors as $sel){
+
+					// if we don't have any parent paths, the & might be in a mixin so that it can be used
+					// whether there are parents or not
+					if( !$context ){
+						// the combinator used on el should now be applied to the next element instead so that
+						// it is not lost
+						if( $sel ){
+							$sel[0]->elements = array_slice($sel[0]->elements,0);
+							$sel[0]->elements[] = new Less_Tree_Element($el->combinator, '', $el->index, $el->currentFileInfo );
+						}
+						$selectorsMultiplied[] = $sel;
+					}else {
+
+						// and the parent selectors
+						foreach($context as $parentSel){
+							// We need to put the current selectors
+							// then join the last selector's elements on to the parents selectors
+
+							// our new selector path
+							$newSelectorPath = array();
+							// selectors from the parent after the join
+							$afterParentJoin = array();
+							$newJoinedSelectorEmpty = true;
+
+							//construct the joined selector - if & is the first thing this will be empty,
+							// if not newJoinedSelector will be the last set of elements in the selector
+							if( $sel ){
+								$newSelectorPath = $sel;
+								$lastSelector = array_pop($newSelectorPath);
+								$newJoinedSelector = $selector->createDerived( array_slice($lastSelector->elements,0) );
+								$newJoinedSelectorEmpty = false;
+							}
+							else {
+								$newJoinedSelector = $selector->createDerived(array());
+							}
+
+							//put together the parent selectors after the join
+							if ( count($parentSel) > 1) {
+								$afterParentJoin = array_merge($afterParentJoin, array_slice($parentSel,1) );
+							}
+
+							if ( $parentSel ){
+								$newJoinedSelectorEmpty = false;
+
+								// join the elements so far with the first part of the parent
+								$newJoinedSelector->elements[] = new Less_Tree_Element( $el->combinator, $parentSel[0]->elements[0]->value, $el->index, $el->currentFileInfo);
+
+								$newJoinedSelector->elements = array_merge( $newJoinedSelector->elements, array_slice($parentSel[0]->elements, 1) );
+							}
+
+							if (!$newJoinedSelectorEmpty) {
+								// now add the joined selector
+								$newSelectorPath[] = $newJoinedSelector;
+							}
+
+							// and the rest of the parent
+							$newSelectorPath = array_merge($newSelectorPath, $afterParentJoin);
+
+							// add that to our new set of selectors
+							$selectorsMultiplied[] = $newSelectorPath;
+						}
+					}
+				}
+
+				// our new selectors has been multiplied, so reset the state
+				$newSelectors = $selectorsMultiplied;
+				$currentElements = array();
+			}
+		}
+
+		// if we have any elements left over (e.g. .a& .b == .b)
+		// add them on to all the current selectors
+		if( $currentElements ){
+			$this->mergeElementsOnToSelectors($currentElements, $newSelectors);
+		}
+		foreach( $newSelectors as $new_sel){
+			if( $new_sel ){
+				$paths[] = $new_sel;
+			}
+		}
+	}
+
+	function mergeElementsOnToSelectors( $elements, &$selectors){
+
+		if( !$selectors ){
+			$selectors[] = array( new Less_Tree_Selector($elements) );
+			return;
+		}
+
+
+		foreach( $selectors as &$sel){
+
+			// if the previous thing in sel is a parent this needs to join on to it
+			if( $sel ){
+				$last = count($sel)-1;
+				$sel[$last] = $sel[$last]->createDerived( array_merge($sel[$last]->elements, $elements) );
+			}else{
+				$sel[] = new Less_Tree_Selector( $elements );
+			}
+		}
+	}
+}
+ 
+
+/**
+ * RulesetCall
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_RulesetCall extends Less_Tree{
+
+	public $variable;
+	public $type = "RulesetCall";
+
+    public function __construct($variable){
+		$this->variable = $variable;
+	}
+
+    public function accept($visitor) {}
+
+    public function compile( $env ){
+		$variable = new Less_Tree_Variable($this->variable);
+		$detachedRuleset = $variable->compile($env);
+		return $detachedRuleset->callEval($env);
+	}
+}
+
+ 
+
+/**
+ * Selector
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Selector extends Less_Tree{
+
+	public $elements;
+	public $condition;
+	public $extendList = array();
+	public $_css;
+	public $index;
+	public $evaldCondition = false;
+	public $type = 'Selector';
+	public $currentFileInfo = array();
+	public $isReferenced;
+	public $mediaEmpty;
+
+	public $elements_len = 0;
+
+	public $_oelements;
+	public $_oelements_len;
+	public $cacheable = true;
+
+	/**
+	 * @param boolean $isReferenced
+	 */
+	public function __construct( $elements, $extendList = array() , $condition = null, $index=null, $currentFileInfo=null, $isReferenced=null ){
+
+		$this->elements = $elements;
+		$this->elements_len = count($elements);
+		$this->extendList = $extendList;
+		$this->condition = $condition;
+		if( $currentFileInfo ){
+			$this->currentFileInfo = $currentFileInfo;
+		}
+		$this->isReferenced = $isReferenced;
+		if( !$condition ){
+			$this->evaldCondition = true;
+		}
+
+		$this->CacheElements();
+	}
+
+    public function accept($visitor) {
+		$this->elements = $visitor->visitArray($this->elements);
+		$this->extendList = $visitor->visitArray($this->extendList);
+		if( $this->condition ){
+			$this->condition = $visitor->visitObj($this->condition);
+		}
+
+		if( $visitor instanceof Less_Visitor_extendFinder ){
+			$this->CacheElements();
+		}
+	}
+
+    public function createDerived( $elements, $extendList = null, $evaldCondition = null ){
+		$newSelector = new Less_Tree_Selector( $elements, ($extendList ? $extendList : $this->extendList), null, $this->index, $this->currentFileInfo, $this->isReferenced);
+		$newSelector->evaldCondition = $evaldCondition ? $evaldCondition : $this->evaldCondition;
+		return $newSelector;
+	}
+
+
+	public function match( $other ){
+
+		if( !$other->_oelements || ($this->elements_len < $other->_oelements_len) ){
+			return 0;
+		}
+
+		for( $i = 0; $i < $other->_oelements_len; $i++ ){
+			if( $this->elements[$i]->value !== $other->_oelements[$i]) {
+				return 0;
+			}
+		}
+
+		return $other->_oelements_len; // return number of matched elements
+	}
+
+
+	public function CacheElements(){
+
+		$this->_oelements = array();
+		$css = '';
+
+		foreach($this->elements as $v){
+
+			$css .= $v->combinator;
+			if( !$v->value_is_object ){
+				$css .= $v->value;
+				continue;
+			}
+
+			if( !property_exists($v->value,'value') || !is_string($v->value->value) ){
+				$this->cacheable = false;
+				return;
+			}
+			$css .= $v->value->value;
+		}
+
+		$this->_oelements_len = preg_match_all('/[,&#\.\w-](?:[\w-]|(?:\\\\.))*/', $css, $matches);
+		if( $this->_oelements_len ){
+			$this->_oelements = $matches[0];
+
+			if( $this->_oelements[0] === '&' ){
+				array_shift($this->_oelements);
+				$this->_oelements_len--;
+			}
+		}
+	}
+
+	public function isJustParentSelector(){
+		return !$this->mediaEmpty &&
+			count($this->elements) === 1 &&
+			$this->elements[0]->value === '&' &&
+			($this->elements[0]->combinator === ' ' || $this->elements[0]->combinator === '');
+	}
+
+	public function compile($env) {
+
+		$elements = array();
+		foreach($this->elements as $el){
+			$elements[] = $el->compile($env);
+		}
+
+		$extendList = array();
+		foreach($this->extendList as $el){
+			$extendList[] = $el->compile($el);
+		}
+
+		$evaldCondition = false;
+		if( $this->condition ){
+			$evaldCondition = $this->condition->compile($env);
+		}
+
+		return $this->createDerived( $elements, $extendList, $evaldCondition );
+	}
+
+
+	/**
+	 * @see Less_Tree::genCSS
+	 */
+    public function genCSS( $output, $firstSelector = true ){
+
+		if( !$firstSelector && $this->elements[0]->combinator === "" ){
+			$output->add(' ', $this->currentFileInfo, $this->index);
+		}
+
+		foreach($this->elements as $element){
+			$element->genCSS( $output );
+		}
+	}
+
+    public function markReferenced(){
+		$this->isReferenced = true;
+	}
+
+    public function getIsReferenced(){
+		return !isset($this->currentFileInfo['reference']) || !$this->currentFileInfo['reference'] || $this->isReferenced;
+	}
+
+    public function getIsOutput(){
+		return $this->evaldCondition;
+	}
+
+}
+ 
+
+/**
+ * UnicodeDescriptor
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_UnicodeDescriptor extends Less_Tree{
+
+	public $value;
+	public $type = 'UnicodeDescriptor';
+
+	public function __construct($value){
+		$this->value = $value;
+	}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+	public function genCSS( $output ){
+		$output->add( $this->value );
+	}
+
+	public function compile(){
+		return $this;
+	}
+}
+
+ 
+
+/**
+ * Unit
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Unit extends Less_Tree{
+
+	var $numerator = array();
+	var $denominator = array();
+	public $backupUnit;
+	public $type = 'Unit';
+
+    public function __construct($numerator = array(), $denominator = array(), $backupUnit = null ){
+		$this->numerator = $numerator;
+		$this->denominator = $denominator;
+		$this->backupUnit = $backupUnit;
+	}
+
+    public function __clone(){
+	}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+    public function genCSS( $output ){
+
+		if( $this->numerator ){
+			$output->add( $this->numerator[0] );
+		}elseif( $this->denominator ){
+			$output->add( $this->denominator[0] );
+		}elseif( !Less_Parser::$options['strictUnits'] && $this->backupUnit ){
+			$output->add( $this->backupUnit );
+			return ;
+		}
+	}
+
+    public function toString(){
+		$returnStr = implode('*',$this->numerator);
+		foreach($this->denominator as $d){
+			$returnStr .= '/'.$d;
+		}
+		return $returnStr;
+	}
+
+    public function __toString(){
+		return $this->toString();
+	}
+
+
+	/**
+	 * @param Less_Tree_Unit $other
+	 */
+    public function compare($other) {
+		return $this->is( $other->toString() ) ? 0 : -1;
+	}
+
+    public function is($unitString){
+		return $this->toString() === $unitString;
+	}
+
+    public function isLength(){
+		$css = $this->toCSS();
+		return !!preg_match('/px|em|%|in|cm|mm|pc|pt|ex/',$css);
+	}
+
+    public function isAngle() {
+		return isset( Less_Tree_UnitConversions::$angle[$this->toCSS()] );
+	}
+
+    public function isEmpty(){
+		return !$this->numerator && !$this->denominator;
+	}
+
+    public function isSingular() {
+		return count($this->numerator) <= 1 && !$this->denominator;
+	}
+
+
+    public function usedUnits(){
+		$result = array();
+
+		foreach(Less_Tree_UnitConversions::$groups as $groupName){
+			$group = Less_Tree_UnitConversions::${$groupName};
+
+			foreach($this->numerator as $atomicUnit){
+				if( isset($group[$atomicUnit]) && !isset($result[$groupName]) ){
+					$result[$groupName] = $atomicUnit;
+				}
+			}
+
+			foreach($this->denominator as $atomicUnit){
+				if( isset($group[$atomicUnit]) && !isset($result[$groupName]) ){
+					$result[$groupName] = $atomicUnit;
+				}
+			}
+		}
+
+		return $result;
+	}
+
+    public function cancel(){
+		$counter = array();
+		$backup = null;
+
+		foreach($this->numerator as $atomicUnit){
+			if( !$backup ){
+				$backup = $atomicUnit;
+			}
+			$counter[$atomicUnit] = ( isset($counter[$atomicUnit]) ? $counter[$atomicUnit] : 0) + 1;
+		}
+
+		foreach($this->denominator as $atomicUnit){
+			if( !$backup ){
+				$backup = $atomicUnit;
+			}
+			$counter[$atomicUnit] = ( isset($counter[$atomicUnit]) ? $counter[$atomicUnit] : 0) - 1;
+		}
+
+		$this->numerator = array();
+		$this->denominator = array();
+
+		foreach($counter as $atomicUnit => $count){
+			if( $count > 0 ){
+				for( $i = 0; $i < $count; $i++ ){
+					$this->numerator[] = $atomicUnit;
+				}
+			}elseif( $count < 0 ){
+				for( $i = 0; $i < -$count; $i++ ){
+					$this->denominator[] = $atomicUnit;
+				}
+			}
+		}
+
+		if( !$this->numerator && !$this->denominator && $backup ){
+			$this->backupUnit = $backup;
+		}
+
+		sort($this->numerator);
+		sort($this->denominator);
+	}
+
+
+}
+
+ 
+
+/**
+ * UnitConversions
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_UnitConversions{
+
+	public static $groups = array('length','duration','angle');
+
+	public static $length = array(
+		'm'=> 1,
+		'cm'=> 0.01,
+		'mm'=> 0.001,
+		'in'=> 0.0254,
+		'px'=> 0.000264583, // 0.0254 / 96,
+		'pt'=> 0.000352778, // 0.0254 / 72,
+		'pc'=> 0.004233333, // 0.0254 / 72 * 12
+		);
+
+	public static $duration = array(
+		's'=> 1,
+		'ms'=> 0.001
+		);
+
+	public static $angle = array(
+		'rad' => 0.1591549430919,	// 1/(2*M_PI),
+		'deg' => 0.002777778, 		// 1/360,
+		'grad'=> 0.0025,			// 1/400,
+		'turn'=> 1
+		);
+
+} 
+
+/**
+ * Url
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Url extends Less_Tree{
+
+	public $attrs;
+	public $value;
+	public $currentFileInfo;
+	public $isEvald;
+	public $type = 'Url';
+
+	public function __construct($value, $currentFileInfo = null, $isEvald = null){
+		$this->value = $value;
+		$this->currentFileInfo = $currentFileInfo;
+		$this->isEvald = $isEvald;
+	}
+
+    public function accept( $visitor ){
+		$this->value = $visitor->visitObj($this->value);
+	}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+    public function genCSS( $output ){
+		$output->add( 'url(' );
+		$this->value->genCSS( $output );
+		$output->add( ')' );
+	}
+
+	/**
+	 * @param Less_Functions $ctx
+	 */
+	public function compile($ctx){
+		$val = $this->value->compile($ctx);
+
+		if( !$this->isEvald ){
+			// Add the base path if the URL is relative
+			if( Less_Parser::$options['relativeUrls']
+				&& $this->currentFileInfo
+				&& is_string($val->value)
+				&& Less_Environment::isPathRelative($val->value)
+			){
+				$rootpath = $this->currentFileInfo['uri_root'];
+				if ( !$val->quote ){
+					$rootpath = preg_replace('/[\(\)\'"\s]/', '\\$1', $rootpath );
+				}
+				$val->value = $rootpath . $val->value;
+			}
+
+			$val->value = Less_Environment::normalizePath( $val->value);
+		}
+
+		// Add cache buster if enabled
+		if( Less_Parser::$options['urlArgs'] ){
+			if( !preg_match('/^\s*data:/',$val->value) ){
+				$delimiter = strpos($val->value,'?') === false ? '?' : '&';
+				$urlArgs = $delimiter . Less_Parser::$options['urlArgs'];
+				$hash_pos = strpos($val->value,'#');
+				if( $hash_pos !== false ){
+					$val->value = substr_replace($val->value,$urlArgs, $hash_pos, 0);
+				} else {
+					$val->value .= $urlArgs;
+				}
+			}
+		}
+
+		return new Less_Tree_URL($val, $this->currentFileInfo, true);
+	}
+
+}
+ 
+
+/**
+ * Value
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Value extends Less_Tree{
+
+	public $type = 'Value';
+	public $value;
+
+	public function __construct($value){
+		$this->value = $value;
+	}
+
+    public function accept($visitor) {
+		$this->value = $visitor->visitArray($this->value);
+	}
+
+	public function compile($env){
+
+		$ret = array();
+		$i = 0;
+		foreach($this->value as $i => $v){
+			$ret[] = $v->compile($env);
+		}
+		if( $i > 0 ){
+			return new Less_Tree_Value($ret);
+		}
+		return $ret[0];
+	}
+
+    /**
+     * @see Less_Tree::genCSS
+     */
+	function genCSS( $output ){
+		$len = count($this->value);
+		for($i = 0; $i < $len; $i++ ){
+			$this->value[$i]->genCSS( $output );
+			if( $i+1 < $len ){
+				$output->add( Less_Environment::$_outputMap[','] );
+			}
+		}
+	}
+
+}
+ 
+
+/**
+ * Variable
+ *
+ * @package Less
+ * @subpackage tree
+ */
+class Less_Tree_Variable extends Less_Tree{
+
+	public $name;
+	public $index;
+	public $currentFileInfo;
+	public $evaluating = false;
+	public $type = 'Variable';
+
+    /**
+     * @param string $name
+     */
+    public function __construct($name, $index = null, $currentFileInfo = null) {
+        $this->name = $name;
+        $this->index = $index;
+		$this->currentFileInfo = $currentFileInfo;
+    }
+
+	public function compile($env) {
+
+		if( $this->name[1] === '@' ){
+			$v = new Less_Tree_Variable(substr($this->name, 1), $this->index + 1, $this->currentFileInfo);
+			$name = '@' . $v->compile($env)->value;
+		}else{
+			$name = $this->name;
+		}
+
+		if ($this->evaluating) {
+			throw new Less_Exception_Compiler("Recursive variable definition for " . $name, null, $this->index, $this->currentFileInfo);
+		}
+
+		$this->evaluating = true;
+
+		foreach($env->frames as $frame){
+			if( $v = $frame->variable($name) ){
+				$r = $v->value->compile($env);
+				$this->evaluating = false;
+				return $r;
+			}
+		}
+
+		throw new Less_Exception_Compiler("variable " . $name . " is undefined in file ".$this->currentFileInfo["filename"], null, $this->index, $this->currentFileInfo);
+	}
+
+}
+ 
+
+
+class Less_Tree_Mixin_Call extends Less_Tree{
+
+	public $selector;
+	public $arguments;
+	public $index;
+	public $currentFileInfo;
+
+	public $important;
+	public $type = 'MixinCall';
+
+	/**
+	 * less.js: tree.mixin.Call
+	 *
+	 */
+	public function __construct($elements, $args, $index, $currentFileInfo, $important = false){
+		$this->selector = new Less_Tree_Selector($elements);
+		$this->arguments = $args;
+		$this->index = $index;
+		$this->currentFileInfo = $currentFileInfo;
+		$this->important = $important;
+	}
+
+	//function accept($visitor){
+	//	$this->selector = $visitor->visit($this->selector);
+	//	$this->arguments = $visitor->visit($this->arguments);
+	//}
+
+
+	public function compile($env){
+
+		$rules = array();
+		$match = false;
+		$isOneFound = false;
+		$candidates = array();
+		$defaultUsed = false;
+		$conditionResult = array();
+
+		$args = array();
+		foreach($this->arguments as $a){
+			$args[] = array('name'=> $a['name'], 'value' => $a['value']->compile($env) );
+		}
+
+		foreach($env->frames as $frame){
+
+			$mixins = $frame->find($this->selector);
+
+			if( !$mixins ){
+				continue;
+			}
+
+			$isOneFound = true;
+			$defNone = 0;
+			$defTrue = 1;
+			$defFalse = 2;
+
+			// To make `default()` function independent of definition order we have two "subpasses" here.
+			// At first we evaluate each guard *twice* (with `default() == true` and `default() == false`),
+			// and build candidate list with corresponding flags. Then, when we know all possible matches,
+			// we make a final decision.
+
+			$mixins_len = count($mixins);
+			for( $m = 0; $m < $mixins_len; $m++ ){
+				$mixin = $mixins[$m];
+
+				if( $this->IsRecursive( $env, $mixin ) ){
+					continue;
+				}
+
+				if( $mixin->matchArgs($args, $env) ){
+
+					$candidate = array('mixin' => $mixin, 'group' => $defNone);
+
+					if( $mixin instanceof Less_Tree_Ruleset ){
+
+						for( $f = 0; $f < 2; $f++ ){
+							Less_Tree_DefaultFunc::value($f);
+							$conditionResult[$f] = $mixin->matchCondition( $args, $env);
+						}
+						if( $conditionResult[0] || $conditionResult[1] ){
+							if( $conditionResult[0] != $conditionResult[1] ){
+								$candidate['group'] = $conditionResult[1] ? $defTrue : $defFalse;
+							}
+
+							$candidates[] = $candidate;
+						}
+					}else{
+						$candidates[] = $candidate;
+					}
+
+					$match = true;
+				}
+			}
+
+			Less_Tree_DefaultFunc::reset();
+
+
+			$count = array(0, 0, 0);
+			for( $m = 0; $m < count($candidates); $m++ ){
+				$count[ $candidates[$m]['group'] ]++;
+			}
+
+			if( $count[$defNone] > 0 ){
+				$defaultResult = $defFalse;
+			} else {
+				$defaultResult = $defTrue;
+				if( ($count[$defTrue] + $count[$defFalse]) > 1 ){
+					throw new Exception( 'Ambiguous use of `default()` found when matching for `'. $this->format($args) + '`' );
+				}
+			}
+
+
+			$candidates_length = count($candidates);
+			$length_1 = ($candidates_length == 1);
+
+			for( $m = 0; $m < $candidates_length; $m++){
+				$candidate = $candidates[$m]['group'];
+				if( ($candidate === $defNone) || ($candidate === $defaultResult) ){
+					try{
+						$mixin = $candidates[$m]['mixin'];
+						if( !($mixin instanceof Less_Tree_Mixin_Definition) ){
+							$mixin = new Less_Tree_Mixin_Definition('', array(), $mixin->rules, null, false);
+							$mixin->originalRuleset = $mixins[$m]->originalRuleset;
+						}
+						$rules = array_merge($rules, $mixin->evalCall($env, $args, $this->important)->rules);
+					} catch (Exception $e) {
+						//throw new Less_Exception_Compiler($e->getMessage(), $e->index, null, $this->currentFileInfo['filename']);
+						throw new Less_Exception_Compiler($e->getMessage(), null, null, $this->currentFileInfo);
+					}
+				}
+			}
+
+			if( $match ){
+				if( !$this->currentFileInfo || !isset($this->currentFileInfo['reference']) || !$this->currentFileInfo['reference'] ){
+					Less_Tree::ReferencedArray($rules);
+				}
+
+				return $rules;
+			}
+		}
+
+		if( $isOneFound ){
+			throw new Less_Exception_Compiler('No matching definition was found for `'.$this->Format( $args ).'`', null, $this->index, $this->currentFileInfo);
+
+		}else{
+			throw new Less_Exception_Compiler(trim($this->selector->toCSS()) . " is undefined in ".$this->currentFileInfo['filename'], null, $this->index);
+		}
+
+	}
+
+	/**
+	 * Format the args for use in exception messages
+	 *
+	 */
+	private function Format($args){
+		$message = array();
+		if( $args ){
+			foreach($args as $a){
+				$argValue = '';
+				if( $a['name'] ){
+					$argValue += $a['name']+':';
+				}
+				if( is_object($a['value']) ){
+					$argValue += $a['value']->toCSS();
+				}else{
+					$argValue += '???';
+				}
+				$message[] = $argValue;
+			}
+		}
+		return implode(', ',$message);
+	}
+
+
+	/**
+	 * Are we in a recursive mixin call?
+	 *
+	 * @return bool
+	 */
+	private function IsRecursive( $env, $mixin ){
+
+		foreach($env->frames as $recur_frame){
+			if( !($mixin instanceof Less_Tree_Mixin_Definition) ){
+
+				if( $mixin === $recur_frame ){
+					return true;
+				}
+
+				if( isset($recur_frame->originalRuleset) && $mixin->ruleset_id === $recur_frame->originalRuleset ){
+					return true;
+				}
+			}
+		}
+
+		return false;
+	}
+
+}
+
+
+ 
+
+class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset{
+	public $name;
+	public $selectors;
+	public $params;
+	public $arity		= 0;
+	public $rules;
+	public $lookups		= array();
+	public $required	= 0;
+	public $frames		= array();
+	public $condition;
+	public $variadic;
+	public $type		= 'MixinDefinition';
+
+
+	// less.js : /lib/less/tree/mixin.js : tree.mixin.Definition
+	public function __construct($name, $params, $rules, $condition, $variadic = false, $frames = array() ){
+		$this->name = $name;
+		$this->selectors = array(new Less_Tree_Selector(array( new Less_Tree_Element(null, $name))));
+
+		$this->params = $params;
+		$this->condition = $condition;
+		$this->variadic = $variadic;
+		$this->rules = $rules;
+
+		if( $params ){
+			$this->arity = count($params);
+			foreach( $params as $p ){
+				if (! isset($p['name']) || ($p['name'] && !isset($p['value']))) {
+					$this->required++;
+				}
+			}
+		}
+
+		$this->frames = $frames;
+		$this->SetRulesetIndex();
+	}
+
+
+
+	//function accept( $visitor ){
+	//	$this->params = $visitor->visit($this->params);
+	//	$this->rules = $visitor->visit($this->rules);
+	//	$this->condition = $visitor->visit($this->condition);
+	//}
+
+
+	public function toCSS(){
+		return '';
+	}
+
+	// less.js : /lib/less/tree/mixin.js : tree.mixin.Definition.evalParams
+	public function compileParams($env, $mixinFrames, $args = array() , &$evaldArguments = array() ){
+		$frame = new Less_Tree_Ruleset(null, array());
+		$params = $this->params;
+		$mixinEnv = null;
+		$argsLength = 0;
+
+		if( $args ){
+			$argsLength = count($args);
+			for($i = 0; $i < $argsLength; $i++ ){
+				$arg = $args[$i];
+
+				if( $arg && $arg['name'] ){
+					$isNamedFound = false;
+
+					foreach($params as $j => $param){
+						if( !isset($evaldArguments[$j]) && $arg['name'] === $params[$j]['name']) {
+							$evaldArguments[$j] = $arg['value']->compile($env);
+							array_unshift($frame->rules, new Less_Tree_Rule( $arg['name'], $arg['value']->compile($env) ) );
+							$isNamedFound = true;
+							break;
+						}
+					}
+					if ($isNamedFound) {
+						array_splice($args, $i, 1);
+						$i--;
+						$argsLength--;
+						continue;
+					} else {
+						throw new Less_Exception_Compiler("Named argument for " . $this->name .' '.$args[$i]['name'] . ' not found');
+					}
+				}
+			}
+		}
+
+		$argIndex = 0;
+		foreach($params as $i => $param){
+
+			if ( isset($evaldArguments[$i]) ){ continue; }
+
+			$arg = null;
+			if( isset($args[$argIndex]) ){
+				$arg = $args[$argIndex];
+			}
+
+			if (isset($param['name']) && $param['name']) {
+
+				if( isset($param['variadic']) ){
+					$varargs = array();
+					for ($j = $argIndex; $j < $argsLength; $j++) {
+						$varargs[] = $args[$j]['value']->compile($env);
+					}
+					$expression = new Less_Tree_Expression($varargs);
+					array_unshift($frame->rules, new Less_Tree_Rule($param['name'], $expression->compile($env)));
+				}else{
+					$val = ($arg && $arg['value']) ? $arg['value'] : false;
+
+					if ($val) {
+						$val = $val->compile($env);
+					} else if ( isset($param['value']) ) {
+
+						if( !$mixinEnv ){
+							$mixinEnv = new Less_Environment();
+							$mixinEnv->frames = array_merge( array($frame), $mixinFrames);
+						}
+
+						$val = $param['value']->compile($mixinEnv);
+						$frame->resetCache();
+					} else {
+						throw new Less_Exception_Compiler("Wrong number of arguments for " . $this->name . " (" . $argsLength . ' for ' . $this->arity . ")");
+					}
+
+					array_unshift($frame->rules, new Less_Tree_Rule($param['name'], $val));
+					$evaldArguments[$i] = $val;
+				}
+			}
+
+			if ( isset($param['variadic']) && $args) {
+				for ($j = $argIndex; $j < $argsLength; $j++) {
+					$evaldArguments[$j] = $args[$j]['value']->compile($env);
+				}
+			}
+			$argIndex++;
+		}
+
+		ksort($evaldArguments);
+		$evaldArguments = array_values($evaldArguments);
+
+		return $frame;
+	}
+
+	public function compile($env) {
+		if( $this->frames ){
+			return new Less_Tree_Mixin_Definition($this->name, $this->params, $this->rules, $this->condition, $this->variadic, $this->frames );
+		}
+		return new Less_Tree_Mixin_Definition($this->name, $this->params, $this->rules, $this->condition, $this->variadic, $env->frames );
+	}
+
+	public function evalCall($env, $args = NULL, $important = NULL) {
+
+		Less_Environment::$mixin_stack++;
+
+		$_arguments = array();
+
+		if( $this->frames ){
+			$mixinFrames = array_merge($this->frames, $env->frames);
+		}else{
+			$mixinFrames = $env->frames;
+		}
+
+		$frame = $this->compileParams($env, $mixinFrames, $args, $_arguments);
+
+		$ex = new Less_Tree_Expression($_arguments);
+		array_unshift($frame->rules, new Less_Tree_Rule('@arguments', $ex->compile($env)));
+
+
+		$ruleset = new Less_Tree_Ruleset(null, $this->rules);
+		$ruleset->originalRuleset = $this->ruleset_id;
+
+
+		$ruleSetEnv = new Less_Environment();
+		$ruleSetEnv->frames = array_merge( array($this, $frame), $mixinFrames );
+		$ruleset = $ruleset->compile( $ruleSetEnv );
+
+		if( $important ){
+			$ruleset = $ruleset->makeImportant();
+		}
+
+		Less_Environment::$mixin_stack--;
+
+		return $ruleset;
+	}
+
+
+	public function matchCondition($args, $env) {
+
+		if( !$this->condition ){
+			return true;
+		}
+
+		// set array to prevent error on array_merge
+		if(!is_array($this->frames)) {
+             $this->frames = array();
+        }
+
+		$frame = $this->compileParams($env, array_merge($this->frames,$env->frames), $args );
+
+		$compile_env = new Less_Environment();
+		$compile_env->frames = array_merge(
+				array($frame)		// the parameter variables
+				, $this->frames		// the parent namespace/mixin frames
+				, $env->frames		// the current environment frames
+			);
+
+		$compile_env->functions = $env->functions;
+
+		return (bool)$this->condition->compile($compile_env);
+	}
+
+	public function matchArgs($args, $env = NULL){
+		$argsLength = count($args);
+
+		if( !$this->variadic ){
+			if( $argsLength < $this->required ){
+				return false;
+			}
+			if( $argsLength > count($this->params) ){
+				return false;
+			}
+		}else{
+			if( $argsLength < ($this->required - 1)){
+				return false;
+			}
+		}
+
+		$len = min($argsLength, $this->arity);
+
+		for( $i = 0; $i < $len; $i++ ){
+			if( !isset($this->params[$i]['name']) && !isset($this->params[$i]['variadic']) ){
+				if( $args[$i]['value']->compile($env)->toCSS() != $this->params[$i]['value']->compile($env)->toCSS() ){
+					return false;
+				}
+			}
+		}
+
+		return true;
+	}
+
+}
+ 
+
+/**
+ * Extend Finder Visitor
+ *
+ * @package Less
+ * @subpackage visitor
+ */
+class Less_Visitor_extendFinder extends Less_Visitor{
+
+	public $contexts = array();
+	public $allExtendsStack;
+	public $foundExtends;
+
+	public function __construct(){
+		$this->contexts = array();
+		$this->allExtendsStack = array(array());
+		parent::__construct();
+	}
+
+	/**
+	 * @param Less_Tree_Ruleset $root
+	 */
+    public function run($root){
+		$root = $this->visitObj($root);
+		$root->allExtends =& $this->allExtendsStack[0];
+		return $root;
+	}
+
+    public function visitRule($ruleNode, &$visitDeeper ){
+		$visitDeeper = false;
+	}
+
+    public function visitMixinDefinition( $mixinDefinitionNode, &$visitDeeper ){
+		$visitDeeper = false;
+	}
+
+    public function visitRuleset($rulesetNode){
+
+		if( $rulesetNode->root ){
+			return;
+		}
+
+		$allSelectorsExtendList = array();
+
+		// get &:extend(.a); rules which apply to all selectors in this ruleset
+		if( $rulesetNode->rules ){
+			foreach($rulesetNode->rules as $rule){
+				if( $rule instanceof Less_Tree_Extend ){
+					$allSelectorsExtendList[] = $rule;
+					$rulesetNode->extendOnEveryPath = true;
+				}
+			}
+		}
+
+
+		// now find every selector and apply the extends that apply to all extends
+		// and the ones which apply to an individual extend
+		foreach($rulesetNode->paths as $selectorPath){
+			$selector = end($selectorPath); //$selectorPath[ count($selectorPath)-1];
+
+			$j = 0;
+			foreach($selector->extendList as $extend){
+				$this->allExtendsStackPush($rulesetNode, $selectorPath, $extend, $j);
+			}
+			foreach($allSelectorsExtendList as $extend){
+				$this->allExtendsStackPush($rulesetNode, $selectorPath, $extend, $j);
+			}
+		}
+
+		$this->contexts[] = $rulesetNode->selectors;
+	}
+
+    public function allExtendsStackPush($rulesetNode, $selectorPath, $extend, &$j){
+		$this->foundExtends = true;
+		$extend = clone $extend;
+		$extend->findSelfSelectors( $selectorPath );
+		$extend->ruleset = $rulesetNode;
+		if( $j === 0 ){
+			$extend->firstExtendOnThisSelectorPath = true;
+		}
+
+		$end_key = count($this->allExtendsStack)-1;
+		$this->allExtendsStack[$end_key][] = $extend;
+		$j++;
+	}
+
+
+    public function visitRulesetOut( $rulesetNode ){
+		if( !is_object($rulesetNode) || !$rulesetNode->root ){
+			array_pop($this->contexts);
+		}
+	}
+
+    public function visitMedia( $mediaNode ){
+		$mediaNode->allExtends = array();
+		$this->allExtendsStack[] =& $mediaNode->allExtends;
+	}
+
+    public function visitMediaOut(){
+		array_pop($this->allExtendsStack);
+	}
+
+    public function visitDirective( $directiveNode ){
+		$directiveNode->allExtends = array();
+		$this->allExtendsStack[] =& $directiveNode->allExtends;
+	}
+
+    public function visitDirectiveOut(){
+		array_pop($this->allExtendsStack);
+	}
+}
+
+
+ 
+
+/*
+class Less_Visitor_import extends Less_VisitorReplacing{
+
+	public $_visitor;
+	public $_importer;
+	public $importCount;
+
+	function __construct( $evalEnv ){
+		$this->env = $evalEnv;
+		$this->importCount = 0;
+		parent::__construct();
+	}
+
+
+	function run( $root ){
+		$root = $this->visitObj($root);
+		$this->isFinished = true;
+
+		//if( $this->importCount === 0) {
+		//	$this->_finish();
+		//}
+	}
+
+	function visitImport($importNode, &$visitDeeper ){
+		$importVisitor = $this;
+		$inlineCSS = $importNode->options['inline'];
+
+		if( !$importNode->css || $inlineCSS ){
+			$evaldImportNode = $importNode->compileForImport($this->env);
+
+			if( $evaldImportNode && (!$evaldImportNode->css || $inlineCSS) ){
+				$importNode = $evaldImportNode;
+				$this->importCount++;
+				$env = clone $this->env;
+
+				if( (isset($importNode->options['multiple']) && $importNode->options['multiple']) ){
+					$env->importMultiple = true;
+				}
+
+				//get path & uri
+				$path_and_uri = null;
+				if( is_callable(Less_Parser::$options['import_callback']) ){
+					$path_and_uri = call_user_func(Less_Parser::$options['import_callback'],$importNode);
+				}
+
+				if( !$path_and_uri ){
+					$path_and_uri = $importNode->PathAndUri();
+				}
+
+				if( $path_and_uri ){
+					list($full_path, $uri) = $path_and_uri;
+				}else{
+					$full_path = $uri = $importNode->getPath();
+				}
+
+
+				//import once
+				if( $importNode->skip( $full_path, $env) ){
+					return array();
+				}
+
+				if( $importNode->options['inline'] ){
+					//todo needs to reference css file not import
+					//$contents = new Less_Tree_Anonymous($importNode->root, 0, array('filename'=>$importNode->importedFilename), true );
+
+					Less_Parser::AddParsedFile($full_path);
+					$contents = new Less_Tree_Anonymous( file_get_contents($full_path), 0, array(), true );
+
+					if( $importNode->features ){
+						return new Less_Tree_Media( array($contents), $importNode->features->value );
+					}
+
+					return array( $contents );
+				}
+
+
+				// css ?
+				if( $importNode->css ){
+					$features = ( $importNode->features ? $importNode->features->compile($env) : null );
+					return new Less_Tree_Import( $importNode->compilePath( $env), $features, $importNode->options, $this->index);
+				}
+
+				return $importNode->ParseImport( $full_path, $uri, $env );
+			}
+
+		}
+
+		$visitDeeper = false;
+		return $importNode;
+	}
+
+
+	function visitRule( $ruleNode, &$visitDeeper ){
+		$visitDeeper = false;
+		return $ruleNode;
+	}
+
+	function visitDirective($directiveNode, $visitArgs){
+		array_unshift($this->env->frames,$directiveNode);
+		return $directiveNode;
+	}
+
+	function visitDirectiveOut($directiveNode) {
+		array_shift($this->env->frames);
+	}
+
+	function visitMixinDefinition($mixinDefinitionNode, $visitArgs) {
+		array_unshift($this->env->frames,$mixinDefinitionNode);
+		return $mixinDefinitionNode;
+	}
+
+	function visitMixinDefinitionOut($mixinDefinitionNode) {
+		array_shift($this->env->frames);
+	}
+
+	function visitRuleset($rulesetNode, $visitArgs) {
+		array_unshift($this->env->frames,$rulesetNode);
+		return $rulesetNode;
+	}
+
+	function visitRulesetOut($rulesetNode) {
+		array_shift($this->env->frames);
+	}
+
+	function visitMedia($mediaNode, $visitArgs) {
+		array_unshift($this->env->frames, $mediaNode->ruleset);
+		return $mediaNode;
+	}
+
+	function visitMediaOut($mediaNode) {
+		array_shift($this->env->frames);
+	}
+
+}
+*/
+
+
+ 
+
+/**
+ * Join Selector Visitor
+ *
+ * @package Less
+ * @subpackage visitor
+ */
+class Less_Visitor_joinSelector extends Less_Visitor{
+
+	public $contexts = array( array() );
+
+	/**
+	 * @param Less_Tree_Ruleset $root
+	 */
+	public function run( $root ){
+		return $this->visitObj($root);
+	}
+
+    public function visitRule( $ruleNode, &$visitDeeper ){
+		$visitDeeper = false;
+	}
+
+    public function visitMixinDefinition( $mixinDefinitionNode, &$visitDeeper ){
+		$visitDeeper = false;
+	}
+
+    public function visitRuleset( $rulesetNode ){
+
+		$paths = array();
+
+		if( !$rulesetNode->root ){
+			$selectors = array();
+
+			if( $rulesetNode->selectors && $rulesetNode->selectors ){
+				foreach($rulesetNode->selectors as $selector){
+					if( $selector->getIsOutput() ){
+						$selectors[] = $selector;
+					}
+				}
+			}
+
+			if( !$selectors ){
+				$rulesetNode->selectors = null;
+				$rulesetNode->rules = null;
+			}else{
+				$context = end($this->contexts); //$context = $this->contexts[ count($this->contexts) - 1];
+				$paths = $rulesetNode->joinSelectors( $context, $selectors);
+			}
+
+			$rulesetNode->paths = $paths;
+		}
+
+		$this->contexts[] = $paths; //different from less.js. Placed after joinSelectors() so that $this->contexts will get correct $paths
+	}
+
+    public function visitRulesetOut(){
+		array_pop($this->contexts);
+	}
+
+    public function visitMedia($mediaNode) {
+		$context = end($this->contexts); //$context = $this->contexts[ count($this->contexts) - 1];
+
+		if( !count($context) || (is_object($context[0]) && $context[0]->multiMedia) ){
+			$mediaNode->rules[0]->root = true;
+		}
+	}
+
+}
+
+ 
+
+/**
+ * Process Extends Visitor
+ *
+ * @package Less
+ * @subpackage visitor
+ */
+class Less_Visitor_processExtends extends Less_Visitor{
+
+	public $allExtendsStack;
+
+	/**
+	 * @param Less_Tree_Ruleset $root
+	 */
+	public function run( $root ){
+		$extendFinder = new Less_Visitor_extendFinder();
+		$extendFinder->run( $root );
+		if( !$extendFinder->foundExtends){
+			return $root;
+		}
+
+		$root->allExtends = $this->doExtendChaining( $root->allExtends, $root->allExtends);
+
+		$this->allExtendsStack = array();
+		$this->allExtendsStack[] = &$root->allExtends;
+
+		return $this->visitObj( $root );
+	}
+
+	private function doExtendChaining( $extendsList, $extendsListTarget, $iterationCount = 0){
+		//
+		// chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting
+		// the selector we would do normally, but we are also adding an extend with the same target selector
+		// this means this new extend can then go and alter other extends
+		//
+		// this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors
+		// this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if
+		// we look at each selector at a time, as is done in visitRuleset
+
+		$extendsToAdd = array();
+
+
+		//loop through comparing every extend with every target extend.
+		// a target extend is the one on the ruleset we are looking at copy/edit/pasting in place
+		// e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one
+		// and the second is the target.
+		// the seperation into two lists allows us to process a subset of chains with a bigger set, as is the
+		// case when processing media queries
+		for( $extendIndex = 0, $extendsList_len = count($extendsList); $extendIndex < $extendsList_len; $extendIndex++ ){
+			for( $targetExtendIndex = 0; $targetExtendIndex < count($extendsListTarget); $targetExtendIndex++ ){
+
+				$extend = $extendsList[$extendIndex];
+				$targetExtend = $extendsListTarget[$targetExtendIndex];
+
+				// look for circular references
+				if( in_array($targetExtend->object_id, $extend->parent_ids,true) ){
+					continue;
+				}
+
+				// find a match in the target extends self selector (the bit before :extend)
+				$selectorPath = array( $targetExtend->selfSelectors[0] );
+				$matches = $this->findMatch( $extend, $selectorPath);
+
+
+				if( $matches ){
+
+					// we found a match, so for each self selector..
+					foreach($extend->selfSelectors as $selfSelector ){
+
+
+						// process the extend as usual
+						$newSelector = $this->extendSelector( $matches, $selectorPath, $selfSelector);
+
+						// but now we create a new extend from it
+						$newExtend = new Less_Tree_Extend( $targetExtend->selector, $targetExtend->option, 0);
+						$newExtend->selfSelectors = $newSelector;
+
+						// add the extend onto the list of extends for that selector
+						end($newSelector)->extendList = array($newExtend);
+						//$newSelector[ count($newSelector)-1]->extendList = array($newExtend);
+
+						// record that we need to add it.
+						$extendsToAdd[] = $newExtend;
+						$newExtend->ruleset = $targetExtend->ruleset;
+
+						//remember its parents for circular references
+						$newExtend->parent_ids = array_merge($newExtend->parent_ids,$targetExtend->parent_ids,$extend->parent_ids);
+
+						// only process the selector once.. if we have :extend(.a,.b) then multiple
+						// extends will look at the same selector path, so when extending
+						// we know that any others will be duplicates in terms of what is added to the css
+						if( $targetExtend->firstExtendOnThisSelectorPath ){
+							$newExtend->firstExtendOnThisSelectorPath = true;
+							$targetExtend->ruleset->paths[] = $newSelector;
+						}
+					}
+				}
+			}
+		}
+
+		if( $extendsToAdd ){
+			// try to detect circular references to stop a stack overflow.
+			// may no longer be needed.			$this->extendChainCount++;
+			if( $iterationCount > 100) {
+
+				try{
+					$selectorOne = $extendsToAdd[0]->selfSelectors[0]->toCSS();
+					$selectorTwo = $extendsToAdd[0]->selector->toCSS();
+				}catch(Exception $e){
+					$selectorOne = "{unable to calculate}";
+					$selectorTwo = "{unable to calculate}";
+				}
+
+				throw new Less_Exception_Parser("extend circular reference detected. One of the circular extends is currently:"+$selectorOne+":extend(" + $selectorTwo+")");
+			}
+
+			// now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e...
+			$extendsToAdd = $this->doExtendChaining( $extendsToAdd, $extendsListTarget, $iterationCount+1);
+		}
+
+		return array_merge($extendsList, $extendsToAdd);
+	}
+
+
+	protected function visitRule( $ruleNode, &$visitDeeper ){
+		$visitDeeper = false;
+	}
+
+	protected function visitMixinDefinition( $mixinDefinitionNode, &$visitDeeper ){
+		$visitDeeper = false;
+	}
+
+	protected function visitSelector( $selectorNode, &$visitDeeper ){
+		$visitDeeper = false;
+	}
+
+	protected function visitRuleset($rulesetNode){
+
+
+		if( $rulesetNode->root ){
+			return;
+		}
+
+		$allExtends	= end($this->allExtendsStack);
+		$paths_len = count($rulesetNode->paths);
+
+		// look at each selector path in the ruleset, find any extend matches and then copy, find and replace
+		foreach($allExtends as $allExtend){
+			for($pathIndex = 0; $pathIndex < $paths_len; $pathIndex++ ){
+
+				// extending extends happens initially, before the main pass
+				if( isset($rulesetNode->extendOnEveryPath) && $rulesetNode->extendOnEveryPath ){
+					continue;
+				}
+
+				$selectorPath = $rulesetNode->paths[$pathIndex];
+
+				if( end($selectorPath)->extendList ){
+					continue;
+				}
+
+				$this->ExtendMatch( $rulesetNode, $allExtend, $selectorPath);
+
+			}
+		}
+	}
+
+
+	private function ExtendMatch( $rulesetNode, $extend, $selectorPath ){
+		$matches = $this->findMatch($extend, $selectorPath);
+
+		if( $matches ){
+			foreach($extend->selfSelectors as $selfSelector ){
+				$rulesetNode->paths[] = $this->extendSelector($matches, $selectorPath, $selfSelector);
+			}
+		}
+	}
+
+
+
+	private function findMatch($extend, $haystackSelectorPath ){
+
+
+		if( !$this->HasMatches($extend, $haystackSelectorPath) ){
+			return false;
+		}
+
+
+		//
+		// look through the haystack selector path to try and find the needle - extend.selector
+		// returns an array of selector matches that can then be replaced
+		//
+		$needleElements = $extend->selector->elements;
+		$potentialMatches = array();
+		$potentialMatches_len = 0;
+		$potentialMatch = null;
+		$matches = array();
+
+
+
+		// loop through the haystack elements
+		$haystack_path_len = count($haystackSelectorPath);
+		for($haystackSelectorIndex = 0; $haystackSelectorIndex < $haystack_path_len; $haystackSelectorIndex++ ){
+			$hackstackSelector = $haystackSelectorPath[$haystackSelectorIndex];
+
+			$haystack_elements_len = count($hackstackSelector->elements);
+			for($hackstackElementIndex = 0; $hackstackElementIndex < $haystack_elements_len; $hackstackElementIndex++ ){
+
+				$haystackElement = $hackstackSelector->elements[$hackstackElementIndex];
+
+				// if we allow elements before our match we can add a potential match every time. otherwise only at the first element.
+				if( $extend->allowBefore || ($haystackSelectorIndex === 0 && $hackstackElementIndex === 0) ){
+					$potentialMatches[] = array('pathIndex'=> $haystackSelectorIndex, 'index'=> $hackstackElementIndex, 'matched'=> 0, 'initialCombinator'=> $haystackElement->combinator);
+					$potentialMatches_len++;
+				}
+
+				for($i = 0; $i < $potentialMatches_len; $i++ ){
+
+					$potentialMatch = &$potentialMatches[$i];
+					$potentialMatch = $this->PotentialMatch( $potentialMatch, $needleElements, $haystackElement, $hackstackElementIndex );
+
+
+					// if we are still valid and have finished, test whether we have elements after and whether these are allowed
+					if( $potentialMatch && $potentialMatch['matched'] === $extend->selector->elements_len ){
+						$potentialMatch['finished'] = true;
+
+						if( !$extend->allowAfter && ($hackstackElementIndex+1 < $haystack_elements_len || $haystackSelectorIndex+1 < $haystack_path_len) ){
+							$potentialMatch = null;
+						}
+					}
+
+					// if null we remove, if not, we are still valid, so either push as a valid match or continue
+					if( $potentialMatch ){
+						if( $potentialMatch['finished'] ){
+							$potentialMatch['length'] = $extend->selector->elements_len;
+							$potentialMatch['endPathIndex'] = $haystackSelectorIndex;
+							$potentialMatch['endPathElementIndex'] = $hackstackElementIndex + 1; // index after end of match
+							$potentialMatches = array(); // we don't allow matches to overlap, so start matching again
+							$potentialMatches_len = 0;
+							$matches[] = $potentialMatch;
+						}
+						continue;
+					}
+
+					array_splice($potentialMatches, $i, 1);
+					$potentialMatches_len--;
+					$i--;
+				}
+			}
+		}
+
+		return $matches;
+	}
+
+
+	// Before going through all the nested loops, lets check to see if a match is possible
+	// Reduces Bootstrap 3.1 compile time from ~6.5s to ~5.6s
+	private function HasMatches($extend, $haystackSelectorPath){
+
+		if( !$extend->selector->cacheable ){
+			return true;
+		}
+
+		$first_el = $extend->selector->_oelements[0];
+
+		foreach($haystackSelectorPath as $hackstackSelector){
+			if( !$hackstackSelector->cacheable ){
+				return true;
+			}
+
+			if( in_array($first_el, $hackstackSelector->_oelements) ){
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+
+	/**
+	 * @param integer $hackstackElementIndex
+	 */
+	private function PotentialMatch( $potentialMatch, $needleElements, $haystackElement, $hackstackElementIndex ){
+
+
+		if( $potentialMatch['matched'] > 0 ){
+
+			// selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't
+			// then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out
+			// what the resulting combinator will be
+			$targetCombinator = $haystackElement->combinator;
+			if( $targetCombinator === '' && $hackstackElementIndex === 0 ){
+				$targetCombinator = ' ';
+			}
+
+			if( $needleElements[ $potentialMatch['matched'] ]->combinator !== $targetCombinator ){
+				return null;
+			}
+		}
+
+		// if we don't match, null our match to indicate failure
+		if( !$this->isElementValuesEqual( $needleElements[$potentialMatch['matched'] ]->value, $haystackElement->value) ){
+			return null;
+		}
+
+		$potentialMatch['finished'] = false;
+		$potentialMatch['matched']++;
+
+		return $potentialMatch;
+	}
+
+
+	private function isElementValuesEqual( $elementValue1, $elementValue2 ){
+
+		if( $elementValue1 === $elementValue2 ){
+			return true;
+		}
+
+		if( is_string($elementValue1) || is_string($elementValue2) ) {
+			return false;
+		}
+
+		if( $elementValue1 instanceof Less_Tree_Attribute ){
+			return $this->isAttributeValuesEqual( $elementValue1, $elementValue2 );
+		}
+
+		$elementValue1 = $elementValue1->value;
+		if( $elementValue1 instanceof Less_Tree_Selector ){
+			return $this->isSelectorValuesEqual( $elementValue1, $elementValue2 );
+		}
+
+		return false;
+	}
+
+
+	/**
+	 * @param Less_Tree_Selector $elementValue1
+	 */
+	private function isSelectorValuesEqual( $elementValue1, $elementValue2 ){
+
+		$elementValue2 = $elementValue2->value;
+		if( !($elementValue2 instanceof Less_Tree_Selector) || $elementValue1->elements_len !== $elementValue2->elements_len ){
+			return false;
+		}
+
+		for( $i = 0; $i < $elementValue1->elements_len; $i++ ){
+
+			if( $elementValue1->elements[$i]->combinator !== $elementValue2->elements[$i]->combinator ){
+				if( $i !== 0 || ($elementValue1->elements[$i]->combinator || ' ') !== ($elementValue2->elements[$i]->combinator || ' ') ){
+					return false;
+				}
+			}
+
+			if( !$this->isElementValuesEqual($elementValue1->elements[$i]->value, $elementValue2->elements[$i]->value) ){
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+
+	/**
+	 * @param Less_Tree_Attribute $elementValue1
+	 */
+	private function isAttributeValuesEqual( $elementValue1, $elementValue2 ){
+
+		if( $elementValue1->op !== $elementValue2->op || $elementValue1->key !== $elementValue2->key ){
+			return false;
+		}
+
+		if( !$elementValue1->value || !$elementValue2->value ){
+			if( $elementValue1->value || $elementValue2->value ) {
+				return false;
+			}
+			return true;
+		}
+
+		$elementValue1 = ($elementValue1->value->value ? $elementValue1->value->value : $elementValue1->value );
+		$elementValue2 = ($elementValue2->value->value ? $elementValue2->value->value : $elementValue2->value );
+
+		return $elementValue1 === $elementValue2;
+	}
+
+
+	private function extendSelector($matches, $selectorPath, $replacementSelector){
+
+		//for a set of matches, replace each match with the replacement selector
+
+		$currentSelectorPathIndex = 0;
+		$currentSelectorPathElementIndex = 0;
+		$path = array();
+		$selectorPath_len = count($selectorPath);
+
+		for($matchIndex = 0, $matches_len = count($matches); $matchIndex < $matches_len; $matchIndex++ ){
+
+
+			$match = $matches[$matchIndex];
+			$selector = $selectorPath[ $match['pathIndex'] ];
+
+			$firstElement = new Less_Tree_Element(
+				$match['initialCombinator'],
+				$replacementSelector->elements[0]->value,
+				$replacementSelector->elements[0]->index,
+				$replacementSelector->elements[0]->currentFileInfo
+			);
+
+			if( $match['pathIndex'] > $currentSelectorPathIndex && $currentSelectorPathElementIndex > 0 ){
+				$last_path = end($path);
+				$last_path->elements = array_merge( $last_path->elements, array_slice( $selectorPath[$currentSelectorPathIndex]->elements, $currentSelectorPathElementIndex));
+				$currentSelectorPathElementIndex = 0;
+				$currentSelectorPathIndex++;
+			}
+
+			$newElements = array_merge(
+				array_slice($selector->elements, $currentSelectorPathElementIndex, ($match['index'] - $currentSelectorPathElementIndex) ) // last parameter of array_slice is different than the last parameter of javascript's slice
+				, array($firstElement)
+				, array_slice($replacementSelector->elements,1)
+				);
+
+			if( $currentSelectorPathIndex === $match['pathIndex'] && $matchIndex > 0 ){
+				$last_key = count($path)-1;
+				$path[$last_key]->elements = array_merge($path[$last_key]->elements,$newElements);
+			}else{
+				$path = array_merge( $path, array_slice( $selectorPath, $currentSelectorPathIndex, $match['pathIndex'] ));
+				$path[] = new Less_Tree_Selector( $newElements );
+			}
+
+			$currentSelectorPathIndex = $match['endPathIndex'];
+			$currentSelectorPathElementIndex = $match['endPathElementIndex'];
+			if( $currentSelectorPathElementIndex >= count($selectorPath[$currentSelectorPathIndex]->elements) ){
+				$currentSelectorPathElementIndex = 0;
+				$currentSelectorPathIndex++;
+			}
+		}
+
+		if( $currentSelectorPathIndex < $selectorPath_len && $currentSelectorPathElementIndex > 0 ){
+			$last_path = end($path);
+			$last_path->elements = array_merge( $last_path->elements, array_slice($selectorPath[$currentSelectorPathIndex]->elements, $currentSelectorPathElementIndex));
+			$currentSelectorPathIndex++;
+		}
+
+		$slice_len = $selectorPath_len - $currentSelectorPathIndex;
+		$path = array_merge($path, array_slice($selectorPath, $currentSelectorPathIndex, $slice_len));
+
+		return $path;
+	}
+
+
+	protected function visitMedia( $mediaNode ){
+		$newAllExtends = array_merge( $mediaNode->allExtends, end($this->allExtendsStack) );
+		$this->allExtendsStack[] = $this->doExtendChaining($newAllExtends, $mediaNode->allExtends);
+	}
+
+	protected function visitMediaOut(){
+		array_pop( $this->allExtendsStack );
+	}
+
+	protected function visitDirective( $directiveNode ){
+		$newAllExtends = array_merge( $directiveNode->allExtends, end($this->allExtendsStack) );
+		$this->allExtendsStack[] = $this->doExtendChaining($newAllExtends, $directiveNode->allExtends);
+	}
+
+	protected function visitDirectiveOut(){
+		array_pop($this->allExtendsStack);
+	}
+
+} 
+
+/**
+ * toCSS Visitor
+ *
+ * @package Less
+ * @subpackage visitor
+ */
+class Less_Visitor_toCSS extends Less_VisitorReplacing{
+
+	private $charset;
+
+	public function __construct(){
+		parent::__construct();
+	}
+
+	/**
+	 * @param Less_Tree_Ruleset $root
+	 */
+	public function run( $root ){
+		return $this->visitObj($root);
+	}
+
+	public function visitRule( $ruleNode ){
+		if( $ruleNode->variable ){
+			return array();
+		}
+		return $ruleNode;
+	}
+
+	public function visitMixinDefinition($mixinNode){
+		// mixin definitions do not get eval'd - this means they keep state
+		// so we have to clear that state here so it isn't used if toCSS is called twice
+		$mixinNode->frames = array();
+		return array();
+	}
+
+	public function visitExtend(){
+		return array();
+	}
+
+	public function visitComment( $commentNode ){
+		if( $commentNode->isSilent() ){
+			return array();
+		}
+		return $commentNode;
+	}
+
+	public function visitMedia( $mediaNode, &$visitDeeper ){
+		$mediaNode->accept($this);
+		$visitDeeper = false;
+
+		if( !$mediaNode->rules ){
+			return array();
+		}
+		return $mediaNode;
+	}
+
+	public function visitDirective( $directiveNode ){
+		if( isset($directiveNode->currentFileInfo['reference']) && (!property_exists($directiveNode,'isReferenced') || !$directiveNode->isReferenced) ){
+			return array();
+		}
+		if( $directiveNode->name === '@charset' ){
+			// Only output the debug info together with subsequent @charset definitions
+			// a comment (or @media statement) before the actual @charset directive would
+			// be considered illegal css as it has to be on the first line
+			if( isset($this->charset) && $this->charset ){
+
+				//if( $directiveNode->debugInfo ){
+				//	$comment = new Less_Tree_Comment('/* ' . str_replace("\n",'',$directiveNode->toCSS())." */\n");
+				//	$comment->debugInfo = $directiveNode->debugInfo;
+				//	return $this->visit($comment);
+				//}
+
+
+				return array();
+			}
+			$this->charset = true;
+		}
+		return $directiveNode;
+	}
+
+	public function checkPropertiesInRoot( $rulesetNode ){
+
+		if( !$rulesetNode->firstRoot ){
+			return;
+		}
+
+		foreach($rulesetNode->rules as $ruleNode){
+			if( $ruleNode instanceof Less_Tree_Rule && !$ruleNode->variable ){
+				$msg = "properties must be inside selector blocks, they cannot be in the root. Index ".$ruleNode->index.($ruleNode->currentFileInfo ? (' Filename: '.$ruleNode->currentFileInfo['filename']) : null);
+				throw new Less_Exception_Compiler($msg);
+			}
+		}
+	}
+
+
+	public function visitRuleset( $rulesetNode, &$visitDeeper ){
+
+		$visitDeeper = false;
+
+		$this->checkPropertiesInRoot( $rulesetNode );
+
+		if( $rulesetNode->root ){
+			return $this->visitRulesetRoot( $rulesetNode );
+		}
+
+		$rulesets = array();
+		$rulesetNode->paths = $this->visitRulesetPaths($rulesetNode);
+
+
+		// Compile rules and rulesets
+		$nodeRuleCnt = count($rulesetNode->rules);
+		for( $i = 0; $i < $nodeRuleCnt; ){
+			$rule = $rulesetNode->rules[$i];
+
+			if( property_exists($rule,'rules') ){
+				// visit because we are moving them out from being a child
+				$rulesets[] = $this->visitObj($rule);
+				array_splice($rulesetNode->rules,$i,1);
+				$nodeRuleCnt--;
+				continue;
+			}
+			$i++;
+		}
+
+
+		// accept the visitor to remove rules and refactor itself
+		// then we can decide now whether we want it or not
+		if( $nodeRuleCnt > 0 ){
+			$rulesetNode->accept($this);
+
+			if( $rulesetNode->rules ){
+
+				if( count($rulesetNode->rules) >  1 ){
+					$this->_mergeRules( $rulesetNode->rules );
+					$this->_removeDuplicateRules( $rulesetNode->rules );
+				}
+
+				// now decide whether we keep the ruleset
+				if( $rulesetNode->paths ){
+					//array_unshift($rulesets, $rulesetNode);
+					array_splice($rulesets,0,0,array($rulesetNode));
+				}
+			}
+
+		}
+
+
+		if( count($rulesets) === 1 ){
+			return $rulesets[0];
+		}
+		return $rulesets;
+	}
+
+
+	/**
+	 * Helper function for visitiRuleset
+	 *
+	 * return array|Less_Tree_Ruleset
+	 */
+	private function visitRulesetRoot( $rulesetNode ){
+		$rulesetNode->accept( $this );
+		if( $rulesetNode->firstRoot || $rulesetNode->rules ){
+			return $rulesetNode;
+		}
+		return array();
+	}
+
+
+	/**
+	 * Helper function for visitRuleset()
+	 *
+	 * @return array
+	 */
+	private function visitRulesetPaths($rulesetNode){
+
+		$paths = array();
+		foreach($rulesetNode->paths as $p){
+			if( $p[0]->elements[0]->combinator === ' ' ){
+				$p[0]->elements[0]->combinator = '';
+			}
+
+			foreach($p as $pi){
+				if( $pi->getIsReferenced() && $pi->getIsOutput() ){
+					$paths[] = $p;
+					break;
+				}
+			}
+		}
+
+		return $paths;
+	}
+
+	protected function _removeDuplicateRules( &$rules ){
+		// remove duplicates
+		$ruleCache = array();
+		for( $i = count($rules)-1; $i >= 0 ; $i-- ){
+			$rule = $rules[$i];
+			if( $rule instanceof Less_Tree_Rule || $rule instanceof Less_Tree_NameValue ){
+
+				if( !isset($ruleCache[$rule->name]) ){
+					$ruleCache[$rule->name] = $rule;
+				}else{
+					$ruleList =& $ruleCache[$rule->name];
+
+					if( $ruleList instanceof Less_Tree_Rule || $ruleList instanceof Less_Tree_NameValue ){
+						$ruleList = $ruleCache[$rule->name] = array( $ruleCache[$rule->name]->toCSS() );
+					}
+
+					$ruleCSS = $rule->toCSS();
+					if( array_search($ruleCSS,$ruleList) !== false ){
+						array_splice($rules,$i,1);
+					}else{
+						$ruleList[] = $ruleCSS;
+					}
+				}
+			}
+		}
+	}
+
+	protected function _mergeRules( &$rules ){
+		$groups = array();
+
+		//obj($rules);
+
+		$rules_len = count($rules);
+		for( $i = 0; $i < $rules_len; $i++ ){
+			$rule = $rules[$i];
+
+			if( ($rule instanceof Less_Tree_Rule) && $rule->merge ){
+
+				$key = $rule->name;
+				if( $rule->important ){
+					$key .= ',!';
+				}
+
+				if( !isset($groups[$key]) ){
+					$groups[$key] = array();
+				}else{
+					array_splice($rules, $i--, 1);
+					$rules_len--;
+				}
+
+				$groups[$key][] = $rule;
+			}
+		}
+
+
+		foreach($groups as $parts){
+
+			if( count($parts) > 1 ){
+				$rule = $parts[0];
+				$spacedGroups = array();
+				$lastSpacedGroup = array();
+				$parts_mapped = array();
+				foreach($parts as $p){
+					if( $p->merge === '+' ){
+						if( $lastSpacedGroup ){
+							$spacedGroups[] = self::toExpression($lastSpacedGroup);
+						}
+						$lastSpacedGroup = array();
+					}
+					$lastSpacedGroup[] = $p;
+				}
+
+				$spacedGroups[] = self::toExpression($lastSpacedGroup);
+				$rule->value = self::toValue($spacedGroups);
+			}
+		}
+
+	}
+
+	public static function toExpression($values){
+		$mapped = array();
+		foreach($values as $p){
+			$mapped[] = $p->value;
+		}
+		return new Less_Tree_Expression( $mapped );
+	}
+
+	public static function toValue($values){
+		//return new Less_Tree_Value($values); ??
+
+		$mapped = array();
+		foreach($values as $p){
+			$mapped[] = $p;
+		}
+		return new Less_Tree_Value($mapped);
+	}
+}
+
+ 
+
+/**
+ * Parser Exception
+ *
+ * @package Less
+ * @subpackage exception
+ */
+class Less_Exception_Parser extends Exception{
+
+	/**
+	 * The current file
+	 *
+	 * @var Less_ImportedFile
+	 */
+	public $currentFile;
+
+	/**
+	 * The current parser index
+	 *
+	 * @var integer
+	 */
+	public $index;
+
+	protected $input;
+
+	protected $details = array();
+
+
+	/**
+	 * Constructor
+	 *
+	 * @param string $message
+	 * @param Exception $previous Previous exception
+	 * @param integer $index The current parser index
+	 * @param Less_FileInfo|string $currentFile The file
+	 * @param integer $code The exception code
+	 */
+	public function __construct($message = null, Exception $previous = null, $index = null, $currentFile = null, $code = 0){
+
+		if (PHP_VERSION_ID < 50300) {
+			$this->previous = $previous;
+			parent::__construct($message, $code);
+		} else {
+			parent::__construct($message, $code, $previous);
+		}
+
+		$this->currentFile = $currentFile;
+		$this->index = $index;
+
+		$this->genMessage();
+	}
+
+
+	protected function getInput(){
+
+		if( !$this->input && $this->currentFile && $this->currentFile['filename'] && file_exists($this->currentFile['filename']) ){
+			$this->input = file_get_contents( $this->currentFile['filename'] );
+		}
+	}
+
+
+
+	/**
+	 * Converts the exception to string
+	 *
+	 * @return string
+	 */
+	public function genMessage(){
+
+		if( $this->currentFile && $this->currentFile['filename'] ){
+			$this->message .= ' in '.basename($this->currentFile['filename']);
+		}
+
+		if( $this->index !== null ){
+			$this->getInput();
+			if( $this->input ){
+				$line = self::getLineNumber();
+				$this->message .= ' on line '.$line.', column '.self::getColumn();
+
+				$lines = explode("\n",$this->input);
+
+				$count = count($lines);
+				$start_line = max(0, $line-3);
+				$last_line = min($count, $start_line+6);
+				$num_len = strlen($last_line);
+				for( $i = $start_line; $i < $last_line; $i++ ){
+					$this->message .= "\n".str_pad($i+1,$num_len,'0',STR_PAD_LEFT).'| '.$lines[$i];
+				}
+			}
+		}
+
+	}
+
+	/**
+	 * Returns the line number the error was encountered
+	 *
+	 * @return integer
+	 */
+	public function getLineNumber(){
+		if( $this->index ){
+			// https://bugs.php.net/bug.php?id=49790
+			if (ini_get("mbstring.func_overload")) {
+				return substr_count(substr($this->input, 0, $this->index), "\n") + 1;
+			} else {
+				return substr_count($this->input, "\n", 0, $this->index) + 1;
+			}
+		}
+		return 1;
+	}
+
+
+	/**
+	 * Returns the column the error was encountered
+	 *
+	 * @return integer
+	 */
+	public function getColumn(){
+
+		$part = substr($this->input, 0, $this->index);
+		$pos = strrpos($part,"\n");
+		return $this->index - $pos;
+	}
+
+}
+ 
+
+/**
+ * Chunk Exception
+ *
+ * @package Less
+ * @subpackage exception
+ */
+class Less_Exception_Chunk extends Less_Exception_Parser{
+
+
+	protected $parserCurrentIndex = 0;
+
+	protected $emitFrom = 0;
+
+	protected $input_len;
+
+
+	/**
+	 * Constructor
+	 *
+	 * @param string $input
+	 * @param Exception $previous Previous exception
+	 * @param integer $index The current parser index
+	 * @param Less_FileInfo|string $currentFile The file
+	 * @param integer $code The exception code
+	 */
+	public function __construct($input, Exception $previous = null, $index = null, $currentFile = null, $code = 0){
+
+		$this->message = 'ParseError: Unexpected input'; //default message
+
+		$this->index = $index;
+
+		$this->currentFile = $currentFile;
+
+		$this->input = $input;
+		$this->input_len = strlen($input);
+
+		$this->Chunks();
+		$this->genMessage();
+	}
+
+
+	/**
+	 * See less.js chunks()
+	 * We don't actually need the chunks
+	 *
+	 */
+	protected function Chunks(){
+		$level = 0;
+		$parenLevel = 0;
+		$lastMultiCommentEndBrace = null;
+		$lastOpening = null;
+		$lastMultiComment = null;
+		$lastParen = null;
+
+		for( $this->parserCurrentIndex = 0; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++ ){
+			$cc = $this->CharCode($this->parserCurrentIndex);
+			if ((($cc >= 97) && ($cc <= 122)) || ($cc < 34)) {
+				// a-z or whitespace
+				continue;
+			}
+
+			switch ($cc) {
+
+				// (
+				case 40:
+					$parenLevel++;
+					$lastParen = $this->parserCurrentIndex;
+					continue;
+
+				// )
+				case 41:
+					$parenLevel--;
+					if( $parenLevel < 0 ){
+						return $this->fail("missing opening `(`");
+					}
+					continue;
+
+				// ;
+				case 59:
+					//if (!$parenLevel) { $this->emitChunk();	}
+					continue;
+
+				// {
+				case 123:
+					$level++;
+					$lastOpening = $this->parserCurrentIndex;
+					continue;
+
+				// }
+				case 125:
+					$level--;
+					if( $level < 0 ){
+						return $this->fail("missing opening `{`");
+
+					}
+					//if (!$level && !$parenLevel) { $this->emitChunk(); }
+					continue;
+				// \
+				case 92:
+					if ($this->parserCurrentIndex < $this->input_len - 1) { $this->parserCurrentIndex++; continue; }
+					return $this->fail("unescaped `\\`");
+
+				// ", ' and `
+				case 34:
+				case 39:
+				case 96:
+					$matched = 0;
+					$currentChunkStartIndex = $this->parserCurrentIndex;
+					for ($this->parserCurrentIndex = $this->parserCurrentIndex + 1; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++) {
+						$cc2 = $this->CharCode($this->parserCurrentIndex);
+						if ($cc2 > 96) { continue; }
+						if ($cc2 == $cc) { $matched = 1; break; }
+						if ($cc2 == 92) {        // \
+							if ($this->parserCurrentIndex == $this->input_len - 1) {
+								return $this->fail("unescaped `\\`");
+							}
+							$this->parserCurrentIndex++;
+						}
+					}
+					if ($matched) { continue; }
+					return $this->fail("unmatched `" + chr($cc) + "`", $currentChunkStartIndex);
+
+				// /, check for comment
+				case 47:
+					if ($parenLevel || ($this->parserCurrentIndex == $this->input_len - 1)) { continue; }
+					$cc2 = $this->CharCode($this->parserCurrentIndex+1);
+					if ($cc2 == 47) {
+						// //, find lnfeed
+						for ($this->parserCurrentIndex = $this->parserCurrentIndex + 2; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++) {
+							$cc2 = $this->CharCode($this->parserCurrentIndex);
+							if (($cc2 <= 13) && (($cc2 == 10) || ($cc2 == 13))) { break; }
+						}
+					} else if ($cc2 == 42) {
+						// /*, find */
+						$lastMultiComment = $currentChunkStartIndex = $this->parserCurrentIndex;
+						for ($this->parserCurrentIndex = $this->parserCurrentIndex + 2; $this->parserCurrentIndex < $this->input_len - 1; $this->parserCurrentIndex++) {
+							$cc2 = $this->CharCode($this->parserCurrentIndex);
+							if ($cc2 == 125) { $lastMultiCommentEndBrace = $this->parserCurrentIndex; }
+							if ($cc2 != 42) { continue; }
+							if ($this->CharCode($this->parserCurrentIndex+1) == 47) { break; }
+						}
+						if ($this->parserCurrentIndex == $this->input_len - 1) {
+							return $this->fail("missing closing `*/`", $currentChunkStartIndex);
+						}
+					}
+					continue;
+
+				// *, check for unmatched */
+				case 42:
+					if (($this->parserCurrentIndex < $this->input_len - 1) && ($this->CharCode($this->parserCurrentIndex+1) == 47)) {
+						return $this->fail("unmatched `/*`");
+					}
+					continue;
+			}
+		}
+
+		if( $level !== 0 ){
+			if( ($lastMultiComment > $lastOpening) && ($lastMultiCommentEndBrace > $lastMultiComment) ){
+				return $this->fail("missing closing `}` or `*/`", $lastOpening);
+			} else {
+				return $this->fail("missing closing `}`", $lastOpening);
+			}
+		} else if ( $parenLevel !== 0 ){
+			return $this->fail("missing closing `)`", $lastParen);
+		}
+
+
+		//chunk didn't fail
+
+
+		//$this->emitChunk(true);
+	}
+
+	public function CharCode($pos){
+		return ord($this->input[$pos]);
+	}
+
+
+	public function fail( $msg, $index = null ){
+
+		if( !$index ){
+			$this->index = $this->parserCurrentIndex;
+		}else{
+			$this->index = $index;
+		}
+		$this->message = 'ParseError: '.$msg;
+	}
+
+
+	/*
+	function emitChunk( $force = false ){
+		$len = $this->parserCurrentIndex - $this->emitFrom;
+		if ((($len < 512) && !$force) || !$len) {
+			return;
+		}
+		$chunks[] = substr($this->input, $this->emitFrom, $this->parserCurrentIndex + 1 - $this->emitFrom );
+		$this->emitFrom = $this->parserCurrentIndex + 1;
+	}
+	*/
+
+}
+ 
+
+/**
+ * Compiler Exception
+ *
+ * @package Less
+ * @subpackage exception
+ */
+class Less_Exception_Compiler extends Less_Exception_Parser{
+
+} 
+
+/**
+ * Parser output with source map
+ *
+ * @package Less
+ * @subpackage Output
+ */
+class Less_Output_Mapped extends Less_Output {
+
+	/**
+	 * The source map generator
+	 *
+	 * @var Less_SourceMap_Generator
+	 */
+	protected $generator;
+
+	/**
+	 * Current line
+	 *
+	 * @var integer
+	 */
+	protected $lineNumber = 0;
+
+	/**
+	 * Current column
+	 *
+	 * @var integer
+	 */
+	protected $column = 0;
+
+	/**
+	 * Array of contents map (file and its content)
+	 *
+	 * @var array
+	 */
+	protected $contentsMap = array();
+
+	/**
+	 * Constructor
+	 *
+	 * @param array $contentsMap Array of filename to contents map
+	 * @param Less_SourceMap_Generator $generator
+	 */
+	public function __construct(array $contentsMap, $generator){
+		$this->contentsMap = $contentsMap;
+		$this->generator = $generator;
+	}
+
+	/**
+	 * Adds a chunk to the stack
+	 * The $index for less.php may be different from less.js since less.php does not chunkify inputs
+	 *
+	 * @param string $chunk
+	 * @param string $fileInfo
+	 * @param integer $index
+	 * @param mixed $mapLines
+	 */
+	public function add($chunk, $fileInfo = null, $index = 0, $mapLines = null){
+
+		//ignore adding empty strings
+		if( $chunk === '' ){
+			return;
+		}
+
+
+		$sourceLines = array();
+		$sourceColumns = ' ';
+
+
+		if( $fileInfo ){
+
+			$url = $fileInfo['currentUri'];
+
+			if( isset($this->contentsMap[$url]) ){
+				$inputSource = substr($this->contentsMap[$url], 0, $index);
+				$sourceLines = explode("\n", $inputSource);
+				$sourceColumns = end($sourceLines);
+			}else{
+				throw new Exception('Filename '.$url.' not in contentsMap');
+			}
+
+		}
+
+		$lines = explode("\n", $chunk);
+		$columns = end($lines);
+
+		if($fileInfo){
+
+			if(!$mapLines){
+				$this->generator->addMapping(
+						$this->lineNumber + 1,					// generated_line
+						$this->column,							// generated_column
+						count($sourceLines),					// original_line
+						strlen($sourceColumns),					// original_column
+						$fileInfo
+				);
+			}else{
+				for($i = 0, $count = count($lines); $i < $count; $i++){
+					$this->generator->addMapping(
+						$this->lineNumber + $i + 1,				// generated_line
+						$i === 0 ? $this->column : 0,			// generated_column
+						count($sourceLines) + $i,				// original_line
+						$i === 0 ? strlen($sourceColumns) : 0, 	// original_column
+						$fileInfo
+					);
+				}
+			}
+		}
+
+		if(count($lines) === 1){
+			$this->column += strlen($columns);
+		}else{
+			$this->lineNumber += count($lines) - 1;
+			$this->column = strlen($columns);
+		}
+
+		// add only chunk
+		parent::add($chunk);
+	}
+
+} 
+
+/**
+ * Encode / Decode Base64 VLQ.
+ *
+ * @package Less
+ * @subpackage SourceMap
+ */
+class Less_SourceMap_Base64VLQ {
+
+	/**
+	 * Shift
+	 *
+	 * @var integer
+	 */
+	private $shift = 5;
+
+	/**
+	 * Mask
+	 *
+	 * @var integer
+	 */
+	private $mask = 0x1F; // == (1 << shift) == 0b00011111
+
+	/**
+	 * Continuation bit
+	 *
+	 * @var integer
+	 */
+	private $continuationBit = 0x20; // == (mask - 1 ) == 0b00100000
+
+	/**
+	 * Char to integer map
+	 *
+	 * @var array
+	 */
+	private $charToIntMap = array(
+		'A' => 0, 'B' => 1, 'C' => 2, 'D' => 3, 'E' => 4, 'F' => 5, 'G' => 6,
+		'H' => 7,'I' => 8, 'J' => 9, 'K' => 10, 'L' => 11, 'M' => 12, 'N' => 13,
+		'O' => 14, 'P' => 15, 'Q' => 16, 'R' => 17, 'S' => 18, 'T' => 19, 'U' => 20,
+		'V' => 21, 'W' => 22, 'X' => 23, 'Y' => 24, 'Z' => 25, 'a' => 26, 'b' => 27,
+		'c' => 28, 'd' => 29, 'e' => 30, 'f' => 31, 'g' => 32, 'h' => 33, 'i' => 34,
+		'j' => 35, 'k' => 36, 'l' => 37, 'm' => 38, 'n' => 39, 'o' => 40, 'p' => 41,
+		'q' => 42, 'r' => 43, 's' => 44, 't' => 45, 'u' => 46, 'v' => 47, 'w' => 48,
+		'x' => 49, 'y' => 50, 'z' => 51, 0 => 52, 1 => 53, 2 => 54, 3 => 55, 4 => 56,
+		5 => 57,	6 => 58, 7 => 59, 8 => 60, 9 => 61, '+' => 62, '/' => 63,
+	);
+
+	/**
+	 * Integer to char map
+	 *
+	 * @var array
+	 */
+	private $intToCharMap = array(
+		0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D', 4 => 'E', 5 => 'F', 6 => 'G',
+		7 => 'H', 8 => 'I', 9 => 'J', 10 => 'K', 11 => 'L', 12 => 'M', 13 => 'N',
+		14 => 'O', 15 => 'P', 16 => 'Q', 17 => 'R', 18 => 'S', 19 => 'T', 20 => 'U',
+		21 => 'V', 22 => 'W', 23 => 'X', 24 => 'Y', 25 => 'Z', 26 => 'a', 27 => 'b',
+		28 => 'c', 29 => 'd', 30 => 'e', 31 => 'f', 32 => 'g', 33 => 'h', 34 => 'i',
+		35 => 'j', 36 => 'k', 37 => 'l', 38 => 'm', 39 => 'n', 40 => 'o', 41 => 'p',
+		42 => 'q', 43 => 'r', 44 => 's', 45 => 't', 46 => 'u', 47 => 'v', 48 => 'w',
+		49 => 'x', 50 => 'y', 51 => 'z', 52 => '0', 53 => '1', 54 => '2', 55 => '3',
+		56 => '4', 57 => '5', 58 => '6', 59 => '7', 60 => '8', 61 => '9', 62 => '+',
+		63 => '/',
+	);
+
+	/**
+	 * Constructor
+	 */
+	public function __construct(){
+		// I leave it here for future reference
+		// foreach(str_split('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/') as $i => $char)
+		// {
+		//	 $this->charToIntMap[$char] = $i;
+		//	 $this->intToCharMap[$i] = $char;
+		// }
+	}
+
+	/**
+	 * Convert from a two-complement value to a value where the sign bit is
+	 * is placed in the least significant bit.	For example, as decimals:
+	 *	 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
+	 *	 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
+	 * We generate the value for 32 bit machines, hence -2147483648 becomes 1, not 4294967297,
+	 * even on a 64 bit machine.
+	 * @param string $aValue
+	 */
+	public function toVLQSigned($aValue){
+		return 0xffffffff & ($aValue < 0 ? ((-$aValue) << 1) + 1 : ($aValue << 1) + 0);
+	}
+
+	/**
+	 * Convert to a two-complement value from a value where the sign bit is
+	 * is placed in the least significant bit. For example, as decimals:
+	 *	 2 (10 binary) becomes 1, 3 (11 binary) becomes -1
+	 *	 4 (100 binary) becomes 2, 5 (101 binary) becomes -2
+	 * We assume that the value was generated with a 32 bit machine in mind.
+	 * Hence
+	 *	 1 becomes -2147483648
+	 * even on a 64 bit machine.
+	 * @param integer $aValue
+	 */
+	public function fromVLQSigned($aValue){
+		return $aValue & 1 ? $this->zeroFill(~$aValue + 2, 1) | (-1 - 0x7fffffff) : $this->zeroFill($aValue, 1);
+	}
+
+	/**
+	 * Return the base 64 VLQ encoded value.
+	 *
+	 * @param string $aValue The value to encode
+	 * @return string The encoded value
+	 */
+	public function encode($aValue){
+		$encoded = '';
+		$vlq = $this->toVLQSigned($aValue);
+		do
+		{
+			$digit = $vlq & $this->mask;
+			$vlq = $this->zeroFill($vlq, $this->shift);
+			if($vlq > 0){
+				$digit |= $this->continuationBit;
+			}
+			$encoded .= $this->base64Encode($digit);
+		} while($vlq > 0);
+
+		return $encoded;
+	}
+
+	/**
+	 * Return the value decoded from base 64 VLQ.
+	 *
+	 * @param string $encoded The encoded value to decode
+	 * @return integer The decoded value
+	 */
+	public function decode($encoded){
+		$vlq = 0;
+		$i = 0;
+		do
+		{
+			$digit = $this->base64Decode($encoded[$i]);
+			$vlq |= ($digit & $this->mask) << ($i * $this->shift);
+			$i++;
+		} while($digit & $this->continuationBit);
+
+		return $this->fromVLQSigned($vlq);
+	}
+
+	/**
+	 * Right shift with zero fill.
+	 *
+	 * @param integer $a number to shift
+	 * @param integer $b number of bits to shift
+	 * @return integer
+	 */
+	public function zeroFill($a, $b){
+		return ($a >= 0) ? ($a >> $b) : ($a >> $b) & (PHP_INT_MAX >> ($b - 1));
+	}
+
+	/**
+	 * Encode single 6-bit digit as base64.
+	 *
+	 * @param integer $number
+	 * @return string
+	 * @throws Exception If the number is invalid
+	 */
+	public function base64Encode($number){
+		if($number < 0 || $number > 63){
+			throw new Exception(sprintf('Invalid number "%s" given. Must be between 0 and 63.', $number));
+		}
+		return $this->intToCharMap[$number];
+	}
+
+	/**
+	 * Decode single 6-bit digit from base64
+	 *
+	 * @param string $char
+	 * @return number
+	 * @throws Exception If the number is invalid
+	 */
+	public function base64Decode($char){
+		if(!array_key_exists($char, $this->charToIntMap)){
+			throw new Exception(sprintf('Invalid base 64 digit "%s" given.', $char));
+		}
+		return $this->charToIntMap[$char];
+	}
+
+}
+ 
+
+/**
+ * Source map generator
+ *
+ * @package Less
+ * @subpackage Output
+ */
+class Less_SourceMap_Generator extends Less_Configurable {
+
+	/**
+	 * What version of source map does the generator generate?
+	 */
+	const VERSION = 3;
+
+	/**
+	 * Array of default options
+	 *
+	 * @var array
+	 */
+	protected $defaultOptions = array(
+			// an optional source root, useful for relocating source files
+			// on a server or removing repeated values in the 'sources' entry.
+			// This value is prepended to the individual entries in the 'source' field.
+			'sourceRoot'			=> '',
+
+			// an optional name of the generated code that this source map is associated with.
+			'sourceMapFilename'		=> null,
+
+			// url of the map
+			'sourceMapURL'			=> null,
+
+			// absolute path to a file to write the map to
+			'sourceMapWriteTo'		=> null,
+
+			// output source contents?
+			'outputSourceFiles'		=> false,
+
+			// base path for filename normalization
+			'sourceMapRootpath'		=> '',
+
+			// base path for filename normalization
+			'sourceMapBasepath'   => ''
+	);
+
+	/**
+	 * The base64 VLQ encoder
+	 *
+	 * @var Less_SourceMap_Base64VLQ
+	 */
+	protected $encoder;
+
+	/**
+	 * Array of mappings
+	 *
+	 * @var array
+	 */
+	protected $mappings = array();
+
+	/**
+	 * The root node
+	 *
+	 * @var Less_Tree_Ruleset
+	 */
+	protected $root;
+
+	/**
+	 * Array of contents map
+	 *
+	 * @var array
+	 */
+	protected $contentsMap = array();
+
+	/**
+	 * File to content map
+	 *
+	 * @var array
+	 */
+	protected $sources = array();
+	protected $source_keys = array();
+
+	/**
+	 * Constructor
+	 *
+	 * @param Less_Tree_Ruleset $root The root node
+	 * @param array $options Array of options
+	 */
+	public function __construct(Less_Tree_Ruleset $root, $contentsMap, $options = array()){
+		$this->root = $root;
+		$this->contentsMap = $contentsMap;
+		$this->encoder = new Less_SourceMap_Base64VLQ();
+
+		$this->SetOptions($options);
+		
+		$this->options['sourceMapRootpath'] = $this->fixWindowsPath($this->options['sourceMapRootpath'], true);
+		$this->options['sourceMapBasepath'] = $this->fixWindowsPath($this->options['sourceMapBasepath'], true);
+	}
+
+	/**
+	 * Generates the CSS
+	 *
+	 * @return string
+	 */
+	public function generateCSS(){
+		$output = new Less_Output_Mapped($this->contentsMap, $this);
+
+		// catch the output
+		$this->root->genCSS($output);
+
+
+		$sourceMapUrl				= $this->getOption('sourceMapURL');
+		$sourceMapFilename			= $this->getOption('sourceMapFilename');
+		$sourceMapContent			= $this->generateJson();
+		$sourceMapWriteTo			= $this->getOption('sourceMapWriteTo');
+
+		if( !$sourceMapUrl && $sourceMapFilename ){
+			$sourceMapUrl = $this->normalizeFilename($sourceMapFilename);
+		}
+
+		// write map to a file
+		if( $sourceMapWriteTo ){
+			$this->saveMap($sourceMapWriteTo, $sourceMapContent);
+		}
+
+		// inline the map
+		if( !$sourceMapUrl ){
+			$sourceMapUrl = sprintf('data:application/json,%s', Less_Functions::encodeURIComponent($sourceMapContent));
+		}
+
+		if( $sourceMapUrl ){
+			$output->add( sprintf('/*# sourceMappingURL=%s */', $sourceMapUrl) );
+		}
+
+		return $output->toString();
+	}
+
+	/**
+	 * Saves the source map to a file
+	 *
+	 * @param string $file The absolute path to a file
+	 * @param string $content The content to write
+	 * @throws Exception If the file could not be saved
+	 */
+	protected function saveMap($file, $content){
+		$dir = dirname($file);
+		// directory does not exist
+		if( !is_dir($dir) ){
+			// FIXME: create the dir automatically?
+			throw new Exception(sprintf('The directory "%s" does not exist. Cannot save the source map.', $dir));
+		}
+		// FIXME: proper saving, with dir write check!
+		if(file_put_contents($file, $content) === false){
+			throw new Exception(sprintf('Cannot save the source map to "%s"', $file));
+		}
+		return true;
+	}
+
+	/**
+	 * Normalizes the filename
+	 *
+	 * @param string $filename
+	 * @return string
+	 */
+	protected function normalizeFilename($filename){
+
+		$filename = $this->fixWindowsPath($filename);
+
+		$rootpath = $this->getOption('sourceMapRootpath');
+		$basePath = $this->getOption('sourceMapBasepath');
+
+		// "Trim" the 'sourceMapBasepath' from the output filename.
+		if (strpos($filename, $basePath) === 0) {
+			$filename = substr($filename, strlen($basePath));
+		}
+
+		// Remove extra leading path separators.
+		if(strpos($filename, '\\') === 0 || strpos($filename, '/') === 0){
+			$filename = substr($filename, 1);
+		}
+
+		return $rootpath . $filename;
+	}
+
+	/**
+	 * Adds a mapping
+	 *
+	 * @param integer $generatedLine The line number in generated file
+	 * @param integer $generatedColumn The column number in generated file
+	 * @param integer $originalLine The line number in original file
+	 * @param integer $originalColumn The column number in original file
+	 * @param string $sourceFile The original source file
+	 */
+	public function addMapping($generatedLine, $generatedColumn, $originalLine, $originalColumn, $fileInfo ){
+
+		$this->mappings[] = array(
+			'generated_line' => $generatedLine,
+			'generated_column' => $generatedColumn,
+			'original_line' => $originalLine,
+			'original_column' => $originalColumn,
+			'source_file' => $fileInfo['currentUri']
+		);
+
+		$this->sources[$fileInfo['currentUri']] = $fileInfo['filename'];
+	}
+
+
+	/**
+	 * Generates the JSON source map
+	 *
+	 * @return string
+	 * @see https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#
+	 */
+	protected function generateJson(){
+
+		$sourceMap = array();
+		$mappings = $this->generateMappings();
+
+		// File version (always the first entry in the object) and must be a positive integer.
+		$sourceMap['version'] = self::VERSION;
+
+
+		// An optional name of the generated code that this source map is associated with.
+		$file = $this->getOption('sourceMapFilename');
+		if( $file ){
+			$sourceMap['file'] = $file;
+		}
+
+
+		// An optional source root, useful for relocating source files on a server or removing repeated values in the 'sources' entry.	This value is prepended to the individual entries in the 'source' field.
+		$root = $this->getOption('sourceRoot');
+		if( $root ){
+			$sourceMap['sourceRoot'] = $root;
+		}
+
+
+		// A list of original sources used by the 'mappings' entry.
+		$sourceMap['sources'] = array();
+		foreach($this->sources as $source_uri => $source_filename){
+			$sourceMap['sources'][] = $this->normalizeFilename($source_filename);
+		}
+
+
+		// A list of symbol names used by the 'mappings' entry.
+		$sourceMap['names'] = array();
+
+		// A string with the encoded mapping data.
+		$sourceMap['mappings'] = $mappings;
+
+		if( $this->getOption('outputSourceFiles') ){
+			// An optional list of source content, useful when the 'source' can't be hosted.
+			// The contents are listed in the same order as the sources above.
+			// 'null' may be used if some original sources should be retrieved by name.
+			$sourceMap['sourcesContent'] = $this->getSourcesContent();
+		}
+
+		// less.js compat fixes
+		if( count($sourceMap['sources']) && empty($sourceMap['sourceRoot']) ){
+			unset($sourceMap['sourceRoot']);
+		}
+
+		return json_encode($sourceMap);
+	}
+
+	/**
+	 * Returns the sources contents
+	 *
+	 * @return array|null
+	 */
+	protected function getSourcesContent(){
+		if(empty($this->sources)){
+			return;
+		}
+		$content = array();
+		foreach($this->sources as $sourceFile){
+			$content[] = file_get_contents($sourceFile);
+		}
+		return $content;
+	}
+
+	/**
+	 * Generates the mappings string
+	 *
+	 * @return string
+	 */
+	public function generateMappings(){
+
+		if( !count($this->mappings) ){
+			return '';
+		}
+
+		$this->source_keys = array_flip(array_keys($this->sources));
+
+
+		// group mappings by generated line number.
+		$groupedMap = $groupedMapEncoded = array();
+		foreach($this->mappings as $m){
+			$groupedMap[$m['generated_line']][] = $m;
+		}
+		ksort($groupedMap);
+
+		$lastGeneratedLine = $lastOriginalIndex = $lastOriginalLine = $lastOriginalColumn = 0;
+
+		foreach($groupedMap as $lineNumber => $line_map){
+			while(++$lastGeneratedLine < $lineNumber){
+				$groupedMapEncoded[] = ';';
+			}
+
+			$lineMapEncoded = array();
+			$lastGeneratedColumn = 0;
+
+			foreach($line_map as $m){
+				$mapEncoded = $this->encoder->encode($m['generated_column'] - $lastGeneratedColumn);
+				$lastGeneratedColumn = $m['generated_column'];
+
+				// find the index
+				if( $m['source_file'] ){
+					$index = $this->findFileIndex($m['source_file']);
+					if( $index !== false ){
+						$mapEncoded .= $this->encoder->encode($index - $lastOriginalIndex);
+						$lastOriginalIndex = $index;
+
+						// lines are stored 0-based in SourceMap spec version 3
+						$mapEncoded .= $this->encoder->encode($m['original_line'] - 1 - $lastOriginalLine);
+						$lastOriginalLine = $m['original_line'] - 1;
+
+						$mapEncoded .= $this->encoder->encode($m['original_column'] - $lastOriginalColumn);
+						$lastOriginalColumn = $m['original_column'];
+					}
+				}
+
+				$lineMapEncoded[] = $mapEncoded;
+			}
+
+			$groupedMapEncoded[] = implode(',', $lineMapEncoded) . ';';
+		}
+
+		return rtrim(implode($groupedMapEncoded), ';');
+	}
+
+	/**
+	 * Finds the index for the filename
+	 *
+	 * @param string $filename
+	 * @return integer|false
+	 */
+	protected function findFileIndex($filename){
+		return $this->source_keys[$filename];
+	}
+
+	/**
+	 * fix windows paths
+	 * @param  string $path
+	 * @return string      
+	 */
+	public function fixWindowsPath($path, $addEndSlash = false){
+		$slash = ($addEndSlash) ? '/' : '';
+		if( !empty($path) ){
+			$path = str_replace('\\', '/', $path);
+			$path = rtrim($path,'/') . $slash;
+		}
+
+		return $path;
+	}
+
+} 
\ No newline at end of file
diff --git a/less/less/Version.php b/less/less/Version.php
new file mode 100644
index 0000000000000000000000000000000000000000..704ec6e07b31838c0d7fd83af9853a9b66e361e4
--- /dev/null
+++ b/less/less/Version.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * Release numbers
+ *
+ * @package Less
+ * @subpackage version
+ */
+class Less_Version{
+
+	const version = '1.7.0.9';			// The current build number of less.php
+	const less_version = '1.7';			// The less.js version that this build should be compatible with
+    const cache_version = '170';		// The parser cache version
+
+}
diff --git a/less/style.php b/less/style.php
new file mode 100644
index 0000000000000000000000000000000000000000..ca41f72f179329e51606aa783699536013ac33ac
--- /dev/null
+++ b/less/style.php
@@ -0,0 +1,78 @@
+<?php
+
+$tmp_dir = "tmp";
+chdir("..");
+
+if (!isset($_GET["name"])) {
+    http_response_code(404);
+    echo "no valid file given";
+    return;
+}
+
+$less_file = $_GET["name"]; //"panels/departure/style.less";
+$debug=isset($_GET["debug"]);
+
+include "config/config.php";
+echo ROOT_DIR;
+
+
+$panel = null;
+
+if ($debug)
+    header("content-type:text/plain;charset=utf8");
+
+
+if (!file_exists($less_file)) {
+    http_response_code(404);
+    echo $less_file . " not found";
+    return;
+}
+
+if (preg_match_all ('/'.'panels\\/((?:[a-z][a-z]+))\\/style\\.less'.'/is', $less_file, $matches))
+{
+    $panel=$matches[1][0];
+}
+
+if ($debug && isset($panel))
+    echo "panel:" . $panel."\n";
+
+$cache_name = "lesscache_".md5($less_file."_".filemtime($less_file)).".css";
+$cache_file = $tmp_dir."/".$cache_name;
+
+if (!file_exists($cache_file)) {
+
+	require("less/Less.php");
+	$options = array( 'compress'=>true );
+	$parser = new Less_Parser($options);
+	$parser->parseFile("css/colors.less");
+
+    try {
+        if (!isset($panel)) {
+            $parser->parseFile($less_file);
+        } else {
+            $parser->parse("
+                    [data-template=$panel] {
+                        @import \"$less_file\";
+                    }", "/panels/$panel");
+        }
+		$content = $parser->getCss();
+	}catch(Exception $e) {
+        http_response_code(500);
+        header("content-type:text/plain;charset=utf8");
+        echo $e->getMessage();
+        return;
+    }
+    file_put_contents($cache_file,$content);;
+}
+
+if ($debug) {
+    echo "cache-name: " . $cache_file . "\n";
+    echo "content:\n";
+    if (!isset($content))
+        echo file_get_contents($cache_file)."\n";
+    else
+        echo $content;
+} else {
+    header("Location: ".ROOT_DIR."/$cache_file");
+}
+
diff --git a/lessc.php b/lessc.php
deleted file mode 100755
index 261e7efdce2f988d4d652e9ad7fcc4da19284c9e..0000000000000000000000000000000000000000
--- a/lessc.php
+++ /dev/null
@@ -1,3766 +0,0 @@
-<?php
-
-/**
- * lessphp v0.5.0
- * http://leafo.net/lessphp
- *
- * LESS CSS compiler, adapted from http://lesscss.org
- *
- * Copyright 2013, Leaf Corcoran <leafot@gmail.com>
- * Licensed under MIT or GPLv3, see LICENSE
- */
-
-
-/**
- * The LESS compiler and parser.
- *
- * Converting LESS to CSS is a three stage process. The incoming file is parsed
- * by `lessc_parser` into a syntax tree, then it is compiled into another tree
- * representing the CSS structure by `lessc`. The CSS tree is fed into a
- * formatter, like `lessc_formatter` which then outputs CSS as a string.
- *
- * During the first compile, all values are *reduced*, which means that their
- * types are brought to the lowest form before being dump as strings. This
- * handles math equations, variable dereferences, and the like.
- *
- * The `parse` function of `lessc` is the entry point.
- *
- * In summary:
- *
- * The `lessc` class creates an instance of the parser, feeds it LESS code,
- * then transforms the resulting tree to a CSS tree. This class also holds the
- * evaluation context, such as all available mixins and variables at any given
- * time.
- *
- * The `lessc_parser` class is only concerned with parsing its input.
- *
- * The `lessc_formatter` takes a CSS tree, and dumps it to a formatted string,
- * handling things like indentation.
- */
-class lessc {
-	static public $VERSION = "v0.5.0";
-
-	static public $TRUE = array("keyword", "true");
-	static public $FALSE = array("keyword", "false");
-
-	protected $libFunctions = array();
-	protected $registeredVars = array();
-	protected $preserveComments = false;
-
-	public $vPrefix = '@'; // prefix of abstract properties
-	public $mPrefix = '$'; // prefix of abstract blocks
-	public $parentSelector = '&';
-
-	public $importDisabled = false;
-	public $importDir = '';
-
-	protected $numberPrecision = null;
-
-	protected $allParsedFiles = array();
-
-	// set to the parser that generated the current line when compiling
-	// so we know how to create error messages
-	protected $sourceParser = null;
-	protected $sourceLoc = null;
-
-	static protected $nextImportId = 0; // uniquely identify imports
-
-	// attempts to find the path of an import url, returns null for css files
-	protected function findImport($url) {
-		foreach ((array)$this->importDir as $dir) {
-			$full = $dir.(substr($dir, -1) != '/' ? '/' : '').$url;
-			if ($this->fileExists($file = $full.'.less') || $this->fileExists($file = $full)) {
-				return $file;
-			}
-		}
-
-		return null;
-	}
-
-	protected function fileExists($name) {
-		return is_file($name);
-	}
-
-	static public function compressList($items, $delim) {
-		if (!isset($items[1]) && isset($items[0])) return $items[0];
-		else return array('list', $delim, $items);
-	}
-
-	static public function preg_quote($what) {
-		return preg_quote($what, '/');
-	}
-
-	protected function tryImport($importPath, $parentBlock, $out) {
-		if ($importPath[0] == "function" && $importPath[1] == "url") {
-			$importPath = $this->flattenList($importPath[2]);
-		}
-
-		$str = $this->coerceString($importPath);
-		if ($str === null) return false;
-
-		$url = $this->compileValue($this->lib_e($str));
-
-		// don't import if it ends in css
-		if (substr_compare($url, '.css', -4, 4) === 0) return false;
-
-		$realPath = $this->findImport($url);
-
-		if ($realPath === null) return false;
-
-		if ($this->importDisabled) {
-			return array(false, "/* import disabled */");
-		}
-
-		if (isset($this->allParsedFiles[realpath($realPath)])) {
-			return array(false, null);
-		}
-
-		$this->addParsedFile($realPath);
-		$parser = $this->makeParser($realPath);
-		$root = $parser->parse(file_get_contents($realPath));
-
-		// set the parents of all the block props
-		foreach ($root->props as $prop) {
-			if ($prop[0] == "block") {
-				$prop[1]->parent = $parentBlock;
-			}
-		}
-
-		// copy mixins into scope, set their parents
-		// bring blocks from import into current block
-		// TODO: need to mark the source parser	these came from this file
-		foreach ($root->children as $childName => $child) {
-			if (isset($parentBlock->children[$childName])) {
-				$parentBlock->children[$childName] = array_merge(
-					$parentBlock->children[$childName],
-					$child);
-			} else {
-				$parentBlock->children[$childName] = $child;
-			}
-		}
-
-		$pi = pathinfo($realPath);
-		$dir = $pi["dirname"];
-
-		list($top, $bottom) = $this->sortProps($root->props, true);
-		$this->compileImportedProps($top, $parentBlock, $out, $parser, $dir);
-
-		return array(true, $bottom, $parser, $dir);
-	}
-
-	protected function compileImportedProps($props, $block, $out, $sourceParser, $importDir) {
-		$oldSourceParser = $this->sourceParser;
-
-		$oldImport = $this->importDir;
-
-		// TODO: this is because the importDir api is stupid
-		$this->importDir = (array)$this->importDir;
-		array_unshift($this->importDir, $importDir);
-
-		foreach ($props as $prop) {
-			$this->compileProp($prop, $block, $out);
-		}
-
-		$this->importDir = $oldImport;
-		$this->sourceParser = $oldSourceParser;
-	}
-
-	/**
-	 * Recursively compiles a block.
-	 *
-	 * A block is analogous to a CSS block in most cases. A single LESS document
-	 * is encapsulated in a block when parsed, but it does not have parent tags
-	 * so all of it's children appear on the root level when compiled.
-	 *
-	 * Blocks are made up of props and children.
-	 *
-	 * Props are property instructions, array tuples which describe an action
-	 * to be taken, eg. write a property, set a variable, mixin a block.
-	 *
-	 * The children of a block are just all the blocks that are defined within.
-	 * This is used to look up mixins when performing a mixin.
-	 *
-	 * Compiling the block involves pushing a fresh environment on the stack,
-	 * and iterating through the props, compiling each one.
-	 *
-	 * See lessc::compileProp()
-	 *
-	 */
-	protected function compileBlock($block) {
-		switch ($block->type) {
-		case "root":
-			$this->compileRoot($block);
-			break;
-		case null:
-			$this->compileCSSBlock($block);
-			break;
-		case "media":
-			$this->compileMedia($block);
-			break;
-		case "directive":
-			$name = "@" . $block->name;
-			if (!empty($block->value)) {
-				$name .= " " . $this->compileValue($this->reduce($block->value));
-			}
-
-			$this->compileNestedBlock($block, array($name));
-			break;
-		default:
-			$this->throwError("unknown block type: $block->type\n");
-		}
-	}
-
-	protected function compileCSSBlock($block) {
-		$env = $this->pushEnv();
-
-		$selectors = $this->compileSelectors($block->tags);
-		$env->selectors = $this->multiplySelectors($selectors);
-		$out = $this->makeOutputBlock(null, $env->selectors);
-
-		$this->scope->children[] = $out;
-		$this->compileProps($block, $out);
-
-		$block->scope = $env; // mixins carry scope with them!
-		$this->popEnv();
-	}
-
-	protected function compileMedia($media) {
-		$env = $this->pushEnv($media);
-		$parentScope = $this->mediaParent($this->scope);
-
-		$query = $this->compileMediaQuery($this->multiplyMedia($env));
-
-		$this->scope = $this->makeOutputBlock($media->type, array($query));
-		$parentScope->children[] = $this->scope;
-
-		$this->compileProps($media, $this->scope);
-
-		if (count($this->scope->lines) > 0) {
-			$orphanSelelectors = $this->findClosestSelectors();
-			if (!is_null($orphanSelelectors)) {
-				$orphan = $this->makeOutputBlock(null, $orphanSelelectors);
-				$orphan->lines = $this->scope->lines;
-				array_unshift($this->scope->children, $orphan);
-				$this->scope->lines = array();
-			}
-		}
-
-		$this->scope = $this->scope->parent;
-		$this->popEnv();
-	}
-
-	protected function mediaParent($scope) {
-		while (!empty($scope->parent)) {
-			if (!empty($scope->type) && $scope->type != "media") {
-				break;
-			}
-			$scope = $scope->parent;
-		}
-
-		return $scope;
-	}
-
-	protected function compileNestedBlock($block, $selectors) {
-		$this->pushEnv($block);
-		$this->scope = $this->makeOutputBlock($block->type, $selectors);
-		$this->scope->parent->children[] = $this->scope;
-
-		$this->compileProps($block, $this->scope);
-
-		$this->scope = $this->scope->parent;
-		$this->popEnv();
-	}
-
-	protected function compileRoot($root) {
-		$this->pushEnv();
-		$this->scope = $this->makeOutputBlock($root->type);
-		$this->compileProps($root, $this->scope);
-		$this->popEnv();
-	}
-
-	protected function compileProps($block, $out) {
-		foreach ($this->sortProps($block->props) as $prop) {
-			$this->compileProp($prop, $block, $out);
-		}
-		$out->lines = $this->deduplicate($out->lines);
-	}
-
-	/**
-	 * Deduplicate lines in a block. Comments are not deduplicated. If a
-	 * duplicate rule is detected, the comments immediately preceding each
-	 * occurence are consolidated.
-	 */
-	protected function deduplicate($lines) {
-		$unique = array();
-		$comments = array();
-
-		foreach($lines as $line) {
-			if (strpos($line, '/*') === 0) {
-				$comments[] = $line;
-				continue;
-			}
-			if (!in_array($line, $unique)) {
-				$unique[] = $line;
-			}
-			array_splice($unique, array_search($line, $unique), 0, $comments);
-			$comments = array();
-		}
-		return array_merge($unique, $comments);
-	}
-
-	protected function sortProps($props, $split = false) {
-		$vars = array();
-		$imports = array();
-		$other = array();
-		$stack = array();
-
-		foreach ($props as $prop) {
-			switch ($prop[0]) {
-			case "comment":
-				$stack[] = $prop;
-				break;
-			case "assign":
-				$stack[] = $prop;
-				if (isset($prop[1][0]) && $prop[1][0] == $this->vPrefix) {
-					$vars = array_merge($vars, $stack);
-				} else {
-					$other = array_merge($other, $stack);
-				}
-				$stack = array();
-				break;
-			case "import":
-				$id = self::$nextImportId++;
-				$prop[] = $id;
-				$stack[] = $prop;
-				$imports = array_merge($imports, $stack);
-				$other[] = array("import_mixin", $id);
-				$stack = array();
-				break;
-			default:
-				$stack[] = $prop;
-				$other = array_merge($other, $stack);
-				$stack = array();
-				break;
-			}
-		}
-		$other = array_merge($other, $stack);
-
-		if ($split) {
-			return array(array_merge($imports, $vars), $other);
-		} else {
-			return array_merge($imports, $vars, $other);
-		}
-	}
-
-	protected function compileMediaQuery($queries) {
-		$compiledQueries = array();
-		foreach ($queries as $query) {
-			$parts = array();
-			foreach ($query as $q) {
-				switch ($q[0]) {
-				case "mediaType":
-					$parts[] = implode(" ", array_slice($q, 1));
-					break;
-				case "mediaExp":
-					if (isset($q[2])) {
-						$parts[] = "($q[1]: " .
-							$this->compileValue($this->reduce($q[2])) . ")";
-					} else {
-						$parts[] = "($q[1])";
-					}
-					break;
-				case "variable":
-					$parts[] = $this->compileValue($this->reduce($q));
-				break;
-				}
-			}
-
-			if (count($parts) > 0) {
-				$compiledQueries[] =  implode(" and ", $parts);
-			}
-		}
-
-		$out = "@media";
-		if (!empty($parts)) {
-			$out .= " " .
-				implode($this->formatter->selectorSeparator, $compiledQueries);
-		}
-		return $out;
-	}
-
-	protected function multiplyMedia($env, $childQueries = null) {
-		if (is_null($env) ||
-			!empty($env->block->type) && $env->block->type != "media")
-		{
-			return $childQueries;
-		}
-
-		// plain old block, skip
-		if (empty($env->block->type)) {
-			return $this->multiplyMedia($env->parent, $childQueries);
-		}
-
-		$out = array();
-		$queries = $env->block->queries;
-		if (is_null($childQueries)) {
-			$out = $queries;
-		} else {
-			foreach ($queries as $parent) {
-				foreach ($childQueries as $child) {
-					$out[] = array_merge($parent, $child);
-				}
-			}
-		}
-
-		return $this->multiplyMedia($env->parent, $out);
-	}
-
-	protected function expandParentSelectors(&$tag, $replace) {
-		$parts = explode("$&$", $tag);
-		$count = 0;
-		foreach ($parts as &$part) {
-			$part = str_replace($this->parentSelector, $replace, $part, $c);
-			$count += $c;
-		}
-		$tag = implode($this->parentSelector, $parts);
-		return $count;
-	}
-
-	protected function findClosestSelectors() {
-		$env = $this->env;
-		$selectors = null;
-		while ($env !== null) {
-			if (isset($env->selectors)) {
-				$selectors = $env->selectors;
-				break;
-			}
-			$env = $env->parent;
-		}
-
-		return $selectors;
-	}
-
-
-	// multiply $selectors against the nearest selectors in env
-	protected function multiplySelectors($selectors) {
-		// find parent selectors
-
-		$parentSelectors = $this->findClosestSelectors();
-		if (is_null($parentSelectors)) {
-			// kill parent reference in top level selector
-			foreach ($selectors as &$s) {
-				$this->expandParentSelectors($s, "");
-			}
-
-			return $selectors;
-		}
-
-		$out = array();
-		foreach ($parentSelectors as $parent) {
-			foreach ($selectors as $child) {
-				$count = $this->expandParentSelectors($child, $parent);
-
-				// don't prepend the parent tag if & was used
-				if ($count > 0) {
-					$out[] = trim($child);
-				} else {
-					$out[] = trim($parent . ' ' . $child);
-				}
-			}
-		}
-
-		return $out;
-	}
-
-	// reduces selector expressions
-	protected function compileSelectors($selectors) {
-		$out = array();
-
-		foreach ($selectors as $s) {
-			if (is_array($s)) {
-				list(, $value) = $s;
-				$out[] = trim($this->compileValue($this->reduce($value)));
-			} else {
-				$out[] = $s;
-			}
-		}
-
-		return $out;
-	}
-
-	protected function eq($left, $right) {
-		return $left == $right;
-	}
-
-	protected function patternMatch($block, $orderedArgs, $keywordArgs) {
-		// match the guards if it has them
-		// any one of the groups must have all its guards pass for a match
-		if (!empty($block->guards)) {
-			$groupPassed = false;
-			foreach ($block->guards as $guardGroup) {
-				foreach ($guardGroup as $guard) {
-					$this->pushEnv();
-					$this->zipSetArgs($block->args, $orderedArgs, $keywordArgs);
-
-					$negate = false;
-					if ($guard[0] == "negate") {
-						$guard = $guard[1];
-						$negate = true;
-					}
-
-					$passed = $this->reduce($guard) == self::$TRUE;
-					if ($negate) $passed = !$passed;
-
-					$this->popEnv();
-
-					if ($passed) {
-						$groupPassed = true;
-					} else {
-						$groupPassed = false;
-						break;
-					}
-				}
-
-				if ($groupPassed) break;
-			}
-
-			if (!$groupPassed) {
-				return false;
-			}
-		}
-
-		if (empty($block->args)) {
-			return $block->isVararg || empty($orderedArgs) && empty($keywordArgs);
-		}
-
-		$remainingArgs = $block->args;
-		if ($keywordArgs) {
-			$remainingArgs = array();
-			foreach ($block->args as $arg) {
-				if ($arg[0] == "arg" && isset($keywordArgs[$arg[1]])) {
-					continue;
-				}
-
-				$remainingArgs[] = $arg;
-			}
-		}
-
-		$i = -1; // no args
-		// try to match by arity or by argument literal
-		foreach ($remainingArgs as $i => $arg) {
-			switch ($arg[0]) {
-			case "lit":
-				if (empty($orderedArgs[$i]) || !$this->eq($arg[1], $orderedArgs[$i])) {
-					return false;
-				}
-				break;
-			case "arg":
-				// no arg and no default value
-				if (!isset($orderedArgs[$i]) && !isset($arg[2])) {
-					return false;
-				}
-				break;
-			case "rest":
-				$i--; // rest can be empty
-				break 2;
-			}
-		}
-
-		if ($block->isVararg) {
-			return true; // not having enough is handled above
-		} else {
-			$numMatched = $i + 1;
-			// greater than becuase default values always match
-			return $numMatched >= count($orderedArgs);
-		}
-	}
-
-	protected function patternMatchAll($blocks, $orderedArgs, $keywordArgs, $skip=array()) {
-		$matches = null;
-		foreach ($blocks as $block) {
-			// skip seen blocks that don't have arguments
-			if (isset($skip[$block->id]) && !isset($block->args)) {
-				continue;
-			}
-
-			if ($this->patternMatch($block, $orderedArgs, $keywordArgs)) {
-				$matches[] = $block;
-			}
-		}
-
-		return $matches;
-	}
-
-	// attempt to find blocks matched by path and args
-	protected function findBlocks($searchIn, $path, $orderedArgs, $keywordArgs, $seen=array()) {
-		if ($searchIn == null) return null;
-		if (isset($seen[$searchIn->id])) return null;
-		$seen[$searchIn->id] = true;
-
-		$name = $path[0];
-
-		if (isset($searchIn->children[$name])) {
-			$blocks = $searchIn->children[$name];
-			if (count($path) == 1) {
-				$matches = $this->patternMatchAll($blocks, $orderedArgs, $keywordArgs, $seen);
-				if (!empty($matches)) {
-					// This will return all blocks that match in the closest
-					// scope that has any matching block, like lessjs
-					return $matches;
-				}
-			} else {
-				$matches = array();
-				foreach ($blocks as $subBlock) {
-					$subMatches = $this->findBlocks($subBlock,
-						array_slice($path, 1), $orderedArgs, $keywordArgs, $seen);
-
-					if (!is_null($subMatches)) {
-						foreach ($subMatches as $sm) {
-							$matches[] = $sm;
-						}
-					}
-				}
-
-				return count($matches) > 0 ? $matches : null;
-			}
-		}
-		if ($searchIn->parent === $searchIn) return null;
-		return $this->findBlocks($searchIn->parent, $path, $orderedArgs, $keywordArgs, $seen);
-	}
-
-	// sets all argument names in $args to either the default value
-	// or the one passed in through $values
-	protected function zipSetArgs($args, $orderedValues, $keywordValues) {
-		$assignedValues = array();
-
-		$i = 0;
-		foreach ($args as  $a) {
-			if ($a[0] == "arg") {
-				if (isset($keywordValues[$a[1]])) {
-					// has keyword arg
-					$value = $keywordValues[$a[1]];
-				} elseif (isset($orderedValues[$i])) {
-					// has ordered arg
-					$value = $orderedValues[$i];
-					$i++;
-				} elseif (isset($a[2])) {
-					// has default value
-					$value = $a[2];
-				} else {
-					$this->throwError("Failed to assign arg " . $a[1]);
-					$value = null; // :(
-				}
-
-				$value = $this->reduce($value);
-				$this->set($a[1], $value);
-				$assignedValues[] = $value;
-			} else {
-				// a lit
-				$i++;
-			}
-		}
-
-		// check for a rest
-		$last = end($args);
-		if ($last[0] == "rest") {
-			$rest = array_slice($orderedValues, count($args) - 1);
-			$this->set($last[1], $this->reduce(array("list", " ", $rest)));
-		}
-
-		// wow is this the only true use of PHP's + operator for arrays?
-		$this->env->arguments = $assignedValues + $orderedValues;
-	}
-
-	// compile a prop and update $lines or $blocks appropriately
-	protected function compileProp($prop, $block, $out) {
-		// set error position context
-		$this->sourceLoc = isset($prop[-1]) ? $prop[-1] : -1;
-
-		switch ($prop[0]) {
-		case 'assign':
-			list(, $name, $value) = $prop;
-			if ($name[0] == $this->vPrefix) {
-				$this->set($name, $value);
-			} else {
-				$out->lines[] = $this->formatter->property($name,
-						$this->compileValue($this->reduce($value)));
-			}
-			break;
-		case 'block':
-			list(, $child) = $prop;
-			$this->compileBlock($child);
-			break;
-		case 'mixin':
-			list(, $path, $args, $suffix) = $prop;
-
-			$orderedArgs = array();
-			$keywordArgs = array();
-			foreach ((array)$args as $arg) {
-				$argval = null;
-				switch ($arg[0]) {
-				case "arg":
-					if (!isset($arg[2])) {
-						$orderedArgs[] = $this->reduce(array("variable", $arg[1]));
-					} else {
-						$keywordArgs[$arg[1]] = $this->reduce($arg[2]);
-					}
-					break;
-
-				case "lit":
-					$orderedArgs[] = $this->reduce($arg[1]);
-					break;
-				default:
-					$this->throwError("Unknown arg type: " . $arg[0]);
-				}
-			}
-
-			$mixins = $this->findBlocks($block, $path, $orderedArgs, $keywordArgs);
-
-			if ($mixins === null) {
-				$this->throwError("{$prop[1][0]} is undefined");
-			}
-
-			foreach ($mixins as $mixin) {
-				if ($mixin === $block && !$orderedArgs) {
-					continue;
-				}
-
-				$haveScope = false;
-				if (isset($mixin->parent->scope)) {
-					$haveScope = true;
-					$mixinParentEnv = $this->pushEnv();
-					$mixinParentEnv->storeParent = $mixin->parent->scope;
-				}
-
-				$haveArgs = false;
-				if (isset($mixin->args)) {
-					$haveArgs = true;
-					$this->pushEnv();
-					$this->zipSetArgs($mixin->args, $orderedArgs, $keywordArgs);
-				}
-
-				$oldParent = $mixin->parent;
-				if ($mixin != $block) $mixin->parent = $block;
-
-				foreach ($this->sortProps($mixin->props) as $subProp) {
-					if ($suffix !== null &&
-						$subProp[0] == "assign" &&
-						is_string($subProp[1]) &&
-						$subProp[1]{0} != $this->vPrefix)
-					{
-						$subProp[2] = array(
-							'list', ' ',
-							array($subProp[2], array('keyword', $suffix))
-						);
-					}
-
-					$this->compileProp($subProp, $mixin, $out);
-				}
-
-				$mixin->parent = $oldParent;
-
-				if ($haveArgs) $this->popEnv();
-				if ($haveScope) $this->popEnv();
-			}
-
-			break;
-		case 'raw':
-			$out->lines[] = $prop[1];
-			break;
-		case "directive":
-			list(, $name, $value) = $prop;
-			$out->lines[] = "@$name " . $this->compileValue($this->reduce($value)).';';
-			break;
-		case "comment":
-			$out->lines[] = $prop[1];
-			break;
-		case "import";
-			list(, $importPath, $importId) = $prop;
-			$importPath = $this->reduce($importPath);
-
-			if (!isset($this->env->imports)) {
-				$this->env->imports = array();
-			}
-
-			$result = $this->tryImport($importPath, $block, $out);
-
-			$this->env->imports[$importId] = $result === false ?
-				array(false, "@import " . $this->compileValue($importPath).";") :
-				$result;
-
-			break;
-		case "import_mixin":
-			list(,$importId) = $prop;
-			$import = $this->env->imports[$importId];
-			if ($import[0] === false) {
-				if (isset($import[1])) {
-					$out->lines[] = $import[1];
-				}
-			} else {
-				list(, $bottom, $parser, $importDir) = $import;
-				$this->compileImportedProps($bottom, $block, $out, $parser, $importDir);
-			}
-
-			break;
-		default:
-			$this->throwError("unknown op: {$prop[0]}\n");
-		}
-	}
-
-
-	/**
-	 * Compiles a primitive value into a CSS property value.
-	 *
-	 * Values in lessphp are typed by being wrapped in arrays, their format is
-	 * typically:
-	 *
-	 *     array(type, contents [, additional_contents]*)
-	 *
-	 * The input is expected to be reduced. This function will not work on
-	 * things like expressions and variables.
-	 */
-	public function compileValue($value) {
-		switch ($value[0]) {
-		case 'list':
-			// [1] - delimiter
-			// [2] - array of values
-			return implode($value[1], array_map(array($this, 'compileValue'), $value[2]));
-		case 'raw_color':
-			if (!empty($this->formatter->compressColors)) {
-				return $this->compileValue($this->coerceColor($value));
-			}
-			return $value[1];
-		case 'keyword':
-			// [1] - the keyword
-			return $value[1];
-		case 'number':
-			list(, $num, $unit) = $value;
-			// [1] - the number
-			// [2] - the unit
-			if ($this->numberPrecision !== null) {
-				$num = round($num, $this->numberPrecision);
-			}
-			return $num . $unit;
-		case 'string':
-			// [1] - contents of string (includes quotes)
-			list(, $delim, $content) = $value;
-			foreach ($content as &$part) {
-				if (is_array($part)) {
-					$part = $this->compileValue($part);
-				}
-			}
-			return $delim . implode($content) . $delim;
-		case 'color':
-			// [1] - red component (either number or a %)
-			// [2] - green component
-			// [3] - blue component
-			// [4] - optional alpha component
-			list(, $r, $g, $b) = $value;
-			$r = round($r);
-			$g = round($g);
-			$b = round($b);
-
-			if (count($value) == 5 && $value[4] != 1) { // rgba
-				return 'rgba('.$r.','.$g.','.$b.','.$value[4].')';
-			}
-
-			$h = sprintf("#%02x%02x%02x", $r, $g, $b);
-
-			if (!empty($this->formatter->compressColors)) {
-				// Converting hex color to short notation (e.g. #003399 to #039)
-				if ($h[1] === $h[2] && $h[3] === $h[4] && $h[5] === $h[6]) {
-					$h = '#' . $h[1] . $h[3] . $h[5];
-				}
-			}
-
-			return $h;
-
-		case 'function':
-			list(, $name, $args) = $value;
-			return $name.'('.$this->compileValue($args).')';
-		default: // assumed to be unit
-			$this->throwError("unknown value type: $value[0]");
-		}
-	}
-
-	protected function lib_pow($args) {
-		list($base, $exp) = $this->assertArgs($args, 2, "pow");
-		return pow($this->assertNumber($base), $this->assertNumber($exp));
-	}
-
-	protected function lib_pi() {
-		return pi();
-	}
-
-	protected function lib_mod($args) {
-		list($a, $b) = $this->assertArgs($args, 2, "mod");
-		return $this->assertNumber($a) % $this->assertNumber($b);
-	}
-
-	protected function lib_tan($num) {
-		return tan($this->assertNumber($num));
-	}
-
-	protected function lib_sin($num) {
-		return sin($this->assertNumber($num));
-	}
-
-	protected function lib_cos($num) {
-		return cos($this->assertNumber($num));
-	}
-
-	protected function lib_atan($num) {
-		$num = atan($this->assertNumber($num));
-		return array("number", $num, "rad");
-	}
-
-	protected function lib_asin($num) {
-		$num = asin($this->assertNumber($num));
-		return array("number", $num, "rad");
-	}
-
-	protected function lib_acos($num) {
-		$num = acos($this->assertNumber($num));
-		return array("number", $num, "rad");
-	}
-
-	protected function lib_sqrt($num) {
-		return sqrt($this->assertNumber($num));
-	}
-
-	protected function lib_extract($value) {
-		list($list, $idx) = $this->assertArgs($value, 2, "extract");
-		$idx = $this->assertNumber($idx);
-		// 1 indexed
-		if ($list[0] == "list" && isset($list[2][$idx - 1])) {
-			return $list[2][$idx - 1];
-		}
-	}
-
-	protected function lib_isnumber($value) {
-		return $this->toBool($value[0] == "number");
-	}
-
-	protected function lib_isstring($value) {
-		return $this->toBool($value[0] == "string");
-	}
-
-	protected function lib_iscolor($value) {
-		return $this->toBool($this->coerceColor($value));
-	}
-
-	protected function lib_iskeyword($value) {
-		return $this->toBool($value[0] == "keyword");
-	}
-
-	protected function lib_ispixel($value) {
-		return $this->toBool($value[0] == "number" && $value[2] == "px");
-	}
-
-	protected function lib_ispercentage($value) {
-		return $this->toBool($value[0] == "number" && $value[2] == "%");
-	}
-
-	protected function lib_isem($value) {
-		return $this->toBool($value[0] == "number" && $value[2] == "em");
-	}
-
-	protected function lib_isrem($value) {
-		return $this->toBool($value[0] == "number" && $value[2] == "rem");
-	}
-
-	protected function lib_rgbahex($color) {
-		$color = $this->coerceColor($color);
-		if (is_null($color))
-			$this->throwError("color expected for rgbahex");
-
-		return sprintf("#%02x%02x%02x%02x",
-			isset($color[4]) ? $color[4]*255 : 255,
-			$color[1],$color[2], $color[3]);
-	}
-
-	protected function lib_argb($color){
-		return $this->lib_rgbahex($color);
-	}
-
-	/**
-	 * Given an url, decide whether to output a regular link or the base64-encoded contents of the file
-	 *
-	 * @param  array  $value either an argument list (two strings) or a single string
-	 * @return string        formatted url(), either as a link or base64-encoded
-	 */
-	protected function lib_data_uri($value) {
-		$mime = ($value[0] === 'list') ? $value[2][0][2] : null;
-		$url = ($value[0] === 'list') ? $value[2][1][2][0] : $value[2][0];
-
-		$fullpath = $this->findImport($url);
-
-		if($fullpath && ($fsize = filesize($fullpath)) !== false) {
-			// IE8 can't handle data uris larger than 32KB
-			if($fsize/1024 < 32) {
-				if(is_null($mime)) {
-					if(class_exists('finfo')) { // php 5.3+
-						$finfo = new finfo(FILEINFO_MIME);
-						$mime = explode('; ', $finfo->file($fullpath));
-						$mime = $mime[0];
-					} elseif(function_exists('mime_content_type')) { // PHP 5.2
-						$mime = mime_content_type($fullpath);
-					}
-				}
-
-				if(!is_null($mime)) // fallback if the mime type is still unknown
-					$url = sprintf('data:%s;base64,%s', $mime, base64_encode(file_get_contents($fullpath)));
-			}
-		}
-
-		return 'url("'.$url.'")';
-	}
-
-	// utility func to unquote a string
-	protected function lib_e($arg) {
-		switch ($arg[0]) {
-			case "list":
-				$items = $arg[2];
-				if (isset($items[0])) {
-					return $this->lib_e($items[0]);
-				}
-				$this->throwError("unrecognised input");
-			case "string":
-				$arg[1] = "";
-				return $arg;
-			case "keyword":
-				return $arg;
-			default:
-				return array("keyword", $this->compileValue($arg));
-		}
-	}
-
-	protected function lib__sprintf($args) {
-		if ($args[0] != "list") return $args;
-		$values = $args[2];
-		$string = array_shift($values);
-		$template = $this->compileValue($this->lib_e($string));
-
-		$i = 0;
-		if (preg_match_all('/%[dsa]/', $template, $m)) {
-			foreach ($m[0] as $match) {
-				$val = isset($values[$i]) ?
-					$this->reduce($values[$i]) : array('keyword', '');
-
-				// lessjs compat, renders fully expanded color, not raw color
-				if ($color = $this->coerceColor($val)) {
-					$val = $color;
-				}
-
-				$i++;
-				$rep = $this->compileValue($this->lib_e($val));
-				$template = preg_replace('/'.self::preg_quote($match).'/',
-					$rep, $template, 1);
-			}
-		}
-
-		$d = $string[0] == "string" ? $string[1] : '"';
-		return array("string", $d, array($template));
-	}
-
-	protected function lib_floor($arg) {
-		$value = $this->assertNumber($arg);
-		return array("number", floor($value), $arg[2]);
-	}
-
-	protected function lib_ceil($arg) {
-		$value = $this->assertNumber($arg);
-		return array("number", ceil($value), $arg[2]);
-	}
-
-	protected function lib_round($arg) {
-		if($arg[0] != "list") {
-			$value = $this->assertNumber($arg);
-			return array("number", round($value), $arg[2]);
-		} else {
-			$value = $this->assertNumber($arg[2][0]);
-			$precision = $this->assertNumber($arg[2][1]);
-			return array("number", round($value, $precision), $arg[2][0][2]);
-		}
-	}
-
-	protected function lib_unit($arg) {
-		if ($arg[0] == "list") {
-			list($number, $newUnit) = $arg[2];
-			return array("number", $this->assertNumber($number),
-				$this->compileValue($this->lib_e($newUnit)));
-		} else {
-			return array("number", $this->assertNumber($arg), "");
-		}
-	}
-
-	/**
-	 * Helper function to get arguments for color manipulation functions.
-	 * takes a list that contains a color like thing and a percentage
-	 */
-	public function colorArgs($args) {
-		if ($args[0] != 'list' || count($args[2]) < 2) {
-			return array(array('color', 0, 0, 0), 0);
-		}
-		list($color, $delta) = $args[2];
-		$color = $this->assertColor($color);
-		$delta = floatval($delta[1]);
-
-		return array($color, $delta);
-	}
-
-	protected function lib_darken($args) {
-		list($color, $delta) = $this->colorArgs($args);
-
-		$hsl = $this->toHSL($color);
-		$hsl[3] = $this->clamp($hsl[3] - $delta, 100);
-		return $this->toRGB($hsl);
-	}
-
-	protected function lib_lighten($args) {
-		list($color, $delta) = $this->colorArgs($args);
-
-		$hsl = $this->toHSL($color);
-		$hsl[3] = $this->clamp($hsl[3] + $delta, 100);
-		return $this->toRGB($hsl);
-	}
-
-	protected function lib_saturate($args) {
-		list($color, $delta) = $this->colorArgs($args);
-
-		$hsl = $this->toHSL($color);
-		$hsl[2] = $this->clamp($hsl[2] + $delta, 100);
-		return $this->toRGB($hsl);
-	}
-
-	protected function lib_desaturate($args) {
-		list($color, $delta) = $this->colorArgs($args);
-
-		$hsl = $this->toHSL($color);
-		$hsl[2] = $this->clamp($hsl[2] - $delta, 100);
-		return $this->toRGB($hsl);
-	}
-
-	protected function lib_spin($args) {
-		list($color, $delta) = $this->colorArgs($args);
-
-		$hsl = $this->toHSL($color);
-
-		$hsl[1] = $hsl[1] + $delta % 360;
-		if ($hsl[1] < 0) $hsl[1] += 360;
-
-		return $this->toRGB($hsl);
-	}
-
-	protected function lib_fadeout($args) {
-		list($color, $delta) = $this->colorArgs($args);
-		$color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) - $delta/100);
-		return $color;
-	}
-
-	protected function lib_fadein($args) {
-		list($color, $delta) = $this->colorArgs($args);
-		$color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) + $delta/100);
-		return $color;
-	}
-
-	protected function lib_hue($color) {
-		$hsl = $this->toHSL($this->assertColor($color));
-		return round($hsl[1]);
-	}
-
-	protected function lib_saturation($color) {
-		$hsl = $this->toHSL($this->assertColor($color));
-		return round($hsl[2]);
-	}
-
-	protected function lib_lightness($color) {
-		$hsl = $this->toHSL($this->assertColor($color));
-		return round($hsl[3]);
-	}
-
-	// get the alpha of a color
-	// defaults to 1 for non-colors or colors without an alpha
-	protected function lib_alpha($value) {
-		if (!is_null($color = $this->coerceColor($value))) {
-			return isset($color[4]) ? $color[4] : 1;
-		}
-	}
-
-	// set the alpha of the color
-	protected function lib_fade($args) {
-		list($color, $alpha) = $this->colorArgs($args);
-		$color[4] = $this->clamp($alpha / 100.0);
-		return $color;
-	}
-
-	protected function lib_percentage($arg) {
-		$num = $this->assertNumber($arg);
-		return array("number", $num*100, "%");
-	}
-
-	// mixes two colors by weight
-	// mix(@color1, @color2, [@weight: 50%]);
-	// http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#mix-instance_method
-	protected function lib_mix($args) {
-		if ($args[0] != "list" || count($args[2]) < 2)
-			$this->throwError("mix expects (color1, color2, weight)");
-
-		list($first, $second) = $args[2];
-		$first = $this->assertColor($first);
-		$second = $this->assertColor($second);
-
-		$first_a = $this->lib_alpha($first);
-		$second_a = $this->lib_alpha($second);
-
-		if (isset($args[2][2])) {
-			$weight = $args[2][2][1] / 100.0;
-		} else {
-			$weight = 0.5;
-		}
-
-		$w = $weight * 2 - 1;
-		$a = $first_a - $second_a;
-
-		$w1 = (($w * $a == -1 ? $w : ($w + $a)/(1 + $w * $a)) + 1) / 2.0;
-		$w2 = 1.0 - $w1;
-
-		$new = array('color',
-			$w1 * $first[1] + $w2 * $second[1],
-			$w1 * $first[2] + $w2 * $second[2],
-			$w1 * $first[3] + $w2 * $second[3],
-		);
-
-		if ($first_a != 1.0 || $second_a != 1.0) {
-			$new[] = $first_a * $weight + $second_a * ($weight - 1);
-		}
-
-		return $this->fixColor($new);
-	}
-
-	protected function lib_contrast($args) {
-	    $darkColor  = array('color', 0, 0, 0);
-	    $lightColor = array('color', 255, 255, 255);
-	    $threshold  = 0.43;
-
-	    if ( $args[0] == 'list' ) {
-	        $inputColor = ( isset($args[2][0]) ) ? $this->assertColor($args[2][0])  : $lightColor;
-	        $darkColor  = ( isset($args[2][1]) ) ? $this->assertColor($args[2][1])  : $darkColor;
-	        $lightColor = ( isset($args[2][2]) ) ? $this->assertColor($args[2][2])  : $lightColor;
-	        $threshold  = ( isset($args[2][3]) ) ? $this->assertNumber($args[2][3]) : $threshold;
-	    }
-	    else {
-	        $inputColor  = $this->assertColor($args);
-	    }
-
-	    $inputColor = $this->coerceColor($inputColor);
-	    $darkColor  = $this->coerceColor($darkColor);
-	    $lightColor = $this->coerceColor($lightColor);
-
-	    //Figure out which is actually light and dark!
-	    if ( $this->lib_luma($darkColor) > $this->lib_luma($lightColor) ) {
-	        $t  = $lightColor;
-	        $lightColor = $darkColor;
-	        $darkColor  = $t;
-	    }
-
-	    $inputColor_alpha = $this->lib_alpha($inputColor);
-	    if ( ( $this->lib_luma($inputColor) * $inputColor_alpha) < $threshold) {
-	        return $lightColor;
-	    }
-	    return $darkColor;
-	}
-
-	protected function lib_luma($color) {
-	    $color = $this->coerceColor($color);
-	    return (0.2126 * $color[0] / 255) + (0.7152 * $color[1] / 255) + (0.0722 * $color[2] / 255);
-	}
-
-
-	public function assertColor($value, $error = "expected color value") {
-		$color = $this->coerceColor($value);
-		if (is_null($color)) $this->throwError($error);
-		return $color;
-	}
-
-	public function assertNumber($value, $error = "expecting number") {
-		if ($value[0] == "number") return $value[1];
-		$this->throwError($error);
-	}
-
-	public function assertArgs($value, $expectedArgs, $name="") {
-		if ($expectedArgs == 1) {
-			return $value;
-		} else {
-			if ($value[0] !== "list" || $value[1] != ",") $this->throwError("expecting list");
-			$values = $value[2];
-			$numValues = count($values);
-			if ($expectedArgs != $numValues) {
-				if ($name) {
-					$name = $name . ": ";
-				}
-
-				$this->throwError("${name}expecting $expectedArgs arguments, got $numValues");
-			}
-
-			return $values;
-		}
-	}
-
-	protected function toHSL($color) {
-		if ($color[0] == 'hsl') return $color;
-
-		$r = $color[1] / 255;
-		$g = $color[2] / 255;
-		$b = $color[3] / 255;
-
-		$min = min($r, $g, $b);
-		$max = max($r, $g, $b);
-
-		$L = ($min + $max) / 2;
-		if ($min == $max) {
-			$S = $H = 0;
-		} else {
-			if ($L < 0.5)
-				$S = ($max - $min)/($max + $min);
-			else
-				$S = ($max - $min)/(2.0 - $max - $min);
-
-			if ($r == $max) $H = ($g - $b)/($max - $min);
-			elseif ($g == $max) $H = 2.0 + ($b - $r)/($max - $min);
-			elseif ($b == $max) $H = 4.0 + ($r - $g)/($max - $min);
-
-		}
-
-		$out = array('hsl',
-			($H < 0 ? $H + 6 : $H)*60,
-			$S*100,
-			$L*100,
-		);
-
-		if (count($color) > 4) $out[] = $color[4]; // copy alpha
-		return $out;
-	}
-
-	protected function toRGB_helper($comp, $temp1, $temp2) {
-		if ($comp < 0) $comp += 1.0;
-		elseif ($comp > 1) $comp -= 1.0;
-
-		if (6 * $comp < 1) return $temp1 + ($temp2 - $temp1) * 6 * $comp;
-		if (2 * $comp < 1) return $temp2;
-		if (3 * $comp < 2) return $temp1 + ($temp2 - $temp1)*((2/3) - $comp) * 6;
-
-		return $temp1;
-	}
-
-	/**
-	 * Converts a hsl array into a color value in rgb.
-	 * Expects H to be in range of 0 to 360, S and L in 0 to 100
-	 */
-	protected function toRGB($color) {
-		if ($color[0] == 'color') return $color;
-
-		$H = $color[1] / 360;
-		$S = $color[2] / 100;
-		$L = $color[3] / 100;
-
-		if ($S == 0) {
-			$r = $g = $b = $L;
-		} else {
-			$temp2 = $L < 0.5 ?
-				$L*(1.0 + $S) :
-				$L + $S - $L * $S;
-
-			$temp1 = 2.0 * $L - $temp2;
-
-			$r = $this->toRGB_helper($H + 1/3, $temp1, $temp2);
-			$g = $this->toRGB_helper($H, $temp1, $temp2);
-			$b = $this->toRGB_helper($H - 1/3, $temp1, $temp2);
-		}
-
-		// $out = array('color', round($r*255), round($g*255), round($b*255));
-		$out = array('color', $r*255, $g*255, $b*255);
-		if (count($color) > 4) $out[] = $color[4]; // copy alpha
-		return $out;
-	}
-
-	protected function clamp($v, $max = 1, $min = 0) {
-		return min($max, max($min, $v));
-	}
-
-	/**
-	 * Convert the rgb, rgba, hsl color literals of function type
-	 * as returned by the parser into values of color type.
-	 */
-	protected function funcToColor($func) {
-		$fname = $func[1];
-		if ($func[2][0] != 'list') return false; // need a list of arguments
-		$rawComponents = $func[2][2];
-
-		if ($fname == 'hsl' || $fname == 'hsla') {
-			$hsl = array('hsl');
-			$i = 0;
-			foreach ($rawComponents as $c) {
-				$val = $this->reduce($c);
-				$val = isset($val[1]) ? floatval($val[1]) : 0;
-
-				if ($i == 0) $clamp = 360;
-				elseif ($i < 3) $clamp = 100;
-				else $clamp = 1;
-
-				$hsl[] = $this->clamp($val, $clamp);
-				$i++;
-			}
-
-			while (count($hsl) < 4) $hsl[] = 0;
-			return $this->toRGB($hsl);
-
-		} elseif ($fname == 'rgb' || $fname == 'rgba') {
-			$components = array();
-			$i = 1;
-			foreach	($rawComponents as $c) {
-				$c = $this->reduce($c);
-				if ($i < 4) {
-					if ($c[0] == "number" && $c[2] == "%") {
-						$components[] = 255 * ($c[1] / 100);
-					} else {
-						$components[] = floatval($c[1]);
-					}
-				} elseif ($i == 4) {
-					if ($c[0] == "number" && $c[2] == "%") {
-						$components[] = 1.0 * ($c[1] / 100);
-					} else {
-						$components[] = floatval($c[1]);
-					}
-				} else break;
-
-				$i++;
-			}
-			while (count($components) < 3) $components[] = 0;
-			array_unshift($components, 'color');
-			return $this->fixColor($components);
-		}
-
-		return false;
-	}
-
-	protected function reduce($value, $forExpression = false) {
-		switch ($value[0]) {
-		case "interpolate":
-			$reduced = $this->reduce($value[1]);
-			$var = $this->compileValue($reduced);
-			$res = $this->reduce(array("variable", $this->vPrefix . $var));
-
-			if ($res[0] == "raw_color") {
-				$res = $this->coerceColor($res);
-			}
-
-			if (empty($value[2])) $res = $this->lib_e($res);
-
-			return $res;
-		case "variable":
-			$key = $value[1];
-			if (is_array($key)) {
-				$key = $this->reduce($key);
-				$key = $this->vPrefix . $this->compileValue($this->lib_e($key));
-			}
-
-			$seen =& $this->env->seenNames;
-
-			if (!empty($seen[$key])) {
-				$this->throwError("infinite loop detected: $key");
-			}
-
-			$seen[$key] = true;
-			$out = $this->reduce($this->get($key));
-			$seen[$key] = false;
-			return $out;
-		case "list":
-			foreach ($value[2] as &$item) {
-				$item = $this->reduce($item, $forExpression);
-			}
-			return $value;
-		case "expression":
-			return $this->evaluate($value);
-		case "string":
-			foreach ($value[2] as &$part) {
-				if (is_array($part)) {
-					$strip = $part[0] == "variable";
-					$part = $this->reduce($part);
-					if ($strip) $part = $this->lib_e($part);
-				}
-			}
-			return $value;
-		case "escape":
-			list(,$inner) = $value;
-			return $this->lib_e($this->reduce($inner));
-		case "function":
-			$color = $this->funcToColor($value);
-			if ($color) return $color;
-
-			list(, $name, $args) = $value;
-			if ($name == "%") $name = "_sprintf";
-
-			$f = isset($this->libFunctions[$name]) ?
-				$this->libFunctions[$name] : array($this, 'lib_'.str_replace('-', '_', $name));
-
-			if (is_callable($f)) {
-				if ($args[0] == 'list')
-					$args = self::compressList($args[2], $args[1]);
-
-				$ret = call_user_func($f, $this->reduce($args, true), $this);
-
-				if (is_null($ret)) {
-					return array("string", "", array(
-						$name, "(", $args, ")"
-					));
-				}
-
-				// convert to a typed value if the result is a php primitive
-				if (is_numeric($ret)) $ret = array('number', $ret, "");
-				elseif (!is_array($ret)) $ret = array('keyword', $ret);
-
-				return $ret;
-			}
-
-			// plain function, reduce args
-			$value[2] = $this->reduce($value[2]);
-			return $value;
-		case "unary":
-			list(, $op, $exp) = $value;
-			$exp = $this->reduce($exp);
-
-			if ($exp[0] == "number") {
-				switch ($op) {
-				case "+":
-					return $exp;
-				case "-":
-					$exp[1] *= -1;
-					return $exp;
-				}
-			}
-			return array("string", "", array($op, $exp));
-		}
-
-		if ($forExpression) {
-			switch ($value[0]) {
-			case "keyword":
-				if ($color = $this->coerceColor($value)) {
-					return $color;
-				}
-				break;
-			case "raw_color":
-				return $this->coerceColor($value);
-			}
-		}
-
-		return $value;
-	}
-
-
-	// coerce a value for use in color operation
-	protected function coerceColor($value) {
-		switch($value[0]) {
-			case 'color': return $value;
-			case 'raw_color':
-				$c = array("color", 0, 0, 0);
-				$colorStr = substr($value[1], 1);
-				$num = hexdec($colorStr);
-				$width = strlen($colorStr) == 3 ? 16 : 256;
-
-				for ($i = 3; $i > 0; $i--) { // 3 2 1
-					$t = $num % $width;
-					$num /= $width;
-
-					$c[$i] = $t * (256/$width) + $t * floor(16/$width);
-				}
-
-				return $c;
-			case 'keyword':
-				$name = $value[1];
-				if (isset(self::$cssColors[$name])) {
-					$rgba = explode(',', self::$cssColors[$name]);
-
-					if(isset($rgba[3]))
-						return array('color', $rgba[0], $rgba[1], $rgba[2], $rgba[3]);
-
-					return array('color', $rgba[0], $rgba[1], $rgba[2]);
-				}
-				return null;
-		}
-	}
-
-	// make something string like into a string
-	protected function coerceString($value) {
-		switch ($value[0]) {
-		case "string":
-			return $value;
-		case "keyword":
-			return array("string", "", array($value[1]));
-		}
-		return null;
-	}
-
-	// turn list of length 1 into value type
-	protected function flattenList($value) {
-		if ($value[0] == "list" && count($value[2]) == 1) {
-			return $this->flattenList($value[2][0]);
-		}
-		return $value;
-	}
-
-	public function toBool($a) {
-		if ($a) return self::$TRUE;
-		else return self::$FALSE;
-	}
-
-	// evaluate an expression
-	protected function evaluate($exp) {
-		list(, $op, $left, $right, $whiteBefore, $whiteAfter) = $exp;
-
-		$left = $this->reduce($left, true);
-		$right = $this->reduce($right, true);
-
-		if ($leftColor = $this->coerceColor($left)) {
-			$left = $leftColor;
-		}
-
-		if ($rightColor = $this->coerceColor($right)) {
-			$right = $rightColor;
-		}
-
-		$ltype = $left[0];
-		$rtype = $right[0];
-
-		// operators that work on all types
-		if ($op == "and") {
-			return $this->toBool($left == self::$TRUE && $right == self::$TRUE);
-		}
-
-		if ($op == "=") {
-			return $this->toBool($this->eq($left, $right) );
-		}
-
-		if ($op == "+" && !is_null($str = $this->stringConcatenate($left, $right))) {
-			return $str;
-		}
-
-		// type based operators
-		$fname = "op_${ltype}_${rtype}";
-		if (is_callable(array($this, $fname))) {
-			$out = $this->$fname($op, $left, $right);
-			if (!is_null($out)) return $out;
-		}
-
-		// make the expression look it did before being parsed
-		$paddedOp = $op;
-		if ($whiteBefore) $paddedOp = " " . $paddedOp;
-		if ($whiteAfter) $paddedOp .= " ";
-
-		return array("string", "", array($left, $paddedOp, $right));
-	}
-
-	protected function stringConcatenate($left, $right) {
-		if ($strLeft = $this->coerceString($left)) {
-			if ($right[0] == "string") {
-				$right[1] = "";
-			}
-			$strLeft[2][] = $right;
-			return $strLeft;
-		}
-
-		if ($strRight = $this->coerceString($right)) {
-			array_unshift($strRight[2], $left);
-			return $strRight;
-		}
-	}
-
-
-	// make sure a color's components don't go out of bounds
-	protected function fixColor($c) {
-		foreach (range(1, 3) as $i) {
-			if ($c[$i] < 0) $c[$i] = 0;
-			if ($c[$i] > 255) $c[$i] = 255;
-		}
-
-		return $c;
-	}
-
-	protected function op_number_color($op, $lft, $rgt) {
-		if ($op == '+' || $op == '*') {
-			return $this->op_color_number($op, $rgt, $lft);
-		}
-	}
-
-	protected function op_color_number($op, $lft, $rgt) {
-		if ($rgt[0] == '%') $rgt[1] /= 100;
-
-		return $this->op_color_color($op, $lft,
-			array_fill(1, count($lft) - 1, $rgt[1]));
-	}
-
-	protected function op_color_color($op, $left, $right) {
-		$out = array('color');
-		$max = count($left) > count($right) ? count($left) : count($right);
-		foreach (range(1, $max - 1) as $i) {
-			$lval = isset($left[$i]) ? $left[$i] : 0;
-			$rval = isset($right[$i]) ? $right[$i] : 0;
-			switch ($op) {
-			case '+':
-				$out[] = $lval + $rval;
-				break;
-			case '-':
-				$out[] = $lval - $rval;
-				break;
-			case '*':
-				$out[] = $lval * $rval;
-				break;
-			case '%':
-				$out[] = $lval % $rval;
-				break;
-			case '/':
-				if ($rval == 0) $this->throwError("evaluate error: can't divide by zero");
-				$out[] = $lval / $rval;
-				break;
-			default:
-				$this->throwError('evaluate error: color op number failed on op '.$op);
-			}
-		}
-		return $this->fixColor($out);
-	}
-
-	function lib_red($color){
-		$color = $this->coerceColor($color);
-		if (is_null($color)) {
-			$this->throwError('color expected for red()');
-		}
-
-		return $color[1];
-	}
-
-	function lib_green($color){
-		$color = $this->coerceColor($color);
-		if (is_null($color)) {
-			$this->throwError('color expected for green()');
-		}
-
-		return $color[2];
-	}
-
-	function lib_blue($color){
-		$color = $this->coerceColor($color);
-		if (is_null($color)) {
-			$this->throwError('color expected for blue()');
-		}
-
-		return $color[3];
-	}
-
-
-	// operator on two numbers
-	protected function op_number_number($op, $left, $right) {
-		$unit = empty($left[2]) ? $right[2] : $left[2];
-
-		$value = 0;
-		switch ($op) {
-		case '+':
-			$value = $left[1] + $right[1];
-			break;
-		case '*':
-			$value = $left[1] * $right[1];
-			break;
-		case '-':
-			$value = $left[1] - $right[1];
-			break;
-		case '%':
-			$value = $left[1] % $right[1];
-			break;
-		case '/':
-			if ($right[1] == 0) $this->throwError('parse error: divide by zero');
-			$value = $left[1] / $right[1];
-			break;
-		case '<':
-			return $this->toBool($left[1] < $right[1]);
-		case '>':
-			return $this->toBool($left[1] > $right[1]);
-		case '>=':
-			return $this->toBool($left[1] >= $right[1]);
-		case '=<':
-			return $this->toBool($left[1] <= $right[1]);
-		default:
-			$this->throwError('parse error: unknown number operator: '.$op);
-		}
-
-		return array("number", $value, $unit);
-	}
-
-
-	/* environment functions */
-
-	protected function makeOutputBlock($type, $selectors = null) {
-		$b = new stdclass;
-		$b->lines = array();
-		$b->children = array();
-		$b->selectors = $selectors;
-		$b->type = $type;
-		$b->parent = $this->scope;
-		return $b;
-	}
-
-	// the state of execution
-	protected function pushEnv($block = null) {
-		$e = new stdclass;
-		$e->parent = $this->env;
-		$e->store = array();
-		$e->block = $block;
-
-		$this->env = $e;
-		return $e;
-	}
-
-	// pop something off the stack
-	protected function popEnv() {
-		$old = $this->env;
-		$this->env = $this->env->parent;
-		return $old;
-	}
-
-	// set something in the current env
-	protected function set($name, $value) {
-		$this->env->store[$name] = $value;
-	}
-
-
-	// get the highest occurrence entry for a name
-	protected function get($name) {
-		$current = $this->env;
-
-		$isArguments = $name == $this->vPrefix . 'arguments';
-		while ($current) {
-			if ($isArguments && isset($current->arguments)) {
-				return array('list', ' ', $current->arguments);
-			}
-
-			if (isset($current->store[$name]))
-				return $current->store[$name];
-			else {
-				$current = isset($current->storeParent) ?
-					$current->storeParent : $current->parent;
-			}
-		}
-
-		$this->throwError("variable $name is undefined");
-	}
-
-	// inject array of unparsed strings into environment as variables
-	protected function injectVariables($args) {
-		$this->pushEnv();
-		$parser = new lessc_parser($this, __METHOD__);
-		foreach ($args as $name => $strValue) {
-			if ($name{0} != '@') $name = '@'.$name;
-			$parser->count = 0;
-			$parser->buffer = (string)$strValue;
-			if (!$parser->propertyValue($value)) {
-				throw new Exception("failed to parse passed in variable $name: $strValue");
-			}
-
-			$this->set($name, $value);
-		}
-	}
-
-	/**
-	 * Initialize any static state, can initialize parser for a file
-	 * $opts isn't used yet
-	 */
-	public function __construct($fname = null) {
-		if ($fname !== null) {
-			// used for deprecated parse method
-			$this->_parseFile = $fname;
-		}
-	}
-
-	public function compile($string, $name = null) {
-		$locale = setlocale(LC_NUMERIC, 0);
-		setlocale(LC_NUMERIC, "C");
-
-		$this->parser = $this->makeParser($name);
-		$root = $this->parser->parse($string);
-
-		$this->env = null;
-		$this->scope = null;
-
-		$this->formatter = $this->newFormatter();
-
-		if (!empty($this->registeredVars)) {
-			$this->injectVariables($this->registeredVars);
-		}
-
-		$this->sourceParser = $this->parser; // used for error messages
-		$this->compileBlock($root);
-
-		ob_start();
-		$this->formatter->block($this->scope);
-		$out = ob_get_clean();
-		setlocale(LC_NUMERIC, $locale);
-		return $out;
-	}
-
-	public function compileFile($fname, $outFname = null) {
-		if (!is_readable($fname)) {
-			throw new Exception('load error: failed to find '.$fname);
-		}
-
-		$pi = pathinfo($fname);
-
-		$oldImport = $this->importDir;
-
-		$this->importDir = (array)$this->importDir;
-		$this->importDir[] = $pi['dirname'].'/';
-
-		$this->addParsedFile($fname);
-
-		$out = $this->compile(file_get_contents($fname), $fname);
-
-		$this->importDir = $oldImport;
-
-		if ($outFname !== null) {
-			return file_put_contents($outFname, $out);
-		}
-
-		return $out;
-	}
-
-	// compile only if changed input has changed or output doesn't exist
-	public function checkedCompile($in, $out) {
-		if (!is_file($out) || filemtime($in) > filemtime($out)) {
-			$this->compileFile($in, $out);
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Execute lessphp on a .less file or a lessphp cache structure
-	 *
-	 * The lessphp cache structure contains information about a specific
-	 * less file having been parsed. It can be used as a hint for future
-	 * calls to determine whether or not a rebuild is required.
-	 *
-	 * The cache structure contains two important keys that may be used
-	 * externally:
-	 *
-	 * compiled: The final compiled CSS
-	 * updated: The time (in seconds) the CSS was last compiled
-	 *
-	 * The cache structure is a plain-ol' PHP associative array and can
-	 * be serialized and unserialized without a hitch.
-	 *
-	 * @param mixed $in Input
-	 * @param bool $force Force rebuild?
-	 * @return array lessphp cache structure
-	 */
-	public function cachedCompile($in, $force = false) {
-		// assume no root
-		$root = null;
-
-		if (is_string($in)) {
-			$root = $in;
-		} elseif (is_array($in) and isset($in['root'])) {
-			if ($force or ! isset($in['files'])) {
-				// If we are forcing a recompile or if for some reason the
-				// structure does not contain any file information we should
-				// specify the root to trigger a rebuild.
-				$root = $in['root'];
-			} elseif (isset($in['files']) and is_array($in['files'])) {
-				foreach ($in['files'] as $fname => $ftime ) {
-					if (!file_exists($fname) or filemtime($fname) > $ftime) {
-						// One of the files we knew about previously has changed
-						// so we should look at our incoming root again.
-						$root = $in['root'];
-						break;
-					}
-				}
-			}
-		} else {
-			// TODO: Throw an exception? We got neither a string nor something
-			// that looks like a compatible lessphp cache structure.
-			return null;
-		}
-
-		if ($root !== null) {
-			// If we have a root value which means we should rebuild.
-			$out = array();
-			$out['root'] = $root;
-			$out['compiled'] = $this->compileFile($root);
-			$out['files'] = $this->allParsedFiles();
-			$out['updated'] = time();
-			return $out;
-		} else {
-			// No changes, pass back the structure
-			// we were given initially.
-			return $in;
-		}
-
-	}
-
-	// parse and compile buffer
-	// This is deprecated
-	public function parse($str = null, $initialVariables = null) {
-		if (is_array($str)) {
-			$initialVariables = $str;
-			$str = null;
-		}
-
-		$oldVars = $this->registeredVars;
-		if ($initialVariables !== null) {
-			$this->setVariables($initialVariables);
-		}
-
-		if ($str == null) {
-			if (empty($this->_parseFile)) {
-				throw new exception("nothing to parse");
-			}
-
-			$out = $this->compileFile($this->_parseFile);
-		} else {
-			$out = $this->compile($str);
-		}
-
-		$this->registeredVars = $oldVars;
-		return $out;
-	}
-
-	protected function makeParser($name) {
-		$parser = new lessc_parser($this, $name);
-		$parser->writeComments = $this->preserveComments;
-
-		return $parser;
-	}
-
-	public function setFormatter($name) {
-		$this->formatterName = $name;
-	}
-
-	protected function newFormatter() {
-		$className = "lessc_formatter_lessjs";
-		if (!empty($this->formatterName)) {
-			if (!is_string($this->formatterName))
-				return $this->formatterName;
-			$className = "lessc_formatter_$this->formatterName";
-		}
-
-		return new $className;
-	}
-
-	public function setPreserveComments($preserve) {
-		$this->preserveComments = $preserve;
-	}
-
-	public function registerFunction($name, $func) {
-		$this->libFunctions[$name] = $func;
-	}
-
-	public function unregisterFunction($name) {
-		unset($this->libFunctions[$name]);
-	}
-
-	public function setVariables($variables) {
-		$this->registeredVars = array_merge($this->registeredVars, $variables);
-	}
-
-	public function unsetVariable($name) {
-		unset($this->registeredVars[$name]);
-	}
-
-	public function setImportDir($dirs) {
-		$this->importDir = (array)$dirs;
-	}
-
-	public function addImportDir($dir) {
-		$this->importDir = (array)$this->importDir;
-		$this->importDir[] = $dir;
-	}
-
-	public function allParsedFiles() {
-		return $this->allParsedFiles;
-	}
-
-	public function addParsedFile($file) {
-		$this->allParsedFiles[realpath($file)] = filemtime($file);
-	}
-
-	/**
-	 * Uses the current value of $this->count to show line and line number
-	 */
-	public function throwError($msg = null) {
-		if ($this->sourceLoc >= 0) {
-			$this->sourceParser->throwError($msg, $this->sourceLoc);
-		}
-		throw new exception($msg);
-	}
-
-	// compile file $in to file $out if $in is newer than $out
-	// returns true when it compiles, false otherwise
-	public static function ccompile($in, $out, $less = null) {
-		if ($less === null) {
-			$less = new self;
-		}
-		return $less->checkedCompile($in, $out);
-	}
-
-	public static function cexecute($in, $force = false, $less = null) {
-		if ($less === null) {
-			$less = new self;
-		}
-		return $less->cachedCompile($in, $force);
-	}
-
-	static protected $cssColors = array(
-		'aliceblue' => '240,248,255',
-		'antiquewhite' => '250,235,215',
-		'aqua' => '0,255,255',
-		'aquamarine' => '127,255,212',
-		'azure' => '240,255,255',
-		'beige' => '245,245,220',
-		'bisque' => '255,228,196',
-		'black' => '0,0,0',
-		'blanchedalmond' => '255,235,205',
-		'blue' => '0,0,255',
-		'blueviolet' => '138,43,226',
-		'brown' => '165,42,42',
-		'burlywood' => '222,184,135',
-		'cadetblue' => '95,158,160',
-		'chartreuse' => '127,255,0',
-		'chocolate' => '210,105,30',
-		'coral' => '255,127,80',
-		'cornflowerblue' => '100,149,237',
-		'cornsilk' => '255,248,220',
-		'crimson' => '220,20,60',
-		'cyan' => '0,255,255',
-		'darkblue' => '0,0,139',
-		'darkcyan' => '0,139,139',
-		'darkgoldenrod' => '184,134,11',
-		'darkgray' => '169,169,169',
-		'darkgreen' => '0,100,0',
-		'darkgrey' => '169,169,169',
-		'darkkhaki' => '189,183,107',
-		'darkmagenta' => '139,0,139',
-		'darkolivegreen' => '85,107,47',
-		'darkorange' => '255,140,0',
-		'darkorchid' => '153,50,204',
-		'darkred' => '139,0,0',
-		'darksalmon' => '233,150,122',
-		'darkseagreen' => '143,188,143',
-		'darkslateblue' => '72,61,139',
-		'darkslategray' => '47,79,79',
-		'darkslategrey' => '47,79,79',
-		'darkturquoise' => '0,206,209',
-		'darkviolet' => '148,0,211',
-		'deeppink' => '255,20,147',
-		'deepskyblue' => '0,191,255',
-		'dimgray' => '105,105,105',
-		'dimgrey' => '105,105,105',
-		'dodgerblue' => '30,144,255',
-		'firebrick' => '178,34,34',
-		'floralwhite' => '255,250,240',
-		'forestgreen' => '34,139,34',
-		'fuchsia' => '255,0,255',
-		'gainsboro' => '220,220,220',
-		'ghostwhite' => '248,248,255',
-		'gold' => '255,215,0',
-		'goldenrod' => '218,165,32',
-		'gray' => '128,128,128',
-		'green' => '0,128,0',
-		'greenyellow' => '173,255,47',
-		'grey' => '128,128,128',
-		'honeydew' => '240,255,240',
-		'hotpink' => '255,105,180',
-		'indianred' => '205,92,92',
-		'indigo' => '75,0,130',
-		'ivory' => '255,255,240',
-		'khaki' => '240,230,140',
-		'lavender' => '230,230,250',
-		'lavenderblush' => '255,240,245',
-		'lawngreen' => '124,252,0',
-		'lemonchiffon' => '255,250,205',
-		'lightblue' => '173,216,230',
-		'lightcoral' => '240,128,128',
-		'lightcyan' => '224,255,255',
-		'lightgoldenrodyellow' => '250,250,210',
-		'lightgray' => '211,211,211',
-		'lightgreen' => '144,238,144',
-		'lightgrey' => '211,211,211',
-		'lightpink' => '255,182,193',
-		'lightsalmon' => '255,160,122',
-		'lightseagreen' => '32,178,170',
-		'lightskyblue' => '135,206,250',
-		'lightslategray' => '119,136,153',
-		'lightslategrey' => '119,136,153',
-		'lightsteelblue' => '176,196,222',
-		'lightyellow' => '255,255,224',
-		'lime' => '0,255,0',
-		'limegreen' => '50,205,50',
-		'linen' => '250,240,230',
-		'magenta' => '255,0,255',
-		'maroon' => '128,0,0',
-		'mediumaquamarine' => '102,205,170',
-		'mediumblue' => '0,0,205',
-		'mediumorchid' => '186,85,211',
-		'mediumpurple' => '147,112,219',
-		'mediumseagreen' => '60,179,113',
-		'mediumslateblue' => '123,104,238',
-		'mediumspringgreen' => '0,250,154',
-		'mediumturquoise' => '72,209,204',
-		'mediumvioletred' => '199,21,133',
-		'midnightblue' => '25,25,112',
-		'mintcream' => '245,255,250',
-		'mistyrose' => '255,228,225',
-		'moccasin' => '255,228,181',
-		'navajowhite' => '255,222,173',
-		'navy' => '0,0,128',
-		'oldlace' => '253,245,230',
-		'olive' => '128,128,0',
-		'olivedrab' => '107,142,35',
-		'orange' => '255,165,0',
-		'orangered' => '255,69,0',
-		'orchid' => '218,112,214',
-		'palegoldenrod' => '238,232,170',
-		'palegreen' => '152,251,152',
-		'paleturquoise' => '175,238,238',
-		'palevioletred' => '219,112,147',
-		'papayawhip' => '255,239,213',
-		'peachpuff' => '255,218,185',
-		'peru' => '205,133,63',
-		'pink' => '255,192,203',
-		'plum' => '221,160,221',
-		'powderblue' => '176,224,230',
-		'purple' => '128,0,128',
-		'red' => '255,0,0',
-		'rosybrown' => '188,143,143',
-		'royalblue' => '65,105,225',
-		'saddlebrown' => '139,69,19',
-		'salmon' => '250,128,114',
-		'sandybrown' => '244,164,96',
-		'seagreen' => '46,139,87',
-		'seashell' => '255,245,238',
-		'sienna' => '160,82,45',
-		'silver' => '192,192,192',
-		'skyblue' => '135,206,235',
-		'slateblue' => '106,90,205',
-		'slategray' => '112,128,144',
-		'slategrey' => '112,128,144',
-		'snow' => '255,250,250',
-		'springgreen' => '0,255,127',
-		'steelblue' => '70,130,180',
-		'tan' => '210,180,140',
-		'teal' => '0,128,128',
-		'thistle' => '216,191,216',
-		'tomato' => '255,99,71',
-		'transparent' => '0,0,0,0',
-		'turquoise' => '64,224,208',
-		'violet' => '238,130,238',
-		'wheat' => '245,222,179',
-		'white' => '255,255,255',
-		'whitesmoke' => '245,245,245',
-		'yellow' => '255,255,0',
-		'yellowgreen' => '154,205,50'
-	);
-}
-
-// responsible for taking a string of LESS code and converting it into a
-// syntax tree
-class lessc_parser {
-	static protected $nextBlockId = 0; // used to uniquely identify blocks
-
-	static protected $precedence = array(
-		'=<' => 0,
-		'>=' => 0,
-		'=' => 0,
-		'<' => 0,
-		'>' => 0,
-
-		'+' => 1,
-		'-' => 1,
-		'*' => 2,
-		'/' => 2,
-		'%' => 2,
-	);
-
-	static protected $whitePattern;
-	static protected $commentMulti;
-
-	static protected $commentSingle = "//";
-	static protected $commentMultiLeft = "/*";
-	static protected $commentMultiRight = "*/";
-
-	// regex string to match any of the operators
-	static protected $operatorString;
-
-	// these properties will supress division unless it's inside parenthases
-	static protected $supressDivisionProps =
-		array('/border-radius$/i', '/^font$/i');
-
-	protected $blockDirectives = array("font-face", "keyframes", "page", "-moz-document", "viewport", "-moz-viewport", "-o-viewport", "-ms-viewport");
-	protected $lineDirectives = array("charset");
-
-	/**
-	 * if we are in parens we can be more liberal with whitespace around
-	 * operators because it must evaluate to a single value and thus is less
-	 * ambiguous.
-	 *
-	 * Consider:
-	 *     property1: 10 -5; // is two numbers, 10 and -5
-	 *     property2: (10 -5); // should evaluate to 5
-	 */
-	protected $inParens = false;
-
-	// caches preg escaped literals
-	static protected $literalCache = array();
-
-	public function __construct($lessc, $sourceName = null) {
-		$this->eatWhiteDefault = true;
-		// reference to less needed for vPrefix, mPrefix, and parentSelector
-		$this->lessc = $lessc;
-
-		$this->sourceName = $sourceName; // name used for error messages
-
-		$this->writeComments = false;
-
-		if (!self::$operatorString) {
-			self::$operatorString =
-				'('.implode('|', array_map(array('lessc', 'preg_quote'),
-					array_keys(self::$precedence))).')';
-
-			$commentSingle = lessc::preg_quote(self::$commentSingle);
-			$commentMultiLeft = lessc::preg_quote(self::$commentMultiLeft);
-			$commentMultiRight = lessc::preg_quote(self::$commentMultiRight);
-
-			self::$commentMulti = $commentMultiLeft.'.*?'.$commentMultiRight;
-			self::$whitePattern = '/'.$commentSingle.'[^\n]*\s*|('.self::$commentMulti.')\s*|\s+/Ais';
-		}
-	}
-
-	public function parse($buffer) {
-		$this->count = 0;
-		$this->line = 1;
-
-		$this->env = null; // block stack
-		$this->buffer = $this->writeComments ? $buffer : $this->removeComments($buffer);
-		$this->pushSpecialBlock("root");
-		$this->eatWhiteDefault = true;
-		$this->seenComments = array();
-
-		// trim whitespace on head
-		// if (preg_match('/^\s+/', $this->buffer, $m)) {
-		// 	$this->line += substr_count($m[0], "\n");
-		// 	$this->buffer = ltrim($this->buffer);
-		// }
-		$this->whitespace();
-
-		// parse the entire file
-		while (false !== $this->parseChunk());
-
-		if ($this->count != strlen($this->buffer))
-			$this->throwError();
-
-		// TODO report where the block was opened
-		if ( !property_exists($this->env, 'parent') || !is_null($this->env->parent) )
-			throw new exception('parse error: unclosed block');
-
-		return $this->env;
-	}
-
-	/**
-	 * Parse a single chunk off the head of the buffer and append it to the
-	 * current parse environment.
-	 * Returns false when the buffer is empty, or when there is an error.
-	 *
-	 * This function is called repeatedly until the entire document is
-	 * parsed.
-	 *
-	 * This parser is most similar to a recursive descent parser. Single
-	 * functions represent discrete grammatical rules for the language, and
-	 * they are able to capture the text that represents those rules.
-	 *
-	 * Consider the function lessc::keyword(). (all parse functions are
-	 * structured the same)
-	 *
-	 * The function takes a single reference argument. When calling the
-	 * function it will attempt to match a keyword on the head of the buffer.
-	 * If it is successful, it will place the keyword in the referenced
-	 * argument, advance the position in the buffer, and return true. If it
-	 * fails then it won't advance the buffer and it will return false.
-	 *
-	 * All of these parse functions are powered by lessc::match(), which behaves
-	 * the same way, but takes a literal regular expression. Sometimes it is
-	 * more convenient to use match instead of creating a new function.
-	 *
-	 * Because of the format of the functions, to parse an entire string of
-	 * grammatical rules, you can chain them together using &&.
-	 *
-	 * But, if some of the rules in the chain succeed before one fails, then
-	 * the buffer position will be left at an invalid state. In order to
-	 * avoid this, lessc::seek() is used to remember and set buffer positions.
-	 *
-	 * Before parsing a chain, use $s = $this->seek() to remember the current
-	 * position into $s. Then if a chain fails, use $this->seek($s) to
-	 * go back where we started.
-	 */
-	protected function parseChunk() {
-		if (empty($this->buffer)) return false;
-		$s = $this->seek();
-
-		if ($this->whitespace()) {
-			return true;
-		}
-
-		// setting a property
-		if ($this->keyword($key) && $this->assign() &&
-			$this->propertyValue($value, $key) && $this->end())
-		{
-			$this->append(array('assign', $key, $value), $s);
-			return true;
-		} else {
-			$this->seek($s);
-		}
-
-
-		// look for special css blocks
-		if ($this->literal('@', false)) {
-			$this->count--;
-
-			// media
-			if ($this->literal('@media')) {
-				if (($this->mediaQueryList($mediaQueries) || true)
-					&& $this->literal('{'))
-				{
-					$media = $this->pushSpecialBlock("media");
-					$media->queries = is_null($mediaQueries) ? array() : $mediaQueries;
-					return true;
-				} else {
-					$this->seek($s);
-					return false;
-				}
-			}
-
-			if ($this->literal("@", false) && $this->keyword($dirName)) {
-				if ($this->isDirective($dirName, $this->blockDirectives)) {
-					if (($this->openString("{", $dirValue, null, array(";")) || true) &&
-						$this->literal("{"))
-					{
-						$dir = $this->pushSpecialBlock("directive");
-						$dir->name = $dirName;
-						if (isset($dirValue)) $dir->value = $dirValue;
-						return true;
-					}
-				} elseif ($this->isDirective($dirName, $this->lineDirectives)) {
-					if ($this->propertyValue($dirValue) && $this->end()) {
-						$this->append(array("directive", $dirName, $dirValue));
-						return true;
-					}
-				}
-			}
-
-			$this->seek($s);
-		}
-
-		// setting a variable
-		if ($this->variable($var) && $this->assign() &&
-			$this->propertyValue($value) && $this->end())
-		{
-			$this->append(array('assign', $var, $value), $s);
-			return true;
-		} else {
-			$this->seek($s);
-		}
-
-		if ($this->import($importValue)) {
-			$this->append($importValue, $s);
-			return true;
-		}
-
-		// opening parametric mixin
-		if ($this->tag($tag, true) && $this->argumentDef($args, $isVararg) &&
-			($this->guards($guards) || true) &&
-			$this->literal('{'))
-		{
-			$block = $this->pushBlock($this->fixTags(array($tag)));
-			$block->args = $args;
-			$block->isVararg = $isVararg;
-			if (!empty($guards)) $block->guards = $guards;
-			return true;
-		} else {
-			$this->seek($s);
-		}
-
-		// opening a simple block
-		if ($this->tags($tags) && $this->literal('{', false)) {
-			$tags = $this->fixTags($tags);
-			$this->pushBlock($tags);
-			return true;
-		} else {
-			$this->seek($s);
-		}
-
-		// closing a block
-		if ($this->literal('}', false)) {
-			try {
-				$block = $this->pop();
-			} catch (exception $e) {
-				$this->seek($s);
-				$this->throwError($e->getMessage());
-			}
-
-			$hidden = false;
-			if (is_null($block->type)) {
-				$hidden = true;
-				if (!isset($block->args)) {
-					foreach ($block->tags as $tag) {
-						if (!is_string($tag) || $tag{0} != $this->lessc->mPrefix) {
-							$hidden = false;
-							break;
-						}
-					}
-				}
-
-				foreach ($block->tags as $tag) {
-					if (is_string($tag)) {
-						$this->env->children[$tag][] = $block;
-					}
-				}
-			}
-
-			if (!$hidden) {
-				$this->append(array('block', $block), $s);
-			}
-
-			// this is done here so comments aren't bundled into he block that
-			// was just closed
-			$this->whitespace();
-			return true;
-		}
-
-		// mixin
-		if ($this->mixinTags($tags) &&
-			($this->argumentDef($argv, $isVararg) || true) &&
-			($this->keyword($suffix) || true) && $this->end())
-		{
-			$tags = $this->fixTags($tags);
-			$this->append(array('mixin', $tags, $argv, $suffix), $s);
-			return true;
-		} else {
-			$this->seek($s);
-		}
-
-		// spare ;
-		if ($this->literal(';')) return true;
-
-		return false; // got nothing, throw error
-	}
-
-	protected function isDirective($dirname, $directives) {
-		// TODO: cache pattern in parser
-		$pattern = implode("|",
-			array_map(array("lessc", "preg_quote"), $directives));
-		$pattern = '/^(-[a-z-]+-)?(' . $pattern . ')$/i';
-
-		return preg_match($pattern, $dirname);
-	}
-
-	protected function fixTags($tags) {
-		// move @ tags out of variable namespace
-		foreach ($tags as &$tag) {
-			if ($tag{0} == $this->lessc->vPrefix)
-				$tag[0] = $this->lessc->mPrefix;
-		}
-		return $tags;
-	}
-
-	// a list of expressions
-	protected function expressionList(&$exps) {
-		$values = array();
-
-		while ($this->expression($exp)) {
-			$values[] = $exp;
-		}
-
-		if (count($values) == 0) return false;
-
-		$exps = lessc::compressList($values, ' ');
-		return true;
-	}
-
-	/**
-	 * Attempt to consume an expression.
-	 * @link http://en.wikipedia.org/wiki/Operator-precedence_parser#Pseudo-code
-	 */
-	protected function expression(&$out) {
-		if ($this->value($lhs)) {
-			$out = $this->expHelper($lhs, 0);
-
-			// look for / shorthand
-			if (!empty($this->env->supressedDivision)) {
-				unset($this->env->supressedDivision);
-				$s = $this->seek();
-				if ($this->literal("/") && $this->value($rhs)) {
-					$out = array("list", "",
-						array($out, array("keyword", "/"), $rhs));
-				} else {
-					$this->seek($s);
-				}
-			}
-
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * recursively parse infix equation with $lhs at precedence $minP
-	 */
-	protected function expHelper($lhs, $minP) {
-		$this->inExp = true;
-		$ss = $this->seek();
-
-		while (true) {
-			$whiteBefore = isset($this->buffer[$this->count - 1]) &&
-				ctype_space($this->buffer[$this->count - 1]);
-
-			// If there is whitespace before the operator, then we require
-			// whitespace after the operator for it to be an expression
-			$needWhite = $whiteBefore && !$this->inParens;
-
-			if ($this->match(self::$operatorString.($needWhite ? '\s' : ''), $m) && self::$precedence[$m[1]] >= $minP) {
-				if (!$this->inParens && isset($this->env->currentProperty) && $m[1] == "/" && empty($this->env->supressedDivision)) {
-					foreach (self::$supressDivisionProps as $pattern) {
-						if (preg_match($pattern, $this->env->currentProperty)) {
-							$this->env->supressedDivision = true;
-							break 2;
-						}
-					}
-				}
-
-
-				$whiteAfter = isset($this->buffer[$this->count - 1]) &&
-					ctype_space($this->buffer[$this->count - 1]);
-
-				if (!$this->value($rhs)) break;
-
-				// peek for next operator to see what to do with rhs
-				if ($this->peek(self::$operatorString, $next) && self::$precedence[$next[1]] > self::$precedence[$m[1]]) {
-					$rhs = $this->expHelper($rhs, self::$precedence[$next[1]]);
-				}
-
-				$lhs = array('expression', $m[1], $lhs, $rhs, $whiteBefore, $whiteAfter);
-				$ss = $this->seek();
-
-				continue;
-			}
-
-			break;
-		}
-
-		$this->seek($ss);
-
-		return $lhs;
-	}
-
-	// consume a list of values for a property
-	public function propertyValue(&$value, $keyName = null) {
-		$values = array();
-
-		if ($keyName !== null) $this->env->currentProperty = $keyName;
-
-		$s = null;
-		while ($this->expressionList($v)) {
-			$values[] = $v;
-			$s = $this->seek();
-			if (!$this->literal(',')) break;
-		}
-
-		if ($s) $this->seek($s);
-
-		if ($keyName !== null) unset($this->env->currentProperty);
-
-		if (count($values) == 0) return false;
-
-		$value = lessc::compressList($values, ', ');
-		return true;
-	}
-
-	protected function parenValue(&$out) {
-		$s = $this->seek();
-
-		// speed shortcut
-		if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "(") {
-			return false;
-		}
-
-		$inParens = $this->inParens;
-		if ($this->literal("(") &&
-			($this->inParens = true) && $this->expression($exp) &&
-			$this->literal(")"))
-		{
-			$out = $exp;
-			$this->inParens = $inParens;
-			return true;
-		} else {
-			$this->inParens = $inParens;
-			$this->seek($s);
-		}
-
-		return false;
-	}
-
-	// a single value
-	protected function value(&$value) {
-		$s = $this->seek();
-
-		// speed shortcut
-		if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "-") {
-			// negation
-			if ($this->literal("-", false) &&
-				(($this->variable($inner) && $inner = array("variable", $inner)) ||
-				$this->unit($inner) ||
-				$this->parenValue($inner)))
-			{
-				$value = array("unary", "-", $inner);
-				return true;
-			} else {
-				$this->seek($s);
-			}
-		}
-
-		if ($this->parenValue($value)) return true;
-		if ($this->unit($value)) return true;
-		if ($this->color($value)) return true;
-		if ($this->func($value)) return true;
-		if ($this->string($value)) return true;
-
-		if ($this->keyword($word)) {
-			$value = array('keyword', $word);
-			return true;
-		}
-
-		// try a variable
-		if ($this->variable($var)) {
-			$value = array('variable', $var);
-			return true;
-		}
-
-		// unquote string (should this work on any type?
-		if ($this->literal("~") && $this->string($str)) {
-			$value = array("escape", $str);
-			return true;
-		} else {
-			$this->seek($s);
-		}
-
-		// css hack: \0
-		if ($this->literal('\\') && $this->match('([0-9]+)', $m)) {
-			$value = array('keyword', '\\'.$m[1]);
-			return true;
-		} else {
-			$this->seek($s);
-		}
-
-		return false;
-	}
-
-	// an import statement
-	protected function import(&$out) {
-		if (!$this->literal('@import')) return false;
-
-		// @import "something.css" media;
-		// @import url("something.css") media;
-		// @import url(something.css) media;
-
-		if ($this->propertyValue($value)) {
-			$out = array("import", $value);
-			return true;
-		}
-	}
-
-	protected function mediaQueryList(&$out) {
-		if ($this->genericList($list, "mediaQuery", ",", false)) {
-			$out = $list[2];
-			return true;
-		}
-		return false;
-	}
-
-	protected function mediaQuery(&$out) {
-		$s = $this->seek();
-
-		$expressions = null;
-		$parts = array();
-
-		if (($this->literal("only") && ($only = true) || $this->literal("not") && ($not = true) || true) && $this->keyword($mediaType)) {
-			$prop = array("mediaType");
-			if (isset($only)) $prop[] = "only";
-			if (isset($not)) $prop[] = "not";
-			$prop[] = $mediaType;
-			$parts[] = $prop;
-		} else {
-			$this->seek($s);
-		}
-
-
-		if (!empty($mediaType) && !$this->literal("and")) {
-			// ~
-		} else {
-			$this->genericList($expressions, "mediaExpression", "and", false);
-			if (is_array($expressions)) $parts = array_merge($parts, $expressions[2]);
-		}
-
-		if (count($parts) == 0) {
-			$this->seek($s);
-			return false;
-		}
-
-		$out = $parts;
-		return true;
-	}
-
-	protected function mediaExpression(&$out) {
-		$s = $this->seek();
-		$value = null;
-		if ($this->literal("(") &&
-			$this->keyword($feature) &&
-			($this->literal(":") && $this->expression($value) || true) &&
-			$this->literal(")"))
-		{
-			$out = array("mediaExp", $feature);
-			if ($value) $out[] = $value;
-			return true;
-		} elseif ($this->variable($variable)) {
-			$out = array('variable', $variable);
-			return true;
-		}
-
-		$this->seek($s);
-		return false;
-	}
-
-	// an unbounded string stopped by $end
-	protected function openString($end, &$out, $nestingOpen=null, $rejectStrs = null) {
-		$oldWhite = $this->eatWhiteDefault;
-		$this->eatWhiteDefault = false;
-
-		$stop = array("'", '"', "@{", $end);
-		$stop = array_map(array("lessc", "preg_quote"), $stop);
-		// $stop[] = self::$commentMulti;
-
-		if (!is_null($rejectStrs)) {
-			$stop = array_merge($stop, $rejectStrs);
-		}
-
-		$patt = '(.*?)('.implode("|", $stop).')';
-
-		$nestingLevel = 0;
-
-		$content = array();
-		while ($this->match($patt, $m, false)) {
-			if (!empty($m[1])) {
-				$content[] = $m[1];
-				if ($nestingOpen) {
-					$nestingLevel += substr_count($m[1], $nestingOpen);
-				}
-			}
-
-			$tok = $m[2];
-
-			$this->count-= strlen($tok);
-			if ($tok == $end) {
-				if ($nestingLevel == 0) {
-					break;
-				} else {
-					$nestingLevel--;
-				}
-			}
-
-			if (($tok == "'" || $tok == '"') && $this->string($str)) {
-				$content[] = $str;
-				continue;
-			}
-
-			if ($tok == "@{" && $this->interpolation($inter)) {
-				$content[] = $inter;
-				continue;
-			}
-
-			if (!empty($rejectStrs) && in_array($tok, $rejectStrs)) {
-				break;
-			}
-
-			$content[] = $tok;
-			$this->count+= strlen($tok);
-		}
-
-		$this->eatWhiteDefault = $oldWhite;
-
-		if (count($content) == 0) return false;
-
-		// trim the end
-		if (is_string(end($content))) {
-			$content[count($content) - 1] = rtrim(end($content));
-		}
-
-		$out = array("string", "", $content);
-		return true;
-	}
-
-	protected function string(&$out) {
-		$s = $this->seek();
-		if ($this->literal('"', false)) {
-			$delim = '"';
-		} elseif ($this->literal("'", false)) {
-			$delim = "'";
-		} else {
-			return false;
-		}
-
-		$content = array();
-
-		// look for either ending delim , escape, or string interpolation
-		$patt = '([^\n]*?)(@\{|\\\\|' .
-			lessc::preg_quote($delim).')';
-
-		$oldWhite = $this->eatWhiteDefault;
-		$this->eatWhiteDefault = false;
-
-		while ($this->match($patt, $m, false)) {
-			$content[] = $m[1];
-			if ($m[2] == "@{") {
-				$this->count -= strlen($m[2]);
-				if ($this->interpolation($inter, false)) {
-					$content[] = $inter;
-				} else {
-					$this->count += strlen($m[2]);
-					$content[] = "@{"; // ignore it
-				}
-			} elseif ($m[2] == '\\') {
-				$content[] = $m[2];
-				if ($this->literal($delim, false)) {
-					$content[] = $delim;
-				}
-			} else {
-				$this->count -= strlen($delim);
-				break; // delim
-			}
-		}
-
-		$this->eatWhiteDefault = $oldWhite;
-
-		if ($this->literal($delim)) {
-			$out = array("string", $delim, $content);
-			return true;
-		}
-
-		$this->seek($s);
-		return false;
-	}
-
-	protected function interpolation(&$out) {
-		$oldWhite = $this->eatWhiteDefault;
-		$this->eatWhiteDefault = true;
-
-		$s = $this->seek();
-		if ($this->literal("@{") &&
-			$this->openString("}", $interp, null, array("'", '"', ";")) &&
-			$this->literal("}", false))
-		{
-			$out = array("interpolate", $interp);
-			$this->eatWhiteDefault = $oldWhite;
-			if ($this->eatWhiteDefault) $this->whitespace();
-			return true;
-		}
-
-		$this->eatWhiteDefault = $oldWhite;
-		$this->seek($s);
-		return false;
-	}
-
-	protected function unit(&$unit) {
-		// speed shortcut
-		if (isset($this->buffer[$this->count])) {
-			$char = $this->buffer[$this->count];
-			if (!ctype_digit($char) && $char != ".") return false;
-		}
-
-		if ($this->match('([0-9]+(?:\.[0-9]*)?|\.[0-9]+)([%a-zA-Z]+)?', $m)) {
-			$unit = array("number", $m[1], empty($m[2]) ? "" : $m[2]);
-			return true;
-		}
-		return false;
-	}
-
-	// a # color
-	protected function color(&$out) {
-		if ($this->match('(#(?:[0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{3}))', $m)) {
-			if (strlen($m[1]) > 7) {
-				$out = array("string", "", array($m[1]));
-			} else {
-				$out = array("raw_color", $m[1]);
-			}
-			return true;
-		}
-
-		return false;
-	}
-
-	// consume an argument definition list surrounded by ()
-	// each argument is a variable name with optional value
-	// or at the end a ... or a variable named followed by ...
-	// arguments are separated by , unless a ; is in the list, then ; is the
-	// delimiter.
-	protected function argumentDef(&$args, &$isVararg) {
-		$s = $this->seek();
-		if (!$this->literal('(')) return false;
-
-		$values = array();
-		$delim = ",";
-		$method = "expressionList";
-
-		$isVararg = false;
-		while (true) {
-			if ($this->literal("...")) {
-				$isVararg = true;
-				break;
-			}
-
-			if ($this->$method($value)) {
-				if ($value[0] == "variable") {
-					$arg = array("arg", $value[1]);
-					$ss = $this->seek();
-
-					if ($this->assign() && $this->$method($rhs)) {
-						$arg[] = $rhs;
-					} else {
-						$this->seek($ss);
-						if ($this->literal("...")) {
-							$arg[0] = "rest";
-							$isVararg = true;
-						}
-					}
-
-					$values[] = $arg;
-					if ($isVararg) break;
-					continue;
-				} else {
-					$values[] = array("lit", $value);
-				}
-			}
-
-
-			if (!$this->literal($delim)) {
-				if ($delim == "," && $this->literal(";")) {
-					// found new delim, convert existing args
-					$delim = ";";
-					$method = "propertyValue";
-
-					// transform arg list
-					if (isset($values[1])) { // 2 items
-						$newList = array();
-						foreach ($values as $i => $arg) {
-							switch($arg[0]) {
-							case "arg":
-								if ($i) {
-									$this->throwError("Cannot mix ; and , as delimiter types");
-								}
-								$newList[] = $arg[2];
-								break;
-							case "lit":
-								$newList[] = $arg[1];
-								break;
-							case "rest":
-								$this->throwError("Unexpected rest before semicolon");
-							}
-						}
-
-						$newList = array("list", ", ", $newList);
-
-						switch ($values[0][0]) {
-						case "arg":
-							$newArg = array("arg", $values[0][1], $newList);
-							break;
-						case "lit":
-							$newArg = array("lit", $newList);
-							break;
-						}
-
-					} elseif ($values) { // 1 item
-						$newArg = $values[0];
-					}
-
-					if ($newArg) {
-						$values = array($newArg);
-					}
-				} else {
-					break;
-				}
-			}
-		}
-
-		if (!$this->literal(')')) {
-			$this->seek($s);
-			return false;
-		}
-
-		$args = $values;
-
-		return true;
-	}
-
-	// consume a list of tags
-	// this accepts a hanging delimiter
-	protected function tags(&$tags, $simple = false, $delim = ',') {
-		$tags = array();
-		while ($this->tag($tt, $simple)) {
-			$tags[] = $tt;
-			if (!$this->literal($delim)) break;
-		}
-		if (count($tags) == 0) return false;
-
-		return true;
-	}
-
-	// list of tags of specifying mixin path
-	// optionally separated by > (lazy, accepts extra >)
-	protected function mixinTags(&$tags) {
-		$tags = array();
-		while ($this->tag($tt, true)) {
-			$tags[] = $tt;
-			$this->literal(">");
-		}
-
-		if (count($tags) == 0) return false;
-
-		return true;
-	}
-
-	// a bracketed value (contained within in a tag definition)
-	protected function tagBracket(&$parts, &$hasExpression) {
-		// speed shortcut
-		if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "[") {
-			return false;
-		}
-
-		$s = $this->seek();
-
-		$hasInterpolation = false;
-
-		if ($this->literal("[", false)) {
-			$attrParts = array("[");
-			// keyword, string, operator
-			while (true) {
-				if ($this->literal("]", false)) {
-					$this->count--;
-					break; // get out early
-				}
-
-				if ($this->match('\s+', $m)) {
-					$attrParts[] = " ";
-					continue;
-				}
-				if ($this->string($str)) {
-					// escape parent selector, (yuck)
-					foreach ($str[2] as &$chunk) {
-						$chunk = str_replace($this->lessc->parentSelector, "$&$", $chunk);
-					}
-
-					$attrParts[] = $str;
-					$hasInterpolation = true;
-					continue;
-				}
-
-				if ($this->keyword($word)) {
-					$attrParts[] = $word;
-					continue;
-				}
-
-				if ($this->interpolation($inter, false)) {
-					$attrParts[] = $inter;
-					$hasInterpolation = true;
-					continue;
-				}
-
-				// operator, handles attr namespace too
-				if ($this->match('[|-~\$\*\^=]+', $m)) {
-					$attrParts[] = $m[0];
-					continue;
-				}
-
-				break;
-			}
-
-			if ($this->literal("]", false)) {
-				$attrParts[] = "]";
-				foreach ($attrParts as $part) {
-					$parts[] = $part;
-				}
-				$hasExpression = $hasExpression || $hasInterpolation;
-				return true;
-			}
-			$this->seek($s);
-		}
-
-		$this->seek($s);
-		return false;
-	}
-
-	// a space separated list of selectors
-	protected function tag(&$tag, $simple = false) {
-		if ($simple)
-			$chars = '^@,:;{}\][>\(\) "\'';
-		else
-			$chars = '^@,;{}["\'';
-
-		$s = $this->seek();
-
-		$hasExpression = false;
-		$parts = array();
-		while ($this->tagBracket($parts, $hasExpression));
-
-		$oldWhite = $this->eatWhiteDefault;
-		$this->eatWhiteDefault = false;
-
-		while (true) {
-			if ($this->match('(['.$chars.'0-9]['.$chars.']*)', $m)) {
-				$parts[] = $m[1];
-				if ($simple) break;
-
-				while ($this->tagBracket($parts, $hasExpression));
-				continue;
-			}
-
-			if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "@") {
-				if ($this->interpolation($interp)) {
-					$hasExpression = true;
-					$interp[2] = true; // don't unescape
-					$parts[] = $interp;
-					continue;
-				}
-
-				if ($this->literal("@")) {
-					$parts[] = "@";
-					continue;
-				}
-			}
-
-			if ($this->unit($unit)) { // for keyframes
-				$parts[] = $unit[1];
-				$parts[] = $unit[2];
-				continue;
-			}
-
-			break;
-		}
-
-		$this->eatWhiteDefault = $oldWhite;
-		if (!$parts) {
-			$this->seek($s);
-			return false;
-		}
-
-		if ($hasExpression) {
-			$tag = array("exp", array("string", "", $parts));
-		} else {
-			$tag = trim(implode($parts));
-		}
-
-		$this->whitespace();
-		return true;
-	}
-
-	// a css function
-	protected function func(&$func) {
-		$s = $this->seek();
-
-		if ($this->match('(%|[\w\-_][\w\-_:\.]+|[\w_])', $m) && $this->literal('(')) {
-			$fname = $m[1];
-
-			$sPreArgs = $this->seek();
-
-			$args = array();
-			while (true) {
-				$ss = $this->seek();
-				// this ugly nonsense is for ie filter properties
-				if ($this->keyword($name) && $this->literal('=') && $this->expressionList($value)) {
-					$args[] = array("string", "", array($name, "=", $value));
-				} else {
-					$this->seek($ss);
-					if ($this->expressionList($value)) {
-						$args[] = $value;
-					}
-				}
-
-				if (!$this->literal(',')) break;
-			}
-			$args = array('list', ',', $args);
-
-			if ($this->literal(')')) {
-				$func = array('function', $fname, $args);
-				return true;
-			} elseif ($fname == 'url') {
-				// couldn't parse and in url? treat as string
-				$this->seek($sPreArgs);
-				if ($this->openString(")", $string) && $this->literal(")")) {
-					$func = array('function', $fname, $string);
-					return true;
-				}
-			}
-		}
-
-		$this->seek($s);
-		return false;
-	}
-
-	// consume a less variable
-	protected function variable(&$name) {
-		$s = $this->seek();
-		if ($this->literal($this->lessc->vPrefix, false) &&
-			($this->variable($sub) || $this->keyword($name)))
-		{
-			if (!empty($sub)) {
-				$name = array('variable', $sub);
-			} else {
-				$name = $this->lessc->vPrefix.$name;
-			}
-			return true;
-		}
-
-		$name = null;
-		$this->seek($s);
-		return false;
-	}
-
-	/**
-	 * Consume an assignment operator
-	 * Can optionally take a name that will be set to the current property name
-	 */
-	protected function assign($name = null) {
-		if ($name) $this->currentProperty = $name;
-		return $this->literal(':') || $this->literal('=');
-	}
-
-	// consume a keyword
-	protected function keyword(&$word) {
-		if ($this->match('([\w_\-\*!"][\w\-_"]*)', $m)) {
-			$word = $m[1];
-			return true;
-		}
-		return false;
-	}
-
-	// consume an end of statement delimiter
-	protected function end() {
-		if ($this->literal(';', false)) {
-			return true;
-		} elseif ($this->count == strlen($this->buffer) || $this->buffer[$this->count] == '}') {
-			// if there is end of file or a closing block next then we don't need a ;
-			return true;
-		}
-		return false;
-	}
-
-	protected function guards(&$guards) {
-		$s = $this->seek();
-
-		if (!$this->literal("when")) {
-			$this->seek($s);
-			return false;
-		}
-
-		$guards = array();
-
-		while ($this->guardGroup($g)) {
-			$guards[] = $g;
-			if (!$this->literal(",")) break;
-		}
-
-		if (count($guards) == 0) {
-			$guards = null;
-			$this->seek($s);
-			return false;
-		}
-
-		return true;
-	}
-
-	// a bunch of guards that are and'd together
-	// TODO rename to guardGroup
-	protected function guardGroup(&$guardGroup) {
-		$s = $this->seek();
-		$guardGroup = array();
-		while ($this->guard($guard)) {
-			$guardGroup[] = $guard;
-			if (!$this->literal("and")) break;
-		}
-
-		if (count($guardGroup) == 0) {
-			$guardGroup = null;
-			$this->seek($s);
-			return false;
-		}
-
-		return true;
-	}
-
-	protected function guard(&$guard) {
-		$s = $this->seek();
-		$negate = $this->literal("not");
-
-		if ($this->literal("(") && $this->expression($exp) && $this->literal(")")) {
-			$guard = $exp;
-			if ($negate) $guard = array("negate", $guard);
-			return true;
-		}
-
-		$this->seek($s);
-		return false;
-	}
-
-	/* raw parsing functions */
-
-	protected function literal($what, $eatWhitespace = null) {
-		if ($eatWhitespace === null) $eatWhitespace = $this->eatWhiteDefault;
-
-		// shortcut on single letter
-		if (!isset($what[1]) && isset($this->buffer[$this->count])) {
-			if ($this->buffer[$this->count] == $what) {
-				if (!$eatWhitespace) {
-					$this->count++;
-					return true;
-				}
-				// goes below...
-			} else {
-				return false;
-			}
-		}
-
-		if (!isset(self::$literalCache[$what])) {
-			self::$literalCache[$what] = lessc::preg_quote($what);
-		}
-
-		return $this->match(self::$literalCache[$what], $m, $eatWhitespace);
-	}
-
-	protected function genericList(&$out, $parseItem, $delim="", $flatten=true) {
-		$s = $this->seek();
-		$items = array();
-		while ($this->$parseItem($value)) {
-			$items[] = $value;
-			if ($delim) {
-				if (!$this->literal($delim)) break;
-			}
-		}
-
-		if (count($items) == 0) {
-			$this->seek($s);
-			return false;
-		}
-
-		if ($flatten && count($items) == 1) {
-			$out = $items[0];
-		} else {
-			$out = array("list", $delim, $items);
-		}
-
-		return true;
-	}
-
-
-	// advance counter to next occurrence of $what
-	// $until - don't include $what in advance
-	// $allowNewline, if string, will be used as valid char set
-	protected function to($what, &$out, $until = false, $allowNewline = false) {
-		if (is_string($allowNewline)) {
-			$validChars = $allowNewline;
-		} else {
-			$validChars = $allowNewline ? "." : "[^\n]";
-		}
-		if (!$this->match('('.$validChars.'*?)'.lessc::preg_quote($what), $m, !$until)) return false;
-		if ($until) $this->count -= strlen($what); // give back $what
-		$out = $m[1];
-		return true;
-	}
-
-	// try to match something on head of buffer
-	protected function match($regex, &$out, $eatWhitespace = null) {
-		if ($eatWhitespace === null) $eatWhitespace = $this->eatWhiteDefault;
-
-		$r = '/'.$regex.($eatWhitespace && !$this->writeComments ? '\s*' : '').'/Ais';
-		if (preg_match($r, $this->buffer, $out, null, $this->count)) {
-			$this->count += strlen($out[0]);
-			if ($eatWhitespace && $this->writeComments) $this->whitespace();
-			return true;
-		}
-		return false;
-	}
-
-	// match some whitespace
-	protected function whitespace() {
-		if ($this->writeComments) {
-			$gotWhite = false;
-			while (preg_match(self::$whitePattern, $this->buffer, $m, null, $this->count)) {
-				if (isset($m[1]) && empty($this->seenComments[$this->count])) {
-					$this->append(array("comment", $m[1]));
-					$this->seenComments[$this->count] = true;
-				}
-				$this->count += strlen($m[0]);
-				$gotWhite = true;
-			}
-			return $gotWhite;
-		} else {
-			$this->match("", $m);
-			return strlen($m[0]) > 0;
-		}
-	}
-
-	// match something without consuming it
-	protected function peek($regex, &$out = null, $from=null) {
-		if (is_null($from)) $from = $this->count;
-		$r = '/'.$regex.'/Ais';
-		$result = preg_match($r, $this->buffer, $out, null, $from);
-
-		return $result;
-	}
-
-	// seek to a spot in the buffer or return where we are on no argument
-	protected function seek($where = null) {
-		if ($where === null) return $this->count;
-		else $this->count = $where;
-		return true;
-	}
-
-	/* misc functions */
-
-	public function throwError($msg = "parse error", $count = null) {
-		$count = is_null($count) ? $this->count : $count;
-
-		$line = $this->line +
-			substr_count(substr($this->buffer, 0, $count), "\n");
-
-		if (!empty($this->sourceName)) {
-			$loc = "$this->sourceName on line $line";
-		} else {
-			$loc = "line: $line";
-		}
-
-		// TODO this depends on $this->count
-		if ($this->peek("(.*?)(\n|$)", $m, $count)) {
-			throw new exception("$msg: failed at `$m[1]` $loc");
-		} else {
-			throw new exception("$msg: $loc");
-		}
-	}
-
-	protected function pushBlock($selectors=null, $type=null) {
-		$b = new stdclass;
-		$b->parent = $this->env;
-
-		$b->type = $type;
-		$b->id = self::$nextBlockId++;
-
-		$b->isVararg = false; // TODO: kill me from here
-		$b->tags = $selectors;
-
-		$b->props = array();
-		$b->children = array();
-
-		$this->env = $b;
-		return $b;
-	}
-
-	// push a block that doesn't multiply tags
-	protected function pushSpecialBlock($type) {
-		return $this->pushBlock(null, $type);
-	}
-
-	// append a property to the current block
-	protected function append($prop, $pos = null) {
-		if ($pos !== null) $prop[-1] = $pos;
-		$this->env->props[] = $prop;
-	}
-
-	// pop something off the stack
-	protected function pop() {
-		$old = $this->env;
-		$this->env = $this->env->parent;
-		return $old;
-	}
-
-	// remove comments from $text
-	// todo: make it work for all functions, not just url
-	protected function removeComments($text) {
-		$look = array(
-			'url(', '//', '/*', '"', "'"
-		);
-
-		$out = '';
-		$min = null;
-		while (true) {
-			// find the next item
-			foreach ($look as $token) {
-				$pos = strpos($text, $token);
-				if ($pos !== false) {
-					if (!isset($min) || $pos < $min[1]) $min = array($token, $pos);
-				}
-			}
-
-			if (is_null($min)) break;
-
-			$count = $min[1];
-			$skip = 0;
-			$newlines = 0;
-			switch ($min[0]) {
-			case 'url(':
-				if (preg_match('/url\(.*?\)/', $text, $m, 0, $count))
-					$count += strlen($m[0]) - strlen($min[0]);
-				break;
-			case '"':
-			case "'":
-				if (preg_match('/'.$min[0].'.*?(?<!\\\\)'.$min[0].'/', $text, $m, 0, $count))
-					$count += strlen($m[0]) - 1;
-				break;
-			case '//':
-				$skip = strpos($text, "\n", $count);
-				if ($skip === false) $skip = strlen($text) - $count;
-				else $skip -= $count;
-				break;
-			case '/*':
-				if (preg_match('/\/\*.*?\*\//s', $text, $m, 0, $count)) {
-					$skip = strlen($m[0]);
-					$newlines = substr_count($m[0], "\n");
-				}
-				break;
-			}
-
-			if ($skip == 0) $count += strlen($min[0]);
-
-			$out .= substr($text, 0, $count).str_repeat("\n", $newlines);
-			$text = substr($text, $count + $skip);
-
-			$min = null;
-		}
-
-		return $out.$text;
-	}
-
-}
-
-class lessc_formatter_classic {
-	public $indentChar = "  ";
-
-	public $break = "\n";
-	public $open = " {";
-	public $close = "}";
-	public $selectorSeparator = ", ";
-	public $assignSeparator = ":";
-
-	public $openSingle = " { ";
-	public $closeSingle = " }";
-
-	public $disableSingle = false;
-	public $breakSelectors = false;
-
-	public $compressColors = false;
-
-	public function __construct() {
-		$this->indentLevel = 0;
-	}
-
-	public function indentStr($n = 0) {
-		return str_repeat($this->indentChar, max($this->indentLevel + $n, 0));
-	}
-
-	public function property($name, $value) {
-		return $name . $this->assignSeparator . $value . ";";
-	}
-
-	protected function isEmpty($block) {
-		if (empty($block->lines)) {
-			foreach ($block->children as $child) {
-				if (!$this->isEmpty($child)) return false;
-			}
-
-			return true;
-		}
-		return false;
-	}
-
-	public function block($block) {
-		if ($this->isEmpty($block)) return;
-
-		$inner = $pre = $this->indentStr();
-
-		$isSingle = !$this->disableSingle &&
-			is_null($block->type) && count($block->lines) == 1;
-
-		if (!empty($block->selectors)) {
-			$this->indentLevel++;
-
-			if ($this->breakSelectors) {
-				$selectorSeparator = $this->selectorSeparator . $this->break . $pre;
-			} else {
-				$selectorSeparator = $this->selectorSeparator;
-			}
-
-			echo $pre .
-				implode($selectorSeparator, $block->selectors);
-			if ($isSingle) {
-				echo $this->openSingle;
-				$inner = "";
-			} else {
-				echo $this->open . $this->break;
-				$inner = $this->indentStr();
-			}
-
-		}
-
-		if (!empty($block->lines)) {
-			$glue = $this->break.$inner;
-			echo $inner . implode($glue, $block->lines);
-			if (!$isSingle && !empty($block->children)) {
-				echo $this->break;
-			}
-		}
-
-		foreach ($block->children as $child) {
-			$this->block($child);
-		}
-
-		if (!empty($block->selectors)) {
-			if (!$isSingle && empty($block->children)) echo $this->break;
-
-			if ($isSingle) {
-				echo $this->closeSingle . $this->break;
-			} else {
-				echo $pre . $this->close . $this->break;
-			}
-
-			$this->indentLevel--;
-		}
-	}
-}
-
-class lessc_formatter_compressed extends lessc_formatter_classic {
-	public $disableSingle = true;
-	public $open = "{";
-	public $selectorSeparator = ",";
-	public $assignSeparator = ":";
-	public $break = "";
-	public $compressColors = true;
-
-	public function indentStr($n = 0) {
-		return "";
-	}
-}
-
-class lessc_formatter_lessjs extends lessc_formatter_classic {
-	public $disableSingle = true;
-	public $breakSelectors = true;
-	public $assignSeparator = ": ";
-	public $selectorSeparator = ",";
-}
diff --git a/panels/mensaPlan/config.php b/panels/mensaPlan/config.php
new file mode 100644
index 0000000000000000000000000000000000000000..f6162edf27979517efe6952e8d04da06f120552d
--- /dev/null
+++ b/panels/mensaPlan/config.php
@@ -0,0 +1,30 @@
+<?php
+// Universal
+$MENSA_URL = "http://www.stwdo.de/gastronomie/speiseplaene/hauptmensa/wochenansicht-hauptmensa/";
+$PARSE_DAYLIST = array (
+		"montag",
+		"dienstag",
+		"mittwoch",
+		"donnerstag",
+		"freitag" 
+);
+$DO_SQL = true;
+$DO_JSON = true;
+
+// SQL
+$SQL_SERVER = "ovanier.de";
+$SQL_USER = "info_writer";
+$SQL_PW = "XAHQTZeGbqsnt8K6";
+$SQL_DB = "infoscreen";
+
+// JSON
+$JSON_NAME = "mensaPlan.json";
+$JSON_INC_NR = false;
+$JSON_INC_ORIGINAL = false;
+$JSON_INC_SHORT = true;
+$JSON_INC_ART = true;
+$JSON_INC_KIND = false;
+$JSON_INC_COUNTER = true;
+$JSON_INC_STOFFE = false;
+$JSON_INC_DATE = true;
+?>
\ No newline at end of file
diff --git a/panels/mensaPlan/gericht.php b/panels/mensaPlan/gericht.php
new file mode 100644
index 0000000000000000000000000000000000000000..49cac16f7603cbf4b49509cb43f64cf9c13bf8c9
--- /dev/null
+++ b/panels/mensaPlan/gericht.php
@@ -0,0 +1,344 @@
+<?php
+class GERICHT {
+	private $nr = 0;
+	private $originalText = "";
+	private $shortText = "";
+	private $rind = false;
+	private $schwein = false;
+	private $gefluegel = false;
+	private $fisch = false;
+	private $vegetarisch = false;
+	private $vegan = false;
+	private $kinderteller = false;
+	private $counter = "";
+	private $zusatzStoffe = array (
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0,
+			0 
+	);
+	private $date = "";
+	public function getNr() {
+		return $this->nr;
+	}
+	public function getOriginalText() {
+		return $this->originalText;
+	}
+	public function getShortText() {
+		return $this->shortText;
+	}
+	public function isRind() {
+		return $this->rind;
+	}
+	public function isSchwein() {
+		return $this->schwein;
+	}
+	public function isGefluegel() {
+		return $this->gefluegel;
+	}
+	public function isFisch() {
+		return $this->fisch;
+	}
+	public function isVegetarisch() {
+		return $this->vegetarisch;
+	}
+	public function isVegan() {
+		return $this->vegan;
+	}
+	public function isKinderteller() {
+		return $this->kinderteller;
+	}
+	public function getArtAsString($seperator = " ") {
+		$art = "";
+		$first = true;
+		if ($this->rind) {
+			$art .= "R";
+			$first = false;
+		}
+		if ($this->schwein) {
+			if (! $first) {
+				$art .= $seperator;
+			}
+			$art .= "S";
+			$first = false;
+		}
+		if ($this->gefluegel) {
+			if (! $first) {
+				$art .= $seperator;
+			}
+			$art .= "G";
+			$first = false;
+		}
+		if ($this->fisch) {
+			if (! $first) {
+				$art .= $seperator;
+			}
+			$art .= "F";
+			$first = false;
+		}
+		if ($this->vegetarisch) {
+			if (! $first) {
+				$art .= $seperator;
+			}
+			$art .= "V";
+			$first = false;
+		}
+		if ($this->vegan) {
+			if (! $first) {
+				$art .= $seperator;
+			}
+			$art .= "N";
+			$first = false;
+		}
+		if ($this->kinderteller) {
+			if (! $first) {
+				$art .= $seperator;
+			}
+			$art .= "K";
+			$first = false;
+		}
+		return $art;
+	}
+	public function getCounter() {
+		return $this->counter;
+	}
+	public function isZusatzstoff($id) {
+		return $this->zusatzStoffe [$id];
+	}
+	public function getZusatzstoffe() {
+		return $this->zusatzStoffe;
+	}
+	public function getZusatzstoffeAsString($seperator = " ") {
+		$stoffe = "";
+		$first = true;
+		for($i = 0; $i < count ( $this->zusatzStoffe ); $i ++) {
+			if ($this->zusatzStoffe [$i]) {
+				if (! $first) {
+					$stoffe .= $seperator . $i;
+				} else {
+					$stoffe .= $i;
+					$first = false;
+				}
+			}
+		}
+		return $stoffe;
+	}
+	public function getDate() {
+		return $this->date;
+	}
+	public function setNr($nr) {
+		$this->nr = $nr;
+	}
+	public function setOriginalText($originalText) {
+		$this->originalText = $originalText;
+	}
+	public function setShortText($shortText) {
+		$this->shortText = $shortText;
+	}
+	public function setRind($rind) {
+		$this->rind = $rind;
+	}
+	public function setSchwein($schwein) {
+		$this->schwein = $schwein;
+	}
+	public function setGefluegel($gefluegel) {
+		$this->gefluegel = $gefluegel;
+	}
+	public function setFisch($fisch) {
+		$this->fisch = $fisch;
+	}
+	public function setVegetarisch($vegetarisch) {
+		$this->vegetarisch = $vegetarisch;
+	}
+	public function setVegan($vegan) {
+		$this->vegan = $vegan;
+	}
+	public function setKinderteller($kinderteller) {
+		$this->kinderteller = $kinderteller;
+	}
+	public function setArt($in, $val) {
+		switch ($in) {
+			case "R" :
+				$this->rind = $val;
+				break;
+			case "S" :
+				$this->schwein = $val;
+				break;
+			case "G" :
+				$this->gefluegel = $val;
+				break;
+			case "F" :
+				$this->fisch = $val;
+				break;
+			case "V" :
+				$this->vegetarisch = $val;
+				break;
+			case "N" :
+				$this->vegan = $val;
+				break;
+			case "K" :
+				$this->kinderteller = $val;
+				break;
+			default :
+				echo "Angegebene Art '" . $in . "' nicht bekannt.";
+		}
+	}
+	public function setCounter($counter) {
+		$this->counter = $counter;
+	}
+	public function setZusatzstoff($in, $val) {
+		$this->zusatzStoffe [$in] = $val;
+	}
+	public function setZusatzstoffe($zusatzStoffe) {
+		$this->zusatzStoffe = $zusatzStoffe;
+	}
+	public function setDate($date) {
+		$this->date = $date;
+	}
+	public function toggleRind() {
+		$this->rind = ! $this->rind;
+	}
+	public function toggleSchwein() {
+		$this->schwein = ! $this->schwein;
+	}
+	public function toggleGefluegel() {
+		$this->gefluegel = ! $this->gefluegel;
+	}
+	public function toggleFisch() {
+		$this->fisch = ! $this->fisch;
+	}
+	public function toggleVegetarisch() {
+		$this->vegetarisch = ! $this->vegetarisch;
+	}
+	public function toggleVegan() {
+		$this->vegan = ! $this->vegan;
+	}
+	public function toggleKinderteller() {
+		$this->kinderteller = ! $this->kinderteller;
+	}
+	public function toggleArt($in) {
+		switch ($in) {
+			case "R" :
+				$this->rind = ! $this->rind;
+				break;
+			case "S" :
+				$this->schwein = ! $this->schwein;
+				break;
+			case "G" :
+				$this->gefluegel = ! $this->gefluegel;
+				break;
+			case "F" :
+				$this->fisch = ! $this->fisch;
+				break;
+			case "V" :
+				$this->vegetarisch = ! $this->vegetarisch;
+				break;
+			case "N" :
+				$this->vegan = ! $this->vegan;
+				break;
+			case "K" :
+				$this->kinderteller = ! $this->kinderteller;
+				break;
+			default :
+				echo "Angegebene Art '" . $in . "' nicht bekannt.";
+		}
+	}
+	public function toggleZusatzstoff($in) {
+		$this->zusatzStoffe [$in] = ! $this->zusatzStoffe [$in];
+	}
+	public function toJson($inc_nr = true, $inc_original = true, $inc_short = true, $inc_art = true, $inc_kind = true, $inc_counter = true, $inc_stoffe = true, $inc_date = true) {
+		$json = "{";
+		if ($inc_nr) {
+			$json .= '"nr": "' . $this->nr . '"';
+		}
+		if ($inc_nr && ($inc_original || $inc_short || $inc_art || $inc_kind || $inc_counter || $inc_stoffe || $inc_date)) {
+			$json .= ',';
+		}
+		if ($inc_original) {
+			$json .= '"originalText": "' . $this->originalText . '"';
+		}
+		if ($inc_original && ($inc_short || $inc_art || $inc_kind || $inc_counter || $inc_stoffe || $inc_date)) {
+			$json .= ',';
+		}
+		if ($inc_short) {
+			$json .= '"shortText": "' . $this->shortText . '"';
+		}
+		if ($inc_short && ($inc_art || $inc_kind || $inc_counter || $inc_stoffe || $inc_date)) {
+			$json .= ',';
+		}
+		if ($inc_art) {
+			$json .= '"rind": ' . $this->rind . ',';
+			$json .= '"schwein": ' . $this->schwein . ',';
+			$json .= '"gefluegel": ' . $this->gefluegel . ',';
+			$json .= '"fisch": ' . $this->fisch . ',';
+			$json .= '"vegetarisch": ' . $this->vegetarisch . ',';
+			$json .= '"vegan": ' . $this->vegan . '';
+		}
+		if ($inc_art && ($inc_kind || $inc_counter || $inc_stoffe || $inc_date)) {
+			$json .= ',';
+		}
+		if ($inc_kind) {
+			$json .= '"kinderteller":' . $this->kinderteller . '';
+		}
+		if ($inc_kind && ($inc_counter || $inc_stoffe || $inc_date)) {
+			$json .= ',';
+		}
+		if ($inc_counter) {
+			$json .= '"counter": "' . $this->getCounter() . '"';
+		}
+		if ($inc_counter && ($inc_stoffe || $inc_date)) {
+			$json .= ',';
+		}
+		if ($inc_stoffe) {
+			$json .= '"zusatzStoffe": {' . '"0":' . $this->zusatzStoffe [0] . ',' . '"1":' . $this->zusatzStoffe [1] . ',' . '"2":' . $this->zusatzStoffe [2] . ',' . '"3":' . $this->zusatzStoffe [3] . ',' . '"4":' . $this->zusatzStoffe [4] . ',' . '"5":' . $this->zusatzStoffe [5] . ',' . '"6":' . $this->zusatzStoffe [6] . ',' . '"7":' . $this->zusatzStoffe [7] . ',' . '"8":' . $this->zusatzStoffe [8] . ',' . '"9":' . $this->zusatzStoffe [9] . ',' . '"10":' . $this->zusatzStoffe [10] . ',' . '"11":' . $this->zusatzStoffe [11] . ',' . '"12":' . $this->zusatzStoffe [12] . ',' . '"13":' . $this->zusatzStoffe [13] . ',' . '"14":' . $this->zusatzStoffe [14] . ',' . '"15":' . $this->zusatzStoffe [15] . ',' . '"16":' . $this->zusatzStoffe [16] . ',' . '"17":' . $this->zusatzStoffe [17] . ',' . '"18":' . $this->zusatzStoffe [18] . ',' . '"19":' . $this->zusatzStoffe [19] . ',' . '"20":' . $this->zusatzStoffe [20] . ',' . '"21":' . $this->zusatzStoffe [21] . ',' . '"22":' . $this->zusatzStoffe [22] . ',' . '"23":' . $this->zusatzStoffe [23] . ',' . '"24":' . $this->zusatzStoffe [24] . ',' . '"25":' . $this->zusatzStoffe [25] . ',' . '"26":' . $this->zusatzStoffe [26] . ',' . '"27":' . $this->zusatzStoffe [27] . ',' . '"28":' . $this->zusatzStoffe [28] . ',' . '"29":' . $this->zusatzStoffe [29] . ',' . '"30":' . $this->zusatzStoffe [30] . ',' . '"31":' . $this->zusatzStoffe [31] . ',' . '"32":' . $this->zusatzStoffe [32] . ',' . '"33":' . $this->zusatzStoffe [33] . '}';
+		}
+		if ($inc_stoffe && ($inc_date)) {
+			$json .= ',';
+		}
+		if ($inc_date) {
+			$json .= '"date": "' . $this->date . '"';
+		}
+		$json .= '}';
+		return $json;
+	}
+	public function __toString() {
+		for($i = 0; $i < count ( $this->zusatzStoffe ); $i ++) {
+			if ($this->zusatzStoffe [$i]) {
+				$stoffe = $stoffe . " " . $i;
+			}
+		}
+		
+		return "Nr: " . $this->nr . ", Original Text: " . $this->originalText . ",\n" . "Short Text: " . $this->shortText . ",\n" . "Rind: " . booleanToString ( $this->rind ) . ",\n" . "Schwein: " . booleanToString ( $this->schwein ) . ",\n" . "Fisch: " . booleanToString ( $this->fisch ) . ",\n" . "Vegetarisch: " . booleanToString ( $this->vegetarisch ) . ",\n" . "Vegan: " . booleanToString ( $this->vegan ) . ",\n" . "Kinderteller: " . booleanToString ( $this->kinderteller ) . ",\n" . "Counter: " . $this->counter . ",\n" . "Zusatzstoffe: " . $stoffe . ",\n";
+	}
+}
+?>
\ No newline at end of file
diff --git a/panels/mensaPlan/getJson.php b/panels/mensaPlan/getJson.php
new file mode 100644
index 0000000000000000000000000000000000000000..09d8f296faba3a5bb222d1aeabbf6fa8335d2762
--- /dev/null
+++ b/panels/mensaPlan/getJson.php
@@ -0,0 +1,15 @@
+<?php
+$mysqli = new mysqli ( "ovanier.de", "info_reader", "7ELZqMyUwU8MaJba", "infoscreen" );
+
+if ($mysqli->connect_errno) {
+	printf ( "Connect failed: %s\n", $mysqli->connect_error );
+	exit ();
+}
+
+if ($result = $mysqli->query ( "SELECT * FROM City" )) {
+	
+	$result->close ();
+}
+
+$mysqli->close ();
+?>
\ No newline at end of file
diff --git a/panels/mensaPlan/helper.php b/panels/mensaPlan/helper.php
new file mode 100644
index 0000000000000000000000000000000000000000..8e0240392907cbd825c30571cbfd710f3364fdf5
--- /dev/null
+++ b/panels/mensaPlan/helper.php
@@ -0,0 +1,136 @@
+<?php
+function booleanToString($bool) {
+	if ($bool) {
+		return "True";
+	} else {
+		return "False";
+	}
+}
+function toJson($tage, $name, $inc_nr, $inc_original, $inc_short, $inc_art, $inc_kind, $inc_stoffe, $inc_counter, $inc_date) {
+	$kommata = false;
+	$json = '{';
+	foreach ( $tage as $tag ) {
+		if ($kommata) {
+			$json .= ',';
+		} else {
+			$kommata = true;
+		}
+		$json .= $tag->toJson ( $inc_nr, $inc_original, $inc_short, $inc_art, $inc_kind, $inc_counter, $inc_stoffe, $inc_date );
+	}
+	$json .= "}";
+	file_put_contents ( $name, $json );
+}
+function toSql($tage, $server, $user, $pw, $db) { // TODO NR
+	$mysqli = new mysqli ( $server, $user, $pw, $db );
+	
+	if ($mysqli->connect_errno) {
+		printf ( "Connect failed: %s\n", $mysqli->connect_error );
+		exit ();
+	}
+	
+	$stmt = mysqli_prepare ( $mysqli, "INSERT INTO gerichte (nr,originalText,shortText,rind,schwein,gefluegel,fisch,vegetarisch,vegan,kinderteller,counter,date) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE originalText = ?,shortText = ?,rind = ?,schwein = ?,gefluegel = ?,fisch = ?,vegetarisch = ?,vegan = ?,kinderteller = ?, counter = ?" );
+	foreach ( $tage as $tag ) {
+		foreach ( $tag->getGerichte () as $gericht ) {
+			mysqli_stmt_bind_param ( $stmt, "issiiiiiiiisssiiiiiiii", $gericht->getNr (), $gericht->getOriginalText (), $gericht->getShortText (), $gericht->isRind (), $gericht->isSchwein (), $gericht->isGefluegel (), $gericht->isFisch (), $gericht->isVegetarisch (), $gericht->isVegan (), $gericht->isKinderteller (), $gericht->getCounter (), $gericht->getDate (), $gericht->getOriginalText (), $gericht->getShortText (), $gericht->isRind (), $gericht->isSchwein (), $gericht->isGefluegel (), $gericht->isFisch (), $gericht->isVegetarisch (), $gericht->isVegan (), $gericht->isKinderteller (), $gericht->getCounter () );
+			$gericht->getNr ();
+			$stmt->execute ();
+		}
+	}
+	$stmt->close ();
+	
+	$mysqli->close ();
+}
+function parsDay($html, $day) {
+	$tag = new TAG ( $day, substr ( $html->find ( 'a[href="#' . $day . '"]', 0 )->innertext, - 10, 10 ) );
+	
+	$html = $html->find ( 'a.#' . $day, 0 );
+	$html = $html->first_child ()->children ( 1 );
+	$tr = $html->first_child ();
+	$nr = 0;
+	while ( $tr != null ) {
+		$nr ++;
+		$current = new GERICHT ();
+		$current->setNr ( $nr );
+		$td0 = $tr->find ( 'td', 0 );
+		$td1 = $tr->find ( 'td', 1 );
+		$td2 = $tr->find ( 'td', 2 );
+		// parse originalText shortText and Zusatzstoffe
+		if ($td0 != null) {
+			$current->setOriginalText ( $td0->innertext );
+			// prepare Zusatzstoffe
+			$zusatzstoffe = $td0->innertext;
+			preg_match_all ( '#\([\d+,]+\)#', $zusatzstoffe, $matches );
+			foreach ( $matches [0] as $match ) {
+				preg_match_all ( '#[\d+]+#', $match, $stoffe );
+				foreach ( $stoffe [0] as $stoff ) {
+					$current->setZusatzstoff ( $stoff, true );
+				}
+			}
+			// shorten Text
+			$current->setShortText ( shortenText ( $td0->innertext ) );
+		}
+		// parse Art
+		if ($td1 != null) {
+			$art = $td1->innertext;
+			$current->setRind ( substr_count ( $art, "R" ) );
+			$current->setSchwein ( substr_count ( $art, "S" ) );
+			$current->setGefluegel ( substr_count ( $art, "G" ) );
+			$current->setFisch ( substr_count ( $art, "F" ) );
+			$current->setVegetarisch ( substr_count ( $art, "V" ) );
+			$current->setVegan ( substr_count ( $art, "N" ) );
+			$current->setKinderteller ( substr_count ( $art, "K" ) );
+		}
+		// parse Counter
+		if ($td2 != null) {
+			$img = $td2->find ( 'img', 0 );
+			if ($img != null) {
+				$img = $img->src;
+				$img = array_pop ( explode ( "/", $img ) );
+				switch ($img) {
+					case "icon-menue-1.png" :
+						$current->setCounter ( 1 );
+						break;
+					case "icon-menue-2.png" :
+						$current->setCounter ( 2 );
+						break;
+					case "icon-tagesgericht.png" :
+						$current->setCounter ( 3 );
+						break;
+					case "icon-vegetarisch.png" :
+						$current->setCounter ( 4 );
+						break;
+					case "icon-aktionsteller.png" :
+						$current->setCounter ( 5 );
+						break;
+					case "icon-grillstation.png" :
+						$current->setCounter ( 6 );
+						break;
+					case "icon-fisch.png" :
+						$current->setCounter ( 7 );
+						break;
+					case "icon-vegan.png" :
+						$current->setCounter ( 8 );
+						break;
+				}
+			}
+		}
+		if ($current->getOriginalText () != "") { // remove empty Fields
+			$current->setDate ( $tag->getDate () );
+			$tag->addGericht ( $current );
+		}
+		$tr = $tr->next_sibling ();
+	}
+	return $tag;
+}
+function shortenText($text) {
+	$text = preg_replace ( '#\([\d+,]+\)#', '', $text ); // remove zusatzstoffe
+	$text = preg_replace ( '#(\s,|,\s)#', ',', $text ); // fix Komma
+	$text = preg_replace ( '#,#', ', ', $text ); // fix Komma
+	$text = preg_replace ( '#\s+#', ' ', $text ); // fix double Whitespace
+	$text = preg_replace ( '#,\sdazu\s\d\sBeilagen\snach\sWahl#', '', $text ); // remove Beilagen
+	$text = preg_replace ( '#,\sdazu\s#', ' + ', $text ); // replace dazu
+	$text = preg_replace ( '#\sund\s#', ' & ', $text ); // replace und
+	return $text;
+}
+
+?>
\ No newline at end of file
diff --git a/panels/mensaPlan/mensaParser.php b/panels/mensaPlan/mensaParser.php
new file mode 100644
index 0000000000000000000000000000000000000000..295f169bea7382f49b65665f165141e59de6c359
--- /dev/null
+++ b/panels/mensaPlan/mensaParser.php
@@ -0,0 +1,28 @@
+<?php
+require 'config.php';
+require 'simple_html_dom.php';
+require 'helper.php';
+require 'gericht.php';
+require 'tag.php';
+
+// Parse
+$html = file_get_html ( $MENSA_URL );
+if ($html != null) {
+	$tage = array ();
+	foreach ( $PARSE_DAYLIST as $DAYNAME ) {
+		array_push ( $tage, parsDay ( $html, $DAYNAME ) );
+	}
+	
+	// CREATE JSON
+	if ($DO_JSON) {
+		toJson ( $tage, $JSON_NAME, $JSON_INC_NR, $JSON_INC_ORIGINAL, $JSON_INC_SHORT, $JSON_INC_ART, $JSON_INC_KIND, $JSON_INC_STOFFE, $JSON_INC_COUNTER, $JSON_INC_DATE );
+	}
+	
+	// SAVE
+	if ($DO_SQL) {
+		toSql ( $tage, $SQL_SERVER, $SQL_USER, $SQL_PW, $SQL_DB );
+	}
+} else {
+	echo "Webseite nicht erreichbar.";
+}
+?>
\ No newline at end of file
diff --git a/panels/mensaPlan/mensaParser.py b/panels/mensaPlan/mensaParser.py
deleted file mode 100755
index ce099aba8f75a5127de01bc0d4c4c3a05281e966..0000000000000000000000000000000000000000
--- a/panels/mensaPlan/mensaParser.py
+++ /dev/null
@@ -1,48 +0,0 @@
-import urllib,json,io,re
-from htmldom import htmldom
-response = urllib.urlopen("http://www.stwdo.de/gastronomie/speiseplaene/hauptmensa/wochenansicht-hauptmensa/")
-dom = htmldom.HtmlDom()
-dom = dom.createDom(response.read())
-response.close()
-
-def parseDay( dom, dayName ):
-	gerichte = []
-	date = dom.find('a[href="#'+dayName+'"]').first().text()[-10:]
-	day = dom.find("div#"+dayName).first().find("tbody").find("tr")
-	for tr in range(day.length()):
-		tds = day[tr].find("td");
-		gericht = tds[0].text()
-		#-zusatzstoffe
-		gericht = re.sub(r'\([\d+,]+\)', '', gericht)
-		#+verkuerzung
-		gericht = re.sub(r' dazu \d Beilagen nach Wahl', '', gericht)
-		gericht = re.sub(r',\sdazu\s', ' + ', gericht)
-		gericht = re.sub(r'\sund\s', ' & ', gericht)
-		#eyecandy
-		gericht = re.sub(r'\s,', ',', gericht)
-		gericht = re.sub(r',\S', ', ', gericht)
-		gericht = re.sub(r'\s$', '', gericht)
-		gericht = re.sub(r',$', '', gericht)
-		art = tds[1].text()
-		art = re.sub(r',A', '', art)
-		art = re.sub(r',K', '', art)
-		kategorie = "icon-aktionsteller.png"
-		#kategorie = tds[2].find("img").first().attr( "src" )
-		#kategorie = re.sub(r'fileadmin/images/speiseplaene/menuekategorie/', '', kategorie)
-		gerichte.append({'gericht': gericht,"art": art,"kategorie":kategorie})
-	jday = {'date': date,"gerichte":gerichte}
-	return jday
-
-result = {
-	'montag': parseDay(dom,"montag"),
-	'dienstag': parseDay(dom,"dienstag"),
-	'mittwoch': parseDay(dom,"mittwoch"),
-	'donnerstag': parseDay(dom,"donnerstag"),
-	'freitag': parseDay(dom,"freitag")
-}
-
-with io.open('mensaPlan.json', 'w', encoding='utf-8') as f:
-  f.write(unicode(json.dumps(result)))
-
-#multimensa
-#style
\ No newline at end of file
diff --git a/panels/mensaPlan/mensaPlan.json b/panels/mensaPlan/mensaPlan.json
index 75f5fba3f66c66c8d358d309a65d28e8b32266c7..ac186da8f671e51c2972174096fbdb2ae02209e3 100755
--- a/panels/mensaPlan/mensaPlan.json
+++ b/panels/mensaPlan/mensaPlan.json
@@ -1 +1 @@
-{"montag": {"date": "24.08.2015", "gerichte": [{"kategorie": "icon-menue-1.png", "art": "G", "gericht": "Gefl\u00fcgelbratwurst  mit Currysauce"}, {"kategorie": "icon-menue-2.png", "art": "S", "gericht": "Cordon Bleu  mit Sauce"}, {"kategorie": "icon-tagesgericht.png", "art": "N", "gericht": "Ravioli Grano Doro  in Tomatensauce + Stangenbrot, Salat & Dessert"}, {"kategorie": "icon-vegetarisch.png", "art": "V", "gericht": "Kartoffeltasche mit Mozzarella  & Kr\u00e4uterdip"}, {"kategorie": "icon-vegetarisch.png", "art": "V", "gericht": ""}, {"kategorie": "icon-aktionsteller.png", "art": "G", "gericht": "H\u00e4hnchengyros mit Tzatziki  + Pommes frites & Krautsalat"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "H\u00e4hnchen D\u00f6ner Tasche  mit Tzatziki  & Krautsalat"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "Gefl\u00fcgel Grillteller (Pute, H\u00e4hnchen, Cevapcici)  + Bratkartoffeln & Prinze\u00dfbohnen"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "H\u00e4hnchenroulade mit Bulgur gef\u00fcllt  + Pommes frites & Salat"}, {"kategorie": "icon-grillstation.png", "art": "S", "gericht": "Frisch gebratenes Schweinesteak mit Kr\u00e4uterbutter  + Wedges & Pfannengem\u00fcse"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "Tagliatelle  mit Gefl\u00fcgel Bolognese  & geriebenem Hartk\u00e4se  + Salat"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "H\u00e4hnchen D\u00f6ner Teller  mit Tzatziki, Pommes frites & Krautsalat"}, {"kategorie": "icon-fisch.png", "art": "F", "gericht": "Kabeljaufilet mit Erdnusskruste + asiatischer Reis & Salat"}, {"kategorie": "icon-vegan.png", "art": "N", "gericht": "Ger\u00e4ucherter Tofu  auf Spitzkohlsalat, azu cremige Sauce  & Drillinge"}]}, "mittwoch": {"date": "26.08.2015", "gerichte": [{"kategorie": "icon-menue-1.png", "art": "S", "gericht": "Spie\u00dfbraten  mit Paprikasauce"}, {"kategorie": "icon-menue-2.png", "art": "G", "gericht": "Knusper Nuggets  mit Dip"}, {"kategorie": "icon-tagesgericht.png", "art": "F", "gericht": "Seelachsfilet  mit Remoulade  + P\u00fcree, Salat & Dessert"}, {"kategorie": "icon-vegetarisch.png", "art": "N", "gericht": "Vollkornspaghetti  mit Soja- Bolognese"}, {"kategorie": "icon-aktionsteller.png", "art": "G", "gericht": "H\u00e4hnchengyros mit Tzatziki  + Pommes frites & Krautsalat"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "Gefl\u00fcgel Grillteller (Pute, H\u00e4hnchen, Cevapcici)  + Bratkartoffeln & Prinze\u00dfbohnen"}, {"kategorie": "icon-grillstation.png", "art": "S", "gericht": "Frisch gebratenes Schweinesteak mit Kr\u00e4uterbutter  + Wedges & Pfannengem\u00fcse"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "H\u00e4hnchen D\u00f6ner Teller  mit Tzatziki, Pommes frites & Krautsalat"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "H\u00e4hnchen D\u00f6ner Tasche  mit Tzatziki  & Krautsalat"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "Tagliatelle  mit Gefl\u00fcgel Bolognese  & geriebenem Hartk\u00e4se  + Salat"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "H\u00e4hnchenroulade mit Bulgur gef\u00fcllt  + Pommes frites & Salat"}, {"kategorie": "icon-fisch.png", "art": "F", "gericht": "Kabeljaufilet mit Erdnusskruste + asiatischer Reis & Salat"}, {"kategorie": "icon-vegan.png", "art": "N", "gericht": "Ger\u00e4ucherter Tofu gebacken  auf Spitzkohlsalat, azu cremige Sauce  & Drillinge"}]}, "freitag": {"date": "28.08.2015", "gerichte": [{"kategorie": "icon-menue-1.png", "art": "S", "gericht": "Frikadelle &quot;Hausfrauen Art&quot;  mit Sauce"}, {"kategorie": "icon-menue-2.png", "art": "F", "gericht": "Seelachsfilet mit Kartoffelkruste  mit Senfsauce"}, {"kategorie": "icon-tagesgericht.png", "art": "V", "gericht": "Frische Schupfnudeln mit Gem\u00fcse  + Tomatensauce, Salat & Dessert"}, {"kategorie": "icon-vegetarisch.png", "art": "N", "gericht": "Tortellini mit Gem\u00fcse  & Sauce"}, {"kategorie": "icon-aktionsteller.png", "art": "G", "gericht": "H\u00e4hnchengyros mit Tzatziki  + Pommes frites & Krautsalat"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "H\u00e4hnchen D\u00f6ner Teller  mit Tzatziki, Pommes frites & Krautsalat"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "Gefl\u00fcgel Grillteller (Pute, H\u00e4hnchen, Cevapcici)  + Bratkartoffeln & Prinze\u00dfbohnen"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "H\u00e4hnchen D\u00f6ner Tasche  mit Tzatziki  & Krautsalat"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "Tagliatelle  mit Gefl\u00fcgel Bolognese  & geriebenem Hartk\u00e4se  + Salat"}, {"kategorie": "icon-grillstation.png", "art": "S", "gericht": "Frisch gebratenes Schweinesteak mit Kr\u00e4uterbutter  + Wedges & Pfannengem\u00fcse"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "H\u00e4hnchenroulade mit Bulgur gef\u00fcllt  + Pommes frites & Salat"}, {"kategorie": "icon-fisch.png", "art": "F", "gericht": "Kabeljaufilet mit Erdnusskruste + asiatischer Reis & Salat"}, {"kategorie": "icon-vegan.png", "art": "N", "gericht": "Ger\u00e4ucherter Tofu gebacken  auf Spitzkohlsalat, azu cremige Sauce  & Drillinge"}]}, "dienstag": {"date": "25.08.2015", "gerichte": [{"kategorie": "icon-menue-1.png", "art": "V", "gericht": "Kartoffel-R\u00f6sti mit Brokkoli, K\u00e4se & Hollandaise \u00fcberbacken  + 3 Beilagen"}, {"kategorie": "icon-menue-2.png", "art": "G", "gericht": "Panierts Putenschnitzel  mit Rahmsauce"}, {"kategorie": "icon-tagesgericht.png", "art": "V", "gericht": "Rahmspinat  mit R\u00fchreier  + Salzkartoffeln & Dessert"}, {"kategorie": "icon-vegetarisch.png", "art": "N", "gericht": "Gr\u00fcnkern- Gem\u00fcsepfanne  mit Tomatensauce"}, {"kategorie": "icon-aktionsteller.png", "art": "G", "gericht": "H\u00e4hnchengyros mit Tzatziki  + Pommes frites & Krautsalat"}, {"kategorie": "icon-grillstation.png", "art": "S", "gericht": "Frisch gebratenes Schweinesteak mit Kr\u00e4uterbutter  + Wedges & Pfannengem\u00fcse"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "Gefl\u00fcgel Grillteller (Pute, H\u00e4hnchen, Cevapcici)  + Bratkartoffeln & Prinze\u00dfbohnen"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "H\u00e4hnchenroulade mit Bulgur gef\u00fcllt  + Pommes frites & Salat"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "Tagliatelle  mit Gefl\u00fcgel Bolognese  & geriebenem Hartk\u00e4se  + Salat"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "H\u00e4hnchen D\u00f6ner Tasche  mit Tzatziki  & Krautsalat"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "H\u00e4hnchen D\u00f6ner Teller  mit Tzatziki, Pommes frites & Krautsalat"}, {"kategorie": "icon-fisch.png", "art": "F", "gericht": "Kabeljaufilet mit Erdnusskruste + asiatischer Reis & Salat"}, {"kategorie": "icon-vegan.png", "art": "N", "gericht": "Ger\u00e4ucherter Tofu gebacken  auf Spitzkohlsalat, azu cremige Sauce  & Drillinge"}]}, "donnerstag": {"date": "27.08.2015", "gerichte": [{"kategorie": "icon-menue-1.png", "art": "V", "gericht": "Gebackene Teigrolle  mit Koriander- Dip"}, {"kategorie": "icon-menue-2.png", "art": "G", "gericht": "Chicken Wings mit Paprika Dip"}, {"kategorie": "icon-tagesgericht.png", "art": "R", "gericht": "Chili con Carne  mit Br\u00f6tchen  & Dessert"}, {"kategorie": "icon-vegetarisch.png", "art": "V", "gericht": "Sesam-Karotten-Sticks  mit Kr\u00e4uterquark"}, {"kategorie": "icon-aktionsteller.png", "art": "G", "gericht": "H\u00e4hnchengyros mit Tzatziki  + Pommes frites & Krautsalat"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "H\u00e4hnchen D\u00f6ner Teller  mit Tzatziki, Pommes frites & Krautsalat"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "Gefl\u00fcgel Grillteller (Pute, H\u00e4hnchen, Cevapcici)  + Bratkartoffeln & Prinze\u00dfbohnen"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "H\u00e4hnchen D\u00f6ner Tasche  mit Tzatziki  & Krautsalat"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "Tagliatelle  mit Gefl\u00fcgel Bolognese  & geriebenem Hartk\u00e4se  + Salat"}, {"kategorie": "icon-grillstation.png", "art": "S", "gericht": "Frisch gebratenes Schweinesteak mit Kr\u00e4uterbutter  + Wedges & Pfannengem\u00fcse"}, {"kategorie": "icon-grillstation.png", "art": "G", "gericht": "H\u00e4hnchenroulade mit Bulgur gef\u00fcllt  + Pommes frites & Salat"}, {"kategorie": "icon-fisch.png", "art": "F", "gericht": "Kabeljaufilet mit Erdnusskruste + asiatischer Reis & Salat"}, {"kategorie": "icon-vegan.png", "art": "N", "gericht": "Ger\u00e4ucherter Tofu gebacken  auf Spitzkohlsalat, azu cremige Sauce  & Drillinge"}]}}
\ No newline at end of file
+{"montag":[{"shortText": "Geflügelbratwurst mit Currysauce","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "1","date": "05.10.2015"},{"shortText": "Cordon Bleu mit Sauce","rind": 0,"schwein": 1,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "2","date": "05.10.2015"},{"shortText": "Ravioli Grano Doro in Tomatensauce + Stangenbrot, Salat & Dessert","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 1,"counter": "3","date": "05.10.2015"},{"shortText": "Kartoffeltasche mit Mozzarella & Kräuterdip","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 1,"vegan": 0,"counter": "4","date": "05.10.2015"},{"shortText": "Hähnchengyros mit Tzatziki + Pommes frites & Krautsalat","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "5","date": "05.10.2015"},{"shortText": "Tagliatelle mit Geflügel Bolognese & geriebenem Hartkäse + Salat ","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "05.10.2015"},{"shortText": "Frisch gebratenes Schweinesteak mit Kräuterbutter + Wedges & Pfannengemüse","rind": 0,"schwein": 1,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "05.10.2015"},{"shortText": "Hähnchenroulade mit Bulgur gefüllt + Pommes frites & Salat ","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "05.10.2015"},{"shortText": "Geflügel Grillteller (Pute, Hähnchen, Cevapcici) + Bratkartoffeln & Prinzeßbohnen","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "05.10.2015"},{"shortText": "Hähnchen Döner Teller mit Tzatziki, Pommes frites & Krautsalat","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "05.10.2015"},{"shortText": "Gefüllter Wraper mit Hähnchen Döner mit Tzatziki & Krautsalat","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "05.10.2015"},{"shortText": "Kabeljaufilet gebacken, mit Sauce Remouladensauce + Salzkartoffeln & Salat ","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 1,"vegetarisch": 0,"vegan": 0,"counter": "7","date": "05.10.2015"},{"shortText": "Couscous mit Gemüse & Sauce + Saisonsalate ","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 1,"counter": "8","date": "05.10.2015"},{"shortText": "Pommes ","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "","date": "05.10.2015"},{"shortText": "Tagessuppe","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "","date": "05.10.2015"}],"dienstag":[{"shortText": "Kartoffel-Rösti mit Brokkoli, Käse & Hollandaise überbacken + 3 Beilagen","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 1,"vegan": 0,"counter": "1","date": "06.10.2015"},{"shortText": "Panierts Putenschnitzel mit Rahmsauce","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "2","date": "06.10.2015"},{"shortText": "Rahmspinat mit Rühreier + Salzkartoffeln & Dessert","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 1,"vegan": 0,"counter": "3","date": "06.10.2015"},{"shortText": "Grünkern- Gemüsepfanne mit Tomatensauce","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 1,"counter": "4","date": "06.10.2015"},{"shortText": "Hähnchengyros mit Tzatziki + Pommes frites & Krautsalat","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "5","date": "06.10.2015"},{"shortText": "Gefüllter Wraper mit Hähnchen Döner mit Tzatziki & Krautsalat","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "06.10.2015"},{"shortText": "Hähnchen Döner Teller mit Tzatziki, Pommes frites & Krautsalat","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "06.10.2015"},{"shortText": "Hähnchenroulade mit Bulgur gefüllt + Pommes frites & Salat ","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "06.10.2015"},{"shortText": "Frisch gebratenes Schweinesteak mit Kräuterbutter + Wedges & Pfannengemüse","rind": 0,"schwein": 1,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "06.10.2015"},{"shortText": "Tagliatelle mit Geflügel Bolognese & geriebenem Hartkäse + Salat ","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "06.10.2015"},{"shortText": "Geflügel Grillteller (Pute, Hähnchen, Cevapcici) + Bratkartoffeln & Prinzeßbohnen","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "06.10.2015"},{"shortText": "Kabeljaufilet gebacken, mit Sauce Remouladensauce + Salzkartoffeln & Salat ","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 1,"vegetarisch": 0,"vegan": 0,"counter": "7","date": "06.10.2015"},{"shortText": "Couscous mit Gemüse + Saisonsalate","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 1,"counter": "8","date": "06.10.2015"},{"shortText": "Tagessuppe","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "","date": "06.10.2015"},{"shortText": "Pommes ","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "","date": "06.10.2015"}],"mittwoch":[{"shortText": "Gebackene Teigrolle mit Dip","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 1,"vegan": 0,"counter": "1","date": "07.10.2015"},{"shortText": "Chicken Wings mit Paprika Dip ","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "2","date": "07.10.2015"},{"shortText": "Seelachsfilet mit Remoulade + Püree, Salat & Dessert","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 1,"vegetarisch": 0,"vegan": 0,"counter": "3","date": "07.10.2015"},{"shortText": "Vollkornspaghetti mit Soja- Bolognese","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 1,"counter": "4","date": "07.10.2015"},{"shortText": "Hähnchengyros mit Tzatziki + Pommes frites & Krautsalat","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "5","date": "07.10.2015"},{"shortText": "Geflügel Grillteller (Pute, Hähnchen, Cevapcici) + Bratkartoffeln & Prinzeßbohnen","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "07.10.2015"},{"shortText": "Hähnchen Döner Teller mit Tzatziki, Pommes frites & Krautsalat","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "07.10.2015"},{"shortText": "Gefüllter Wraper mit Hähnchen Döner mit Tzatziki & Krautsalat","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "07.10.2015"},{"shortText": "Frisch gebratenes Schweinesteak mit Kräuterbutter + Wedges & Pfannengemüse","rind": 0,"schwein": 1,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "07.10.2015"},{"shortText": "Tagliatelle mit Geflügel Bolognese & geriebenem Hartkäse + Salat ","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "07.10.2015"},{"shortText": "Hähnchenroulade mit Bulgur gefüllt + Pommes frites & Salat ","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "07.10.2015"},{"shortText": "Kabeljaufilet gebacken, mit Sauce Remouladensauce + Salzkartoffeln & Salat ","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 1,"vegetarisch": 0,"vegan": 0,"counter": "7","date": "07.10.2015"},{"shortText": "Couscous mit Gemüse + Saisonsalate","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 1,"counter": "8","date": "07.10.2015"},{"shortText": "Pommes ","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "","date": "07.10.2015"},{"shortText": "Tagessuppe","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "","date": "07.10.2015"}],"donnerstag":[{"shortText": "Spießbraten mit Paprikasauce","rind": 0,"schwein": 1,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "1","date": "08.10.2015"},{"shortText": "Knusper Nuggets mit Dip","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "2","date": "08.10.2015"},{"shortText": "Chili con Carne mit Brötchen & Dessert","rind": 1,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "3","date": "08.10.2015"},{"shortText": "Spinat Käse Taler, mit Pilzsauce ","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 1,"vegan": 0,"counter": "4","date": "08.10.2015"},{"shortText": "Hähnchengyros mit Tzatziki + Pommes frites & Krautsalat","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "5","date": "08.10.2015"},{"shortText": "Gefüllter Wraper mit Hähnchen Döner mit Tzatziki & Krautsalat","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "08.10.2015"},{"shortText": "Hähnchen Döner Teller mit Tzatziki, Pommes frites & Krautsalat","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "08.10.2015"},{"shortText": "Geflügel Grillteller (Pute, Hähnchen, Cevapcici) + Bratkartoffeln & Prinzeßbohnen","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "08.10.2015"},{"shortText": "Frisch gebratenes Schweinesteak mit Kräuterbutter + Wedges & Pfannengemüse","rind": 0,"schwein": 1,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "08.10.2015"},{"shortText": "Tagliatelle mit Geflügel Bolognese & geriebenem Hartkäse + Salat ","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "08.10.2015"},{"shortText": "Hähnchenroulade mit Bulgur gefüllt + Pommes frites & Salat ","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "08.10.2015"},{"shortText": "Kabeljaufilet gebacken, mit Sauce Remouladensauce + Salzkartoffeln & Salat ","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 1,"vegetarisch": 0,"vegan": 0,"counter": "7","date": "08.10.2015"},{"shortText": "Couscous mit Gemüse + Saisonsalate","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 1,"counter": "8","date": "08.10.2015"},{"shortText": "Pommes ","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "","date": "08.10.2015"},{"shortText": "Pommes ","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "","date": "08.10.2015"},{"shortText": "Tagessuppe","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "","date": "08.10.2015"}],"freitag":[{"shortText": "Wirsingroulade, mit Sauce ","rind": 0,"schwein": 1,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "1","date": "09.10.2015"},{"shortText": "Seelachsfilet mit Kartoffelkruste mit Senfsauce","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 1,"vegetarisch": 0,"vegan": 0,"counter": "2","date": "09.10.2015"},{"shortText": "Frische Schupfnudeln mit Zucchini + Tomatensauce, Salat & Dessert","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 1,"vegan": 0,"counter": "3","date": "09.10.2015"},{"shortText": "Tortellini mit Gemüse & Sauce","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 1,"counter": "4","date": "09.10.2015"},{"shortText": "Hähnchengyros mit Tzatziki + Pommes frites & Krautsalat","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "5","date": "09.10.2015"},{"shortText": "Tagliatelle mit Geflügel Bolognese & geriebenem Hartkäse + Salat ","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "09.10.2015"},{"shortText": "Gefüllter Wraper mit Hähnchen Döner mit Tzatziki & Krautsalat","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "09.10.2015"},{"shortText": "Frisch gebratenes Schweinesteak mit Kräuterbutter + Wedges & Pfannengemüse","rind": 0,"schwein": 1,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "09.10.2015"},{"shortText": "Hähnchenroulade mit Bulgur gefüllt + Pommes frites & Salat ","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "09.10.2015"},{"shortText": "Geflügel Grillteller (Pute, Hähnchen, Cevapcici) + Bratkartoffeln & Prinzeßbohnen","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "09.10.2015"},{"shortText": "Hähnchen Döner Teller mit Tzatziki, Pommes frites & Krautsalat","rind": 0,"schwein": 0,"gefluegel": 1,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "6","date": "09.10.2015"},{"shortText": "Kabeljaufilet gebacken, mit Sauce Remouladensauce + Salzkartoffeln & Salat ","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 1,"vegetarisch": 0,"vegan": 0,"counter": "7","date": "09.10.2015"},{"shortText": "Couscous mit Gemüse + Saisonsalate","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 1,"counter": "8","date": "09.10.2015"},{"shortText": "Pommes ","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "","date": "09.10.2015"},{"shortText": "Pommes ","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "","date": "09.10.2015"},{"shortText": "Tagessuppe","rind": 0,"schwein": 0,"gefluegel": 0,"fisch": 0,"vegetarisch": 0,"vegan": 0,"counter": "","date": "09.10.2015"}]}
\ No newline at end of file
diff --git a/panels/mensaPlan/script.js b/panels/mensaPlan/script.js
index 672ed28368b45f6ebf0689a5afff4c74257734b4..63e82b49df36f9724cb2f82ca3e04dae5381751a 100755
--- a/panels/mensaPlan/script.js
+++ b/panels/mensaPlan/script.js
@@ -1,8 +1,10 @@
 this.loaded = function(panel, config) {
+	// reload data
 	setInterval(function() {
 		getMensaPlan();
 	}, 1800000);
 
+	// switch tabs
 	setInterval(function() {
 		var currentTab = $("#tabs").tabs('option', 'active');
 		if (currentTab == 0) {
@@ -56,13 +58,12 @@ this.loaded = function(panel, config) {
 			var day = json.montag;
 			break;
 		}
-		var gerichte = day.gerichte;
 		if (next) {
-			document.getElementById("mensaPlanTitleBar").innerHTML = "Mensaplan von MORGEN dem  "
-					+ day.date;
+				document.getElementById("mensaPlanTitleBar").innerHTML = "Mensaplan von MORGEN dem  "
+					+ day[0].date;
 		} else {
 			document.getElementById("mensaPlanTitleBar").innerHTML = "Mensaplan von HEUTE dem  "
-					+ day.date;
+					+ day[0].date;
 		}
 		var tableBody1 = document.getElementById("mensaPlanTable1Body");
 		var tableBody2 = document.getElementById("mensaPlanTable2Body");
@@ -70,12 +71,10 @@ this.loaded = function(panel, config) {
 		tableBody2.innerHTML = "";
 		var a = 0;
 		var b = 0;
-		for (var i = 0; i < gerichte.length; i++) {
-			var gericht = gerichte[i];
-			if (gericht.kategorie == "icon-menue-1.png"
-					|| gericht.kategorie == "icon-menue-2.png"
-					|| gericht.kategorie == "icon-tagesgericht.png"
-					|| gericht.kategorie == "icon-aktionsteller.png") {
+		for (var i = 0; i < day.length; i++) {
+			var gericht = day[i];
+			if (gericht.counter != 8 && gericht.counter != 6
+					&& gericht.counter != 4) {
 				var row = tableBody1.insertRow(a);
 				a++;
 			} else {
@@ -85,11 +84,81 @@ this.loaded = function(panel, config) {
 			var cell1 = row.insertCell(0);
 			var cell2 = row.insertCell(1);
 			var cell3 = row.insertCell(2);
-			cell1.innerHTML = gericht.gericht;
-			cell2.innerHTML = gericht.art;
-			cell3.innerHTML = '<img src="panels/mensaPlan/img/'
-					+ gericht.kategorie + '" />';
-			j++;
+			cell1.innerHTML = gericht.shortText;
+			var art = "";
+			var first = true;
+			if(gericht.rind){
+				art += "R";
+			}
+			if(!first) {
+				art += " ";
+				first = false;
+			}
+			if(gericht.schwein){
+				art += "S";
+			}
+			if(!first) {
+				art += " ";
+				first = false;
+			}
+			if(gericht.gefluegel){
+				art += "G";
+			}
+			if(!first) {
+				art += " ";
+				first = false;
+			}
+			if(gericht.fisch){
+				art += "F";
+			}
+			if(!first) {
+				art += " ";
+				first = false;
+			}
+			if(gericht.vegetarisch){
+				art += "V";
+			}
+			if(!first) {
+				art += " ";
+				first = false;
+			}
+			if(gericht.vegan){
+				art += "N";
+			}
+			cell2.innerHTML = art;
+			var img = "";
+			switch (gericht.counter) {
+			case "1":
+				img = "icon-menue-1.png";
+				break;
+			case "2":
+				img = "icon-menue-2.png";
+				break;
+			case "3":
+				img = "icon-tagesgericht.png";
+				break;
+			case "4":
+				img = "icon-vegetarisch.png";
+				break;
+			case "5":
+				img = "icon-aktionsteller.png";
+				break;
+			case "6":
+				img = "icon-grillstation.png";
+				break;
+			case "7":
+				img = "icon-fisch.png";
+				break;
+			case "8":
+				img = "icon-vegan.png";
+				break;
+			default:
+				img = "ERROR";
+			}
+			if (gericht.counter != 0) {
+				gericht.counter = cell3.innerHTML = '<img src="panels/mensaPlan/img/'
+						+ img + '" />';
+			}
 		}
 	}
 
diff --git a/panels/mensaPlan/setup/gerichte.sql b/panels/mensaPlan/setup/gerichte.sql
new file mode 100644
index 0000000000000000000000000000000000000000..b1ce28e1a46735045401df41043be49df9a19050
--- /dev/null
+++ b/panels/mensaPlan/setup/gerichte.sql
@@ -0,0 +1,18 @@
+CREATE TABLE IF NOT EXISTS `gerichte` (
+`id` int(255) NOT NULL,
+  `nr` int(11) NOT NULL,
+  `originalText` text NOT NULL,
+  `shortText` text NOT NULL,
+  `rind` tinyint(1) NOT NULL DEFAULT '0',
+  `schwein` tinyint(1) NOT NULL DEFAULT '0',
+  `gefluegel` tinyint(1) NOT NULL DEFAULT '0',
+  `fisch` tinyint(1) NOT NULL DEFAULT '0',
+  `vegetarisch` tinyint(1) NOT NULL DEFAULT '0',
+  `vegan` tinyint(1) NOT NULL DEFAULT '0',
+  `kinderteller` tinyint(1) NOT NULL DEFAULT '0',
+  `counter` int(11) DEFAULT '0',
+  `date` varchar(10) NOT NULL
+) ENGINE=InnoDB AUTO_INCREMENT=162 DEFAULT CHARSET=latin1;
+
+ALTER TABLE `gerichte`
+ ADD PRIMARY KEY (`nr`,`date`), ADD UNIQUE KEY (`nr`,`date`), ADD KEY `id` (`id`);
\ No newline at end of file
diff --git a/panels/mensaPlan/simple_html_dom.php b/panels/mensaPlan/simple_html_dom.php
new file mode 100644
index 0000000000000000000000000000000000000000..93884dd8a395203cc6f2e20349b9127bd264de52
--- /dev/null
+++ b/panels/mensaPlan/simple_html_dom.php
@@ -0,0 +1,1742 @@
+<?php
+/**
+ * Website: http://sourceforge.net/projects/simplehtmldom/
+ * Additional projects that may be used: http://sourceforge.net/projects/debugobject/
+ * Acknowledge: Jose Solorzano (https://sourceforge.net/projects/php-html/)
+ * Contributions by:
+ *	 Yousuke Kumakura (Attribute filters)
+ *	 Vadim Voituk (Negative indexes supports of "find" method)
+ *	 Antcs (Constructor with automatically load contents either text or file/url)
+ *
+ * all affected sections have comments starting with "PaperG"
+ *
+ * Paperg - Added case insensitive testing of the value of the selector.
+ * Paperg - Added tag_start for the starting index of tags - NOTE: This works but not accurately.
+ *  This tag_start gets counted AFTER \r\n have been crushed out, and after the remove_noice calls so it will not reflect the REAL position of the tag in the source,
+ *  it will almost always be smaller by some amount.
+ *  We use this to determine how far into the file the tag in question is.  This "percentage will never be accurate as the $dom->size is the "real" number of bytes the dom was created from.
+ *  but for most purposes, it's a really good estimation.
+ * Paperg - Added the forceTagsClosed to the dom constructor.  Forcing tags closed is great for malformed html, but it CAN lead to parsing errors.
+ * Allow the user to tell us how much they trust the html.
+ * Paperg add the text and plaintext to the selectors for the find syntax.  plaintext implies text in the innertext of a node.  text implies that the tag is a text node.
+ * This allows for us to find tags based on the text they contain.
+ * Create find_ancestor_tag to see if a tag is - at any level - inside of another specific tag.
+ * Paperg: added parse_charset so that we know about the character set of the source document.
+ *  NOTE:  If the user's system has a routine called get_last_retrieve_url_contents_content_type availalbe, we will assume it's returning the content-type header from the
+ *  last transfer or curl_exec, and we will parse that and use it in preference to any other method of charset detection.
+ *
+ * Found infinite loop in the case of broken html in restore_noise.  Rewrote to protect from that.
+ * PaperG (John Schlick) Added get_display_size for "IMG" tags.
+ *
+ * Licensed under The MIT License
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author S.C. Chen <me578022@gmail.com>
+ * @author John Schlick
+ * @author Rus Carroll
+ * @version 1.5 ($Rev: 210 $)
+ * @package PlaceLocalInclude
+ * @subpackage simple_html_dom
+ */
+
+/**
+ * All of the Defines for the classes below.
+ * @author S.C. Chen <me578022@gmail.com>
+ */
+define('HDOM_TYPE_ELEMENT', 1);
+define('HDOM_TYPE_COMMENT', 2);
+define('HDOM_TYPE_TEXT',	3);
+define('HDOM_TYPE_ENDTAG',  4);
+define('HDOM_TYPE_ROOT',	5);
+define('HDOM_TYPE_UNKNOWN', 6);
+define('HDOM_QUOTE_DOUBLE', 0);
+define('HDOM_QUOTE_SINGLE', 1);
+define('HDOM_QUOTE_NO',	 3);
+define('HDOM_INFO_BEGIN',   0);
+define('HDOM_INFO_END',	 1);
+define('HDOM_INFO_QUOTE',   2);
+define('HDOM_INFO_SPACE',   3);
+define('HDOM_INFO_TEXT',	4);
+define('HDOM_INFO_INNER',   5);
+define('HDOM_INFO_OUTER',   6);
+define('HDOM_INFO_ENDSPACE',7);
+define('DEFAULT_TARGET_CHARSET', 'UTF-8');
+define('DEFAULT_BR_TEXT', "\r\n");
+define('DEFAULT_SPAN_TEXT', " ");
+define('MAX_FILE_SIZE', 600000);
+// helper functions
+// -----------------------------------------------------------------------------
+// get html dom from file
+// $maxlen is defined in the code as PHP_STREAM_COPY_ALL which is defined as -1.
+function file_get_html($url, $use_include_path = false, $context=null, $offset = -1, $maxLen=-1, $lowercase = true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT)
+{
+	// We DO force the tags to be terminated.
+	$dom = new simple_html_dom(null, $lowercase, $forceTagsClosed, $target_charset, $stripRN, $defaultBRText, $defaultSpanText);
+	// For sourceforge users: uncomment the next line and comment the retreive_url_contents line 2 lines down if it is not already done.
+	$contents = file_get_contents($url, $use_include_path, $context, $offset);
+	// Paperg - use our own mechanism for getting the contents as we want to control the timeout.
+	//$contents = retrieve_url_contents($url);
+	if (empty($contents) || strlen($contents) > MAX_FILE_SIZE)
+	{
+		return false;
+	}
+	// The second parameter can force the selectors to all be lowercase.
+	$dom->load($contents, $lowercase, $stripRN);
+	return $dom;
+}
+
+// get html dom from string
+function str_get_html($str, $lowercase=true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT)
+{
+	$dom = new simple_html_dom(null, $lowercase, $forceTagsClosed, $target_charset, $stripRN, $defaultBRText, $defaultSpanText);
+	if (empty($str) || strlen($str) > MAX_FILE_SIZE)
+	{
+		$dom->clear();
+		return false;
+	}
+	$dom->load($str, $lowercase, $stripRN);
+	return $dom;
+}
+
+// dump html dom tree
+function dump_html_tree($node, $show_attr=true, $deep=0)
+{
+	$node->dump($node);
+}
+
+
+/**
+ * simple html dom node
+ * PaperG - added ability for "find" routine to lowercase the value of the selector.
+ * PaperG - added $tag_start to track the start position of the tag in the total byte index
+ *
+ * @package PlaceLocalInclude
+ */
+class simple_html_dom_node
+{
+	public $nodetype = HDOM_TYPE_TEXT;
+	public $tag = 'text';
+	public $attr = array();
+	public $children = array();
+	public $nodes = array();
+	public $parent = null;
+	// The "info" array - see HDOM_INFO_... for what each element contains.
+	public $_ = array();
+	public $tag_start = 0;
+	private $dom = null;
+
+	function __construct($dom)
+	{
+		$this->dom = $dom;
+		$dom->nodes[] = $this;
+	}
+
+	function __destruct()
+	{
+		$this->clear();
+	}
+
+	function __toString()
+	{
+		return $this->outertext();
+	}
+
+	// clean up memory due to php5 circular references memory leak...
+	function clear()
+	{
+		$this->dom = null;
+		$this->nodes = null;
+		$this->parent = null;
+		$this->children = null;
+	}
+
+	// dump node's tree
+	function dump($show_attr=true, $deep=0)
+	{
+		$lead = str_repeat('	', $deep);
+
+		echo $lead.$this->tag;
+		if ($show_attr && count($this->attr)>0)
+		{
+			echo '(';
+			foreach ($this->attr as $k=>$v)
+				echo "[$k]=>\"".$this->$k.'", ';
+			echo ')';
+		}
+		echo "\n";
+
+		if ($this->nodes)
+		{
+			foreach ($this->nodes as $c)
+			{
+				$c->dump($show_attr, $deep+1);
+			}
+		}
+	}
+
+
+	// Debugging function to dump a single dom node with a bunch of information about it.
+	function dump_node($echo=true)
+	{
+
+		$string = $this->tag;
+		if (count($this->attr)>0)
+		{
+			$string .= '(';
+			foreach ($this->attr as $k=>$v)
+			{
+				$string .= "[$k]=>\"".$this->$k.'", ';
+			}
+			$string .= ')';
+		}
+		if (count($this->_)>0)
+		{
+			$string .= ' $_ (';
+			foreach ($this->_ as $k=>$v)
+			{
+				if (is_array($v))
+				{
+					$string .= "[$k]=>(";
+					foreach ($v as $k2=>$v2)
+					{
+						$string .= "[$k2]=>\"".$v2.'", ';
+					}
+					$string .= ")";
+				} else {
+					$string .= "[$k]=>\"".$v.'", ';
+				}
+			}
+			$string .= ")";
+		}
+
+		if (isset($this->text))
+		{
+			$string .= " text: (" . $this->text . ")";
+		}
+
+		$string .= " HDOM_INNER_INFO: '";
+		if (isset($node->_[HDOM_INFO_INNER]))
+		{
+			$string .= $node->_[HDOM_INFO_INNER] . "'";
+		}
+		else
+		{
+			$string .= ' NULL ';
+		}
+
+		$string .= " children: " . count($this->children);
+		$string .= " nodes: " . count($this->nodes);
+		$string .= " tag_start: " . $this->tag_start;
+		$string .= "\n";
+
+		if ($echo)
+		{
+			echo $string;
+			return;
+		}
+		else
+		{
+			return $string;
+		}
+	}
+
+	// returns the parent of node
+	// If a node is passed in, it will reset the parent of the current node to that one.
+	function parent($parent=null)
+	{
+		// I am SURE that this doesn't work properly.
+		// It fails to unset the current node from it's current parents nodes or children list first.
+		if ($parent !== null)
+		{
+			$this->parent = $parent;
+			$this->parent->nodes[] = $this;
+			$this->parent->children[] = $this;
+		}
+
+		return $this->parent;
+	}
+
+	// verify that node has children
+	function has_child()
+	{
+		return !empty($this->children);
+	}
+
+	// returns children of node
+	function children($idx=-1)
+	{
+		if ($idx===-1)
+		{
+			return $this->children;
+		}
+		if (isset($this->children[$idx]))
+		{
+			return $this->children[$idx];
+		}
+		return null;
+	}
+
+	// returns the first child of node
+	function first_child()
+	{
+		if (count($this->children)>0)
+		{
+			return $this->children[0];
+		}
+		return null;
+	}
+
+	// returns the last child of node
+	function last_child()
+	{
+		if (($count=count($this->children))>0)
+		{
+			return $this->children[$count-1];
+		}
+		return null;
+	}
+
+	// returns the next sibling of node
+	function next_sibling()
+	{
+		if ($this->parent===null)
+		{
+			return null;
+		}
+
+		$idx = 0;
+		$count = count($this->parent->children);
+		while ($idx<$count && $this!==$this->parent->children[$idx])
+		{
+			++$idx;
+		}
+		if (++$idx>=$count)
+		{
+			return null;
+		}
+		return $this->parent->children[$idx];
+	}
+
+	// returns the previous sibling of node
+	function prev_sibling()
+	{
+		if ($this->parent===null) return null;
+		$idx = 0;
+		$count = count($this->parent->children);
+		while ($idx<$count && $this!==$this->parent->children[$idx])
+			++$idx;
+		if (--$idx<0) return null;
+		return $this->parent->children[$idx];
+	}
+
+	// function to locate a specific ancestor tag in the path to the root.
+	function find_ancestor_tag($tag)
+	{
+		global $debug_object;
+		if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
+
+		// Start by including ourselves in the comparison.
+		$returnDom = $this;
+
+		while (!is_null($returnDom))
+		{
+			if (is_object($debug_object)) { $debug_object->debug_log(2, "Current tag is: " . $returnDom->tag); }
+
+			if ($returnDom->tag == $tag)
+			{
+				break;
+			}
+			$returnDom = $returnDom->parent;
+		}
+		return $returnDom;
+	}
+
+	// get dom node's inner html
+	function innertext()
+	{
+		if (isset($this->_[HDOM_INFO_INNER])) return $this->_[HDOM_INFO_INNER];
+		if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
+
+		$ret = '';
+		foreach ($this->nodes as $n)
+			$ret .= $n->outertext();
+		return $ret;
+	}
+
+	// get dom node's outer text (with tag)
+	function outertext()
+	{
+		global $debug_object;
+		if (is_object($debug_object))
+		{
+			$text = '';
+			if ($this->tag == 'text')
+			{
+				if (!empty($this->text))
+				{
+					$text = " with text: " . $this->text;
+				}
+			}
+			$debug_object->debug_log(1, 'Innertext of tag: ' . $this->tag . $text);
+		}
+
+		if ($this->tag==='root') return $this->innertext();
+
+		// trigger callback
+		if ($this->dom && $this->dom->callback!==null)
+		{
+			call_user_func_array($this->dom->callback, array($this));
+		}
+
+		if (isset($this->_[HDOM_INFO_OUTER])) return $this->_[HDOM_INFO_OUTER];
+		if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
+
+		// render begin tag
+		if ($this->dom && $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]])
+		{
+			$ret = $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]->makeup();
+		} else {
+			$ret = "";
+		}
+
+		// render inner text
+		if (isset($this->_[HDOM_INFO_INNER]))
+		{
+			// If it's a br tag...  don't return the HDOM_INNER_INFO that we may or may not have added.
+			if ($this->tag != "br")
+			{
+				$ret .= $this->_[HDOM_INFO_INNER];
+			}
+		} else {
+			if ($this->nodes)
+			{
+				foreach ($this->nodes as $n)
+				{
+					$ret .= $this->convert_text($n->outertext());
+				}
+			}
+		}
+
+		// render end tag
+		if (isset($this->_[HDOM_INFO_END]) && $this->_[HDOM_INFO_END]!=0)
+			$ret .= '</'.$this->tag.'>';
+		return $ret;
+	}
+
+	// get dom node's plain text
+	function text()
+	{
+		if (isset($this->_[HDOM_INFO_INNER])) return $this->_[HDOM_INFO_INNER];
+		switch ($this->nodetype)
+		{
+			case HDOM_TYPE_TEXT: return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
+			case HDOM_TYPE_COMMENT: return '';
+			case HDOM_TYPE_UNKNOWN: return '';
+		}
+		if (strcasecmp($this->tag, 'script')===0) return '';
+		if (strcasecmp($this->tag, 'style')===0) return '';
+
+		$ret = '';
+		// In rare cases, (always node type 1 or HDOM_TYPE_ELEMENT - observed for some span tags, and some p tags) $this->nodes is set to NULL.
+		// NOTE: This indicates that there is a problem where it's set to NULL without a clear happening.
+		// WHY is this happening?
+		if (!is_null($this->nodes))
+		{
+			foreach ($this->nodes as $n)
+			{
+				$ret .= $this->convert_text($n->text());
+			}
+
+			// If this node is a span... add a space at the end of it so multiple spans don't run into each other.  This is plaintext after all.
+			if ($this->tag == "span")
+			{
+				$ret .= $this->dom->default_span_text;
+			}
+
+
+		}
+		return $ret;
+	}
+
+	function xmltext()
+	{
+		$ret = $this->innertext();
+		$ret = str_ireplace('<![CDATA[', '', $ret);
+		$ret = str_replace(']]>', '', $ret);
+		return $ret;
+	}
+
+	// build node's text with tag
+	function makeup()
+	{
+		// text, comment, unknown
+		if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
+
+		$ret = '<'.$this->tag;
+		$i = -1;
+
+		foreach ($this->attr as $key=>$val)
+		{
+			++$i;
+
+			// skip removed attribute
+			if ($val===null || $val===false)
+				continue;
+
+			$ret .= $this->_[HDOM_INFO_SPACE][$i][0];
+			//no value attr: nowrap, checked selected...
+			if ($val===true)
+				$ret .= $key;
+			else {
+				switch ($this->_[HDOM_INFO_QUOTE][$i])
+				{
+					case HDOM_QUOTE_DOUBLE: $quote = '"'; break;
+					case HDOM_QUOTE_SINGLE: $quote = '\''; break;
+					default: $quote = '';
+				}
+				$ret .= $key.$this->_[HDOM_INFO_SPACE][$i][1].'='.$this->_[HDOM_INFO_SPACE][$i][2].$quote.$val.$quote;
+			}
+		}
+		$ret = $this->dom->restore_noise($ret);
+		return $ret . $this->_[HDOM_INFO_ENDSPACE] . '>';
+	}
+
+	// find elements by css selector
+	//PaperG - added ability for find to lowercase the value of the selector.
+	function find($selector, $idx=null, $lowercase=false)
+	{
+		$selectors = $this->parse_selector($selector);
+		if (($count=count($selectors))===0) return array();
+		$found_keys = array();
+
+		// find each selector
+		for ($c=0; $c<$count; ++$c)
+		{
+			// The change on the below line was documented on the sourceforge code tracker id 2788009
+			// used to be: if (($levle=count($selectors[0]))===0) return array();
+			if (($levle=count($selectors[$c]))===0) return array();
+			if (!isset($this->_[HDOM_INFO_BEGIN])) return array();
+
+			$head = array($this->_[HDOM_INFO_BEGIN]=>1);
+
+			// handle descendant selectors, no recursive!
+			for ($l=0; $l<$levle; ++$l)
+			{
+				$ret = array();
+				foreach ($head as $k=>$v)
+				{
+					$n = ($k===-1) ? $this->dom->root : $this->dom->nodes[$k];
+					//PaperG - Pass this optional parameter on to the seek function.
+					$n->seek($selectors[$c][$l], $ret, $lowercase);
+				}
+				$head = $ret;
+			}
+
+			foreach ($head as $k=>$v)
+			{
+				if (!isset($found_keys[$k]))
+				{
+					$found_keys[$k] = 1;
+				}
+			}
+		}
+
+		// sort keys
+		ksort($found_keys);
+
+		$found = array();
+		foreach ($found_keys as $k=>$v)
+			$found[] = $this->dom->nodes[$k];
+
+		// return nth-element or array
+		if (is_null($idx)) return $found;
+		else if ($idx<0) $idx = count($found) + $idx;
+		return (isset($found[$idx])) ? $found[$idx] : null;
+	}
+
+	// seek for given conditions
+	// PaperG - added parameter to allow for case insensitive testing of the value of a selector.
+	protected function seek($selector, &$ret, $lowercase=false)
+	{
+		global $debug_object;
+		if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
+
+		list($tag, $key, $val, $exp, $no_key) = $selector;
+
+		// xpath index
+		if ($tag && $key && is_numeric($key))
+		{
+			$count = 0;
+			foreach ($this->children as $c)
+			{
+				if ($tag==='*' || $tag===$c->tag) {
+					if (++$count==$key) {
+						$ret[$c->_[HDOM_INFO_BEGIN]] = 1;
+						return;
+					}
+				}
+			}
+			return;
+		}
+
+		$end = (!empty($this->_[HDOM_INFO_END])) ? $this->_[HDOM_INFO_END] : 0;
+		if ($end==0) {
+			$parent = $this->parent;
+			while (!isset($parent->_[HDOM_INFO_END]) && $parent!==null) {
+				$end -= 1;
+				$parent = $parent->parent;
+			}
+			$end += $parent->_[HDOM_INFO_END];
+		}
+
+		for ($i=$this->_[HDOM_INFO_BEGIN]+1; $i<$end; ++$i) {
+			$node = $this->dom->nodes[$i];
+
+			$pass = true;
+
+			if ($tag==='*' && !$key) {
+				if (in_array($node, $this->children, true))
+					$ret[$i] = 1;
+				continue;
+			}
+
+			// compare tag
+			if ($tag && $tag!=$node->tag && $tag!=='*') {$pass=false;}
+			// compare key
+			if ($pass && $key) {
+				if ($no_key) {
+					if (isset($node->attr[$key])) $pass=false;
+				} else {
+					if (($key != "plaintext") && !isset($node->attr[$key])) $pass=false;
+				}
+			}
+			// compare value
+			if ($pass && $key && $val  && $val!=='*') {
+				// If they have told us that this is a "plaintext" search then we want the plaintext of the node - right?
+				if ($key == "plaintext") {
+					// $node->plaintext actually returns $node->text();
+					$nodeKeyValue = $node->text();
+				} else {
+					// this is a normal search, we want the value of that attribute of the tag.
+					$nodeKeyValue = $node->attr[$key];
+				}
+				if (is_object($debug_object)) {$debug_object->debug_log(2, "testing node: " . $node->tag . " for attribute: " . $key . $exp . $val . " where nodes value is: " . $nodeKeyValue);}
+
+				//PaperG - If lowercase is set, do a case insensitive test of the value of the selector.
+				if ($lowercase) {
+					$check = $this->match($exp, strtolower($val), strtolower($nodeKeyValue));
+				} else {
+					$check = $this->match($exp, $val, $nodeKeyValue);
+				}
+				if (is_object($debug_object)) {$debug_object->debug_log(2, "after match: " . ($check ? "true" : "false"));}
+
+				// handle multiple class
+				if (!$check && strcasecmp($key, 'class')===0) {
+					foreach (explode(' ',$node->attr[$key]) as $k) {
+						// Without this, there were cases where leading, trailing, or double spaces lead to our comparing blanks - bad form.
+						if (!empty($k)) {
+							if ($lowercase) {
+								$check = $this->match($exp, strtolower($val), strtolower($k));
+							} else {
+								$check = $this->match($exp, $val, $k);
+							}
+							if ($check) break;
+						}
+					}
+				}
+				if (!$check) $pass = false;
+			}
+			if ($pass) $ret[$i] = 1;
+			unset($node);
+		}
+		// It's passed by reference so this is actually what this function returns.
+		if (is_object($debug_object)) {$debug_object->debug_log(1, "EXIT - ret: ", $ret);}
+	}
+
+	protected function match($exp, $pattern, $value) {
+		global $debug_object;
+		if (is_object($debug_object)) {$debug_object->debug_log_entry(1);}
+
+		switch ($exp) {
+			case '=':
+				return ($value===$pattern);
+			case '!=':
+				return ($value!==$pattern);
+			case '^=':
+				return preg_match("/^".preg_quote($pattern,'/')."/", $value);
+			case '$=':
+				return preg_match("/".preg_quote($pattern,'/')."$/", $value);
+			case '*=':
+				if ($pattern[0]=='/') {
+					return preg_match($pattern, $value);
+				}
+				return preg_match("/".$pattern."/i", $value);
+		}
+		return false;
+	}
+
+	protected function parse_selector($selector_string) {
+		global $debug_object;
+		if (is_object($debug_object)) {$debug_object->debug_log_entry(1);}
+
+		// pattern of CSS selectors, modified from mootools
+		// Paperg: Add the colon to the attrbute, so that it properly finds <tag attr:ibute="something" > like google does.
+		// Note: if you try to look at this attribute, yo MUST use getAttribute since $dom->x:y will fail the php syntax check.
+// Notice the \[ starting the attbute?  and the @? following?  This implies that an attribute can begin with an @ sign that is not captured.
+// This implies that an html attribute specifier may start with an @ sign that is NOT captured by the expression.
+// farther study is required to determine of this should be documented or removed.
+//		$pattern = "/([\w-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is";
+		$pattern = "/([\w-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-:]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is";
+		preg_match_all($pattern, trim($selector_string).' ', $matches, PREG_SET_ORDER);
+		if (is_object($debug_object)) {$debug_object->debug_log(2, "Matches Array: ", $matches);}
+
+		$selectors = array();
+		$result = array();
+		//print_r($matches);
+
+		foreach ($matches as $m) {
+			$m[0] = trim($m[0]);
+			if ($m[0]==='' || $m[0]==='/' || $m[0]==='//') continue;
+			// for browser generated xpath
+			if ($m[1]==='tbody') continue;
+
+			list($tag, $key, $val, $exp, $no_key) = array($m[1], null, null, '=', false);
+			if (!empty($m[2])) {$key='id'; $val=$m[2];}
+			if (!empty($m[3])) {$key='class'; $val=$m[3];}
+			if (!empty($m[4])) {$key=$m[4];}
+			if (!empty($m[5])) {$exp=$m[5];}
+			if (!empty($m[6])) {$val=$m[6];}
+
+			// convert to lowercase
+			if ($this->dom->lowercase) {$tag=strtolower($tag); $key=strtolower($key);}
+			//elements that do NOT have the specified attribute
+			if (isset($key[0]) && $key[0]==='!') {$key=substr($key, 1); $no_key=true;}
+
+			$result[] = array($tag, $key, $val, $exp, $no_key);
+			if (trim($m[7])===',') {
+				$selectors[] = $result;
+				$result = array();
+			}
+		}
+		if (count($result)>0)
+			$selectors[] = $result;
+		return $selectors;
+	}
+
+	function __get($name)
+	{
+		if (isset($this->attr[$name]))
+		{
+			return $this->convert_text($this->attr[$name]);
+		}
+		switch ($name)
+		{
+			case 'outertext': return $this->outertext();
+			case 'innertext': return $this->innertext();
+			case 'plaintext': return $this->text();
+			case 'xmltext': return $this->xmltext();
+			default: return array_key_exists($name, $this->attr);
+		}
+	}
+
+	function __set($name, $value)
+	{
+		global $debug_object;
+		if (is_object($debug_object)) {$debug_object->debug_log_entry(1);}
+
+		switch ($name)
+		{
+			case 'outertext': return $this->_[HDOM_INFO_OUTER] = $value;
+			case 'innertext':
+				if (isset($this->_[HDOM_INFO_TEXT])) return $this->_[HDOM_INFO_TEXT] = $value;
+				return $this->_[HDOM_INFO_INNER] = $value;
+		}
+		if (!isset($this->attr[$name]))
+		{
+			$this->_[HDOM_INFO_SPACE][] = array(' ', '', '');
+			$this->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE;
+		}
+		$this->attr[$name] = $value;
+	}
+
+	function __isset($name)
+	{
+		switch ($name)
+		{
+			case 'outertext': return true;
+			case 'innertext': return true;
+			case 'plaintext': return true;
+		}
+		//no value attr: nowrap, checked selected...
+		return (array_key_exists($name, $this->attr)) ? true : isset($this->attr[$name]);
+	}
+
+	function __unset($name) {
+		if (isset($this->attr[$name]))
+			unset($this->attr[$name]);
+	}
+
+	// PaperG - Function to convert the text from one character set to another if the two sets are not the same.
+	function convert_text($text)
+	{
+		global $debug_object;
+		if (is_object($debug_object)) {$debug_object->debug_log_entry(1);}
+
+		$converted_text = $text;
+
+		$sourceCharset = "";
+		$targetCharset = "";
+
+		if ($this->dom)
+		{
+			$sourceCharset = strtoupper($this->dom->_charset);
+			$targetCharset = strtoupper($this->dom->_target_charset);
+		}
+		if (is_object($debug_object)) {$debug_object->debug_log(3, "source charset: " . $sourceCharset . " target charaset: " . $targetCharset);}
+
+		if (!empty($sourceCharset) && !empty($targetCharset) && (strcasecmp($sourceCharset, $targetCharset) != 0))
+		{
+			// Check if the reported encoding could have been incorrect and the text is actually already UTF-8
+			if ((strcasecmp($targetCharset, 'UTF-8') == 0) && ($this->is_utf8($text)))
+			{
+				$converted_text = $text;
+			}
+			else
+			{
+				$converted_text = iconv($sourceCharset, $targetCharset, $text);
+			}
+		}
+
+		// Lets make sure that we don't have that silly BOM issue with any of the utf-8 text we output.
+		if ($targetCharset == 'UTF-8')
+		{
+			if (substr($converted_text, 0, 3) == "\xef\xbb\xbf")
+			{
+				$converted_text = substr($converted_text, 3);
+			}
+			if (substr($converted_text, -3) == "\xef\xbb\xbf")
+			{
+				$converted_text = substr($converted_text, 0, -3);
+			}
+		}
+
+		return $converted_text;
+	}
+
+	/**
+	* Returns true if $string is valid UTF-8 and false otherwise.
+	*
+	* @param mixed $str String to be tested
+	* @return boolean
+	*/
+	static function is_utf8($str)
+	{
+		$c=0; $b=0;
+		$bits=0;
+		$len=strlen($str);
+		for($i=0; $i<$len; $i++)
+		{
+			$c=ord($str[$i]);
+			if($c > 128)
+			{
+				if(($c >= 254)) return false;
+				elseif($c >= 252) $bits=6;
+				elseif($c >= 248) $bits=5;
+				elseif($c >= 240) $bits=4;
+				elseif($c >= 224) $bits=3;
+				elseif($c >= 192) $bits=2;
+				else return false;
+				if(($i+$bits) > $len) return false;
+				while($bits > 1)
+				{
+					$i++;
+					$b=ord($str[$i]);
+					if($b < 128 || $b > 191) return false;
+					$bits--;
+				}
+			}
+		}
+		return true;
+	}
+	/*
+	function is_utf8($string)
+	{
+		//this is buggy
+		return (utf8_encode(utf8_decode($string)) == $string);
+	}
+	*/
+
+	/**
+	 * Function to try a few tricks to determine the displayed size of an img on the page.
+	 * NOTE: This will ONLY work on an IMG tag. Returns FALSE on all other tag types.
+	 *
+	 * @author John Schlick
+	 * @version April 19 2012
+	 * @return array an array containing the 'height' and 'width' of the image on the page or -1 if we can't figure it out.
+	 */
+	function get_display_size()
+	{
+		global $debug_object;
+
+		$width = -1;
+		$height = -1;
+
+		if ($this->tag !== 'img')
+		{
+			return false;
+		}
+
+		// See if there is aheight or width attribute in the tag itself.
+		if (isset($this->attr['width']))
+		{
+			$width = $this->attr['width'];
+		}
+
+		if (isset($this->attr['height']))
+		{
+			$height = $this->attr['height'];
+		}
+
+		// Now look for an inline style.
+		if (isset($this->attr['style']))
+		{
+			// Thanks to user gnarf from stackoverflow for this regular expression.
+			$attributes = array();
+			preg_match_all("/([\w-]+)\s*:\s*([^;]+)\s*;?/", $this->attr['style'], $matches, PREG_SET_ORDER);
+			foreach ($matches as $match) {
+			  $attributes[$match[1]] = $match[2];
+			}
+
+			// If there is a width in the style attributes:
+			if (isset($attributes['width']) && $width == -1)
+			{
+				// check that the last two characters are px (pixels)
+				if (strtolower(substr($attributes['width'], -2)) == 'px')
+				{
+					$proposed_width = substr($attributes['width'], 0, -2);
+					// Now make sure that it's an integer and not something stupid.
+					if (filter_var($proposed_width, FILTER_VALIDATE_INT))
+					{
+						$width = $proposed_width;
+					}
+				}
+			}
+
+			// If there is a width in the style attributes:
+			if (isset($attributes['height']) && $height == -1)
+			{
+				// check that the last two characters are px (pixels)
+				if (strtolower(substr($attributes['height'], -2)) == 'px')
+				{
+					$proposed_height = substr($attributes['height'], 0, -2);
+					// Now make sure that it's an integer and not something stupid.
+					if (filter_var($proposed_height, FILTER_VALIDATE_INT))
+					{
+						$height = $proposed_height;
+					}
+				}
+			}
+
+		}
+
+		// Future enhancement:
+		// Look in the tag to see if there is a class or id specified that has a height or width attribute to it.
+
+		// Far future enhancement
+		// Look at all the parent tags of this image to see if they specify a class or id that has an img selector that specifies a height or width
+		// Note that in this case, the class or id will have the img subselector for it to apply to the image.
+
+		// ridiculously far future development
+		// If the class or id is specified in a SEPARATE css file thats not on the page, go get it and do what we were just doing for the ones on the page.
+
+		$result = array('height' => $height,
+						'width' => $width);
+		return $result;
+	}
+
+	// camel naming conventions
+	function getAllAttributes() {return $this->attr;}
+	function getAttribute($name) {return $this->__get($name);}
+	function setAttribute($name, $value) {$this->__set($name, $value);}
+	function hasAttribute($name) {return $this->__isset($name);}
+	function removeAttribute($name) {$this->__set($name, null);}
+	function getElementById($id) {return $this->find("#$id", 0);}
+	function getElementsById($id, $idx=null) {return $this->find("#$id", $idx);}
+	function getElementByTagName($name) {return $this->find($name, 0);}
+	function getElementsByTagName($name, $idx=null) {return $this->find($name, $idx);}
+	function parentNode() {return $this->parent();}
+	function childNodes($idx=-1) {return $this->children($idx);}
+	function firstChild() {return $this->first_child();}
+	function lastChild() {return $this->last_child();}
+	function nextSibling() {return $this->next_sibling();}
+	function previousSibling() {return $this->prev_sibling();}
+	function hasChildNodes() {return $this->has_child();}
+	function nodeName() {return $this->tag;}
+	function appendChild($node) {$node->parent($this); return $node;}
+
+}
+
+/**
+ * simple html dom parser
+ * Paperg - in the find routine: allow us to specify that we want case insensitive testing of the value of the selector.
+ * Paperg - change $size from protected to public so we can easily access it
+ * Paperg - added ForceTagsClosed in the constructor which tells us whether we trust the html or not.  Default is to NOT trust it.
+ *
+ * @package PlaceLocalInclude
+ */
+class simple_html_dom
+{
+	public $root = null;
+	public $nodes = array();
+	public $callback = null;
+	public $lowercase = false;
+	// Used to keep track of how large the text was when we started.
+	public $original_size;
+	public $size;
+	protected $pos;
+	protected $doc;
+	protected $char;
+	protected $cursor;
+	protected $parent;
+	protected $noise = array();
+	protected $token_blank = " \t\r\n";
+	protected $token_equal = ' =/>';
+	protected $token_slash = " />\r\n\t";
+	protected $token_attr = ' >';
+	// Note that this is referenced by a child node, and so it needs to be public for that node to see this information.
+	public $_charset = '';
+	public $_target_charset = '';
+	protected $default_br_text = "";
+	public $default_span_text = "";
+
+	// use isset instead of in_array, performance boost about 30%...
+	protected $self_closing_tags = array('img'=>1, 'br'=>1, 'input'=>1, 'meta'=>1, 'link'=>1, 'hr'=>1, 'base'=>1, 'embed'=>1, 'spacer'=>1);
+	protected $block_tags = array('root'=>1, 'body'=>1, 'form'=>1, 'div'=>1, 'span'=>1, 'table'=>1);
+	// Known sourceforge issue #2977341
+	// B tags that are not closed cause us to return everything to the end of the document.
+	protected $optional_closing_tags = array(
+		'tr'=>array('tr'=>1, 'td'=>1, 'th'=>1),
+		'th'=>array('th'=>1),
+		'td'=>array('td'=>1),
+		'li'=>array('li'=>1),
+		'dt'=>array('dt'=>1, 'dd'=>1),
+		'dd'=>array('dd'=>1, 'dt'=>1),
+		'dl'=>array('dd'=>1, 'dt'=>1),
+		'p'=>array('p'=>1),
+		'nobr'=>array('nobr'=>1),
+		'b'=>array('b'=>1),
+		'option'=>array('option'=>1),
+	);
+
+	function __construct($str=null, $lowercase=true, $forceTagsClosed=true, $target_charset=DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT)
+	{
+		if ($str)
+		{
+			if (preg_match("/^http:\/\//i",$str) || is_file($str))
+			{
+				$this->load_file($str);
+			}
+			else
+			{
+				$this->load($str, $lowercase, $stripRN, $defaultBRText, $defaultSpanText);
+			}
+		}
+		// Forcing tags to be closed implies that we don't trust the html, but it can lead to parsing errors if we SHOULD trust the html.
+		if (!$forceTagsClosed) {
+			$this->optional_closing_array=array();
+		}
+		$this->_target_charset = $target_charset;
+	}
+
+	function __destruct()
+	{
+		$this->clear();
+	}
+
+	// load html from string
+	function load($str, $lowercase=true, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT)
+	{
+		global $debug_object;
+
+		// prepare
+		$this->prepare($str, $lowercase, $stripRN, $defaultBRText, $defaultSpanText);
+		// strip out cdata
+		$this->remove_noise("'<!\[CDATA\[(.*?)\]\]>'is", true);
+		// strip out comments
+		$this->remove_noise("'<!--(.*?)-->'is");
+		// Per sourceforge http://sourceforge.net/tracker/?func=detail&aid=2949097&group_id=218559&atid=1044037
+		// Script tags removal now preceeds style tag removal.
+		// strip out <script> tags
+		$this->remove_noise("'<\s*script[^>]*[^/]>(.*?)<\s*/\s*script\s*>'is");
+		$this->remove_noise("'<\s*script\s*>(.*?)<\s*/\s*script\s*>'is");
+		// strip out <style> tags
+		$this->remove_noise("'<\s*style[^>]*[^/]>(.*?)<\s*/\s*style\s*>'is");
+		$this->remove_noise("'<\s*style\s*>(.*?)<\s*/\s*style\s*>'is");
+		// strip out preformatted tags
+		$this->remove_noise("'<\s*(?:code)[^>]*>(.*?)<\s*/\s*(?:code)\s*>'is");
+		// strip out server side scripts
+		$this->remove_noise("'(<\?)(.*?)(\?>)'s", true);
+		// strip smarty scripts
+		$this->remove_noise("'(\{\w)(.*?)(\})'s", true);
+
+		// parsing
+		while ($this->parse());
+		// end
+		$this->root->_[HDOM_INFO_END] = $this->cursor;
+		$this->parse_charset();
+
+		// make load function chainable
+		return $this;
+
+	}
+
+	// load html from file
+	function load_file()
+	{
+		$args = func_get_args();
+		$this->load(call_user_func_array('file_get_contents', $args), true);
+		// Throw an error if we can't properly load the dom.
+		if (($error=error_get_last())!==null) {
+			$this->clear();
+			return false;
+		}
+	}
+
+	// set callback function
+	function set_callback($function_name)
+	{
+		$this->callback = $function_name;
+	}
+
+	// remove callback function
+	function remove_callback()
+	{
+		$this->callback = null;
+	}
+
+	// save dom as string
+	function save($filepath='')
+	{
+		$ret = $this->root->innertext();
+		if ($filepath!=='') file_put_contents($filepath, $ret, LOCK_EX);
+		return $ret;
+	}
+
+	// find dom node by css selector
+	// Paperg - allow us to specify that we want case insensitive testing of the value of the selector.
+	function find($selector, $idx=null, $lowercase=false)
+	{
+		return $this->root->find($selector, $idx, $lowercase);
+	}
+
+	// clean up memory due to php5 circular references memory leak...
+	function clear()
+	{
+		foreach ($this->nodes as $n) {$n->clear(); $n = null;}
+		// This add next line is documented in the sourceforge repository. 2977248 as a fix for ongoing memory leaks that occur even with the use of clear.
+		if (isset($this->children)) foreach ($this->children as $n) {$n->clear(); $n = null;}
+		if (isset($this->parent)) {$this->parent->clear(); unset($this->parent);}
+		if (isset($this->root)) {$this->root->clear(); unset($this->root);}
+		unset($this->doc);
+		unset($this->noise);
+	}
+
+	function dump($show_attr=true)
+	{
+		$this->root->dump($show_attr);
+	}
+
+	// prepare HTML data and init everything
+	protected function prepare($str, $lowercase=true, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT)
+	{
+		$this->clear();
+
+		// set the length of content before we do anything to it.
+		$this->size = strlen($str);
+		// Save the original size of the html that we got in.  It might be useful to someone.
+		$this->original_size = $this->size;
+
+		//before we save the string as the doc...  strip out the \r \n's if we are told to.
+		if ($stripRN) {
+			$str = str_replace("\r", " ", $str);
+			$str = str_replace("\n", " ", $str);
+
+			// set the length of content since we have changed it.
+			$this->size = strlen($str);
+		}
+
+		$this->doc = $str;
+		$this->pos = 0;
+		$this->cursor = 1;
+		$this->noise = array();
+		$this->nodes = array();
+		$this->lowercase = $lowercase;
+		$this->default_br_text = $defaultBRText;
+		$this->default_span_text = $defaultSpanText;
+		$this->root = new simple_html_dom_node($this);
+		$this->root->tag = 'root';
+		$this->root->_[HDOM_INFO_BEGIN] = -1;
+		$this->root->nodetype = HDOM_TYPE_ROOT;
+		$this->parent = $this->root;
+		if ($this->size>0) $this->char = $this->doc[0];
+	}
+
+	// parse html content
+	protected function parse()
+	{
+		if (($s = $this->copy_until_char('<'))==='')
+		{
+			return $this->read_tag();
+		}
+
+		// text
+		$node = new simple_html_dom_node($this);
+		++$this->cursor;
+		$node->_[HDOM_INFO_TEXT] = $s;
+		$this->link_nodes($node, false);
+		return true;
+	}
+
+	// PAPERG - dkchou - added this to try to identify the character set of the page we have just parsed so we know better how to spit it out later.
+	// NOTE:  IF you provide a routine called get_last_retrieve_url_contents_content_type which returns the CURLINFO_CONTENT_TYPE from the last curl_exec
+	// (or the content_type header from the last transfer), we will parse THAT, and if a charset is specified, we will use it over any other mechanism.
+	protected function parse_charset()
+	{
+		global $debug_object;
+
+		$charset = null;
+
+		if (function_exists('get_last_retrieve_url_contents_content_type'))
+		{
+			$contentTypeHeader = get_last_retrieve_url_contents_content_type();
+			$success = preg_match('/charset=(.+)/', $contentTypeHeader, $matches);
+			if ($success)
+			{
+				$charset = $matches[1];
+				if (is_object($debug_object)) {$debug_object->debug_log(2, 'header content-type found charset of: ' . $charset);}
+			}
+
+		}
+
+		if (empty($charset))
+		{
+			$el = $this->root->find('meta[http-equiv=Content-Type]',0, true);
+			if (!empty($el))
+			{
+				$fullvalue = $el->content;
+				if (is_object($debug_object)) {$debug_object->debug_log(2, 'meta content-type tag found' . $fullvalue);}
+
+				if (!empty($fullvalue))
+				{
+					$success = preg_match('/charset=(.+)/i', $fullvalue, $matches);
+					if ($success)
+					{
+						$charset = $matches[1];
+					}
+					else
+					{
+						// If there is a meta tag, and they don't specify the character set, research says that it's typically ISO-8859-1
+						if (is_object($debug_object)) {$debug_object->debug_log(2, 'meta content-type tag couldn\'t be parsed. using iso-8859 default.');}
+						$charset = 'ISO-8859-1';
+					}
+				}
+			}
+		}
+
+		// If we couldn't find a charset above, then lets try to detect one based on the text we got...
+		if (empty($charset))
+		{
+			// Use this in case mb_detect_charset isn't installed/loaded on this machine.
+			$charset = false;
+			if (function_exists('mb_detect_encoding'))
+			{
+				// Have php try to detect the encoding from the text given to us.
+				$charset = mb_detect_encoding($this->root->plaintext . "ascii", $encoding_list = array( "UTF-8", "CP1252" ) );
+				if (is_object($debug_object)) {$debug_object->debug_log(2, 'mb_detect found: ' . $charset);}
+			}
+
+			// and if this doesn't work...  then we need to just wrongheadedly assume it's UTF-8 so that we can move on - cause this will usually give us most of what we need...
+			if ($charset === false)
+			{
+				if (is_object($debug_object)) {$debug_object->debug_log(2, 'since mb_detect failed - using default of utf-8');}
+				$charset = 'UTF-8';
+			}
+		}
+
+		// Since CP1252 is a superset, if we get one of it's subsets, we want it instead.
+		if ((strtolower($charset) == strtolower('ISO-8859-1')) || (strtolower($charset) == strtolower('Latin1')) || (strtolower($charset) == strtolower('Latin-1')))
+		{
+			if (is_object($debug_object)) {$debug_object->debug_log(2, 'replacing ' . $charset . ' with CP1252 as its a superset');}
+			$charset = 'CP1252';
+		}
+
+		if (is_object($debug_object)) {$debug_object->debug_log(1, 'EXIT - ' . $charset);}
+
+		return $this->_charset = $charset;
+	}
+
+	// read tag info
+	protected function read_tag()
+	{
+		if ($this->char!=='<')
+		{
+			$this->root->_[HDOM_INFO_END] = $this->cursor;
+			return false;
+		}
+		$begin_tag_pos = $this->pos;
+		$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
+
+		// end tag
+		if ($this->char==='/')
+		{
+			$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
+			// This represents the change in the simple_html_dom trunk from revision 180 to 181.
+			// $this->skip($this->token_blank_t);
+			$this->skip($this->token_blank);
+			$tag = $this->copy_until_char('>');
+
+			// skip attributes in end tag
+			if (($pos = strpos($tag, ' '))!==false)
+				$tag = substr($tag, 0, $pos);
+
+			$parent_lower = strtolower($this->parent->tag);
+			$tag_lower = strtolower($tag);
+
+			if ($parent_lower!==$tag_lower)
+			{
+				if (isset($this->optional_closing_tags[$parent_lower]) && isset($this->block_tags[$tag_lower]))
+				{
+					$this->parent->_[HDOM_INFO_END] = 0;
+					$org_parent = $this->parent;
+
+					while (($this->parent->parent) && strtolower($this->parent->tag)!==$tag_lower)
+						$this->parent = $this->parent->parent;
+
+					if (strtolower($this->parent->tag)!==$tag_lower) {
+						$this->parent = $org_parent; // restore origonal parent
+						if ($this->parent->parent) $this->parent = $this->parent->parent;
+						$this->parent->_[HDOM_INFO_END] = $this->cursor;
+						return $this->as_text_node($tag);
+					}
+				}
+				else if (($this->parent->parent) && isset($this->block_tags[$tag_lower]))
+				{
+					$this->parent->_[HDOM_INFO_END] = 0;
+					$org_parent = $this->parent;
+
+					while (($this->parent->parent) && strtolower($this->parent->tag)!==$tag_lower)
+						$this->parent = $this->parent->parent;
+
+					if (strtolower($this->parent->tag)!==$tag_lower)
+					{
+						$this->parent = $org_parent; // restore origonal parent
+						$this->parent->_[HDOM_INFO_END] = $this->cursor;
+						return $this->as_text_node($tag);
+					}
+				}
+				else if (($this->parent->parent) && strtolower($this->parent->parent->tag)===$tag_lower)
+				{
+					$this->parent->_[HDOM_INFO_END] = 0;
+					$this->parent = $this->parent->parent;
+				}
+				else
+					return $this->as_text_node($tag);
+			}
+
+			$this->parent->_[HDOM_INFO_END] = $this->cursor;
+			if ($this->parent->parent) $this->parent = $this->parent->parent;
+
+			$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
+			return true;
+		}
+
+		$node = new simple_html_dom_node($this);
+		$node->_[HDOM_INFO_BEGIN] = $this->cursor;
+		++$this->cursor;
+		$tag = $this->copy_until($this->token_slash);
+		$node->tag_start = $begin_tag_pos;
+
+		// doctype, cdata & comments...
+		if (isset($tag[0]) && $tag[0]==='!') {
+			$node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until_char('>');
+
+			if (isset($tag[2]) && $tag[1]==='-' && $tag[2]==='-') {
+				$node->nodetype = HDOM_TYPE_COMMENT;
+				$node->tag = 'comment';
+			} else {
+				$node->nodetype = HDOM_TYPE_UNKNOWN;
+				$node->tag = 'unknown';
+			}
+			if ($this->char==='>') $node->_[HDOM_INFO_TEXT].='>';
+			$this->link_nodes($node, true);
+			$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
+			return true;
+		}
+
+		// text
+		if ($pos=strpos($tag, '<')!==false) {
+			$tag = '<' . substr($tag, 0, -1);
+			$node->_[HDOM_INFO_TEXT] = $tag;
+			$this->link_nodes($node, false);
+			$this->char = $this->doc[--$this->pos]; // prev
+			return true;
+		}
+
+		if (!preg_match("/^[\w-:]+$/", $tag)) {
+			$node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until('<>');
+			if ($this->char==='<') {
+				$this->link_nodes($node, false);
+				return true;
+			}
+
+			if ($this->char==='>') $node->_[HDOM_INFO_TEXT].='>';
+			$this->link_nodes($node, false);
+			$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
+			return true;
+		}
+
+		// begin tag
+		$node->nodetype = HDOM_TYPE_ELEMENT;
+		$tag_lower = strtolower($tag);
+		$node->tag = ($this->lowercase) ? $tag_lower : $tag;
+
+		// handle optional closing tags
+		if (isset($this->optional_closing_tags[$tag_lower]) )
+		{
+			while (isset($this->optional_closing_tags[$tag_lower][strtolower($this->parent->tag)]))
+			{
+				$this->parent->_[HDOM_INFO_END] = 0;
+				$this->parent = $this->parent->parent;
+			}
+			$node->parent = $this->parent;
+		}
+
+		$guard = 0; // prevent infinity loop
+		$space = array($this->copy_skip($this->token_blank), '', '');
+
+		// attributes
+		do
+		{
+			if ($this->char!==null && $space[0]==='')
+			{
+				break;
+			}
+			$name = $this->copy_until($this->token_equal);
+			if ($guard===$this->pos)
+			{
+				$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
+				continue;
+			}
+			$guard = $this->pos;
+
+			// handle endless '<'
+			if ($this->pos>=$this->size-1 && $this->char!=='>') {
+				$node->nodetype = HDOM_TYPE_TEXT;
+				$node->_[HDOM_INFO_END] = 0;
+				$node->_[HDOM_INFO_TEXT] = '<'.$tag . $space[0] . $name;
+				$node->tag = 'text';
+				$this->link_nodes($node, false);
+				return true;
+			}
+
+			// handle mismatch '<'
+			if ($this->doc[$this->pos-1]=='<') {
+				$node->nodetype = HDOM_TYPE_TEXT;
+				$node->tag = 'text';
+				$node->attr = array();
+				$node->_[HDOM_INFO_END] = 0;
+				$node->_[HDOM_INFO_TEXT] = substr($this->doc, $begin_tag_pos, $this->pos-$begin_tag_pos-1);
+				$this->pos -= 2;
+				$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
+				$this->link_nodes($node, false);
+				return true;
+			}
+
+			if ($name!=='/' && $name!=='') {
+				$space[1] = $this->copy_skip($this->token_blank);
+				$name = $this->restore_noise($name);
+				if ($this->lowercase) $name = strtolower($name);
+				if ($this->char==='=') {
+					$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
+					$this->parse_attr($node, $name, $space);
+				}
+				else {
+					//no value attr: nowrap, checked selected...
+					$node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO;
+					$node->attr[$name] = true;
+					if ($this->char!='>') $this->char = $this->doc[--$this->pos]; // prev
+				}
+				$node->_[HDOM_INFO_SPACE][] = $space;
+				$space = array($this->copy_skip($this->token_blank), '', '');
+			}
+			else
+				break;
+		} while ($this->char!=='>' && $this->char!=='/');
+
+		$this->link_nodes($node, true);
+		$node->_[HDOM_INFO_ENDSPACE] = $space[0];
+
+		// check self closing
+		if ($this->copy_until_char_escape('>')==='/')
+		{
+			$node->_[HDOM_INFO_ENDSPACE] .= '/';
+			$node->_[HDOM_INFO_END] = 0;
+		}
+		else
+		{
+			// reset parent
+			if (!isset($this->self_closing_tags[strtolower($node->tag)])) $this->parent = $node;
+		}
+		$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
+
+		// If it's a BR tag, we need to set it's text to the default text.
+		// This way when we see it in plaintext, we can generate formatting that the user wants.
+		// since a br tag never has sub nodes, this works well.
+		if ($node->tag == "br")
+		{
+			$node->_[HDOM_INFO_INNER] = $this->default_br_text;
+		}
+
+		return true;
+	}
+
+	// parse attributes
+	protected function parse_attr($node, $name, &$space)
+	{
+		// Per sourceforge: http://sourceforge.net/tracker/?func=detail&aid=3061408&group_id=218559&atid=1044037
+		// If the attribute is already defined inside a tag, only pay atetntion to the first one as opposed to the last one.
+		if (isset($node->attr[$name]))
+		{
+			return;
+		}
+
+		$space[2] = $this->copy_skip($this->token_blank);
+		switch ($this->char) {
+			case '"':
+				$node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE;
+				$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
+				$node->attr[$name] = $this->restore_noise($this->copy_until_char_escape('"'));
+				$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
+				break;
+			case '\'':
+				$node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_SINGLE;
+				$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
+				$node->attr[$name] = $this->restore_noise($this->copy_until_char_escape('\''));
+				$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
+				break;
+			default:
+				$node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO;
+				$node->attr[$name] = $this->restore_noise($this->copy_until($this->token_attr));
+		}
+		// PaperG: Attributes should not have \r or \n in them, that counts as html whitespace.
+		$node->attr[$name] = str_replace("\r", "", $node->attr[$name]);
+		$node->attr[$name] = str_replace("\n", "", $node->attr[$name]);
+		// PaperG: If this is a "class" selector, lets get rid of the preceeding and trailing space since some people leave it in the multi class case.
+		if ($name == "class") {
+			$node->attr[$name] = trim($node->attr[$name]);
+		}
+	}
+
+	// link node's parent
+	protected function link_nodes(&$node, $is_child)
+	{
+		$node->parent = $this->parent;
+		$this->parent->nodes[] = $node;
+		if ($is_child)
+		{
+			$this->parent->children[] = $node;
+		}
+	}
+
+	// as a text node
+	protected function as_text_node($tag)
+	{
+		$node = new simple_html_dom_node($this);
+		++$this->cursor;
+		$node->_[HDOM_INFO_TEXT] = '</' . $tag . '>';
+		$this->link_nodes($node, false);
+		$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
+		return true;
+	}
+
+	protected function skip($chars)
+	{
+		$this->pos += strspn($this->doc, $chars, $this->pos);
+		$this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
+	}
+
+	protected function copy_skip($chars)
+	{
+		$pos = $this->pos;
+		$len = strspn($this->doc, $chars, $pos);
+		$this->pos += $len;
+		$this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
+		if ($len===0) return '';
+		return substr($this->doc, $pos, $len);
+	}
+
+	protected function copy_until($chars)
+	{
+		$pos = $this->pos;
+		$len = strcspn($this->doc, $chars, $pos);
+		$this->pos += $len;
+		$this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
+		return substr($this->doc, $pos, $len);
+	}
+
+	protected function copy_until_char($char)
+	{
+		if ($this->char===null) return '';
+
+		if (($pos = strpos($this->doc, $char, $this->pos))===false) {
+			$ret = substr($this->doc, $this->pos, $this->size-$this->pos);
+			$this->char = null;
+			$this->pos = $this->size;
+			return $ret;
+		}
+
+		if ($pos===$this->pos) return '';
+		$pos_old = $this->pos;
+		$this->char = $this->doc[$pos];
+		$this->pos = $pos;
+		return substr($this->doc, $pos_old, $pos-$pos_old);
+	}
+
+	protected function copy_until_char_escape($char)
+	{
+		if ($this->char===null) return '';
+
+		$start = $this->pos;
+		while (1)
+		{
+			if (($pos = strpos($this->doc, $char, $start))===false)
+			{
+				$ret = substr($this->doc, $this->pos, $this->size-$this->pos);
+				$this->char = null;
+				$this->pos = $this->size;
+				return $ret;
+			}
+
+			if ($pos===$this->pos) return '';
+
+			if ($this->doc[$pos-1]==='\\') {
+				$start = $pos+1;
+				continue;
+			}
+
+			$pos_old = $this->pos;
+			$this->char = $this->doc[$pos];
+			$this->pos = $pos;
+			return substr($this->doc, $pos_old, $pos-$pos_old);
+		}
+	}
+
+	// remove noise from html content
+	// save the noise in the $this->noise array.
+	protected function remove_noise($pattern, $remove_tag=false)
+	{
+		global $debug_object;
+		if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
+
+		$count = preg_match_all($pattern, $this->doc, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
+
+		for ($i=$count-1; $i>-1; --$i)
+		{
+			$key = '___noise___'.sprintf('% 5d', count($this->noise)+1000);
+			if (is_object($debug_object)) { $debug_object->debug_log(2, 'key is: ' . $key); }
+			$idx = ($remove_tag) ? 0 : 1;
+			$this->noise[$key] = $matches[$i][$idx][0];
+			$this->doc = substr_replace($this->doc, $key, $matches[$i][$idx][1], strlen($matches[$i][$idx][0]));
+		}
+
+		// reset the length of content
+		$this->size = strlen($this->doc);
+		if ($this->size>0)
+		{
+			$this->char = $this->doc[0];
+		}
+	}
+
+	// restore noise to html content
+	function restore_noise($text)
+	{
+		global $debug_object;
+		if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
+
+		while (($pos=strpos($text, '___noise___'))!==false)
+		{
+			// Sometimes there is a broken piece of markup, and we don't GET the pos+11 etc... token which indicates a problem outside of us...
+			if (strlen($text) > $pos+15)
+			{
+				$key = '___noise___'.$text[$pos+11].$text[$pos+12].$text[$pos+13].$text[$pos+14].$text[$pos+15];
+				if (is_object($debug_object)) { $debug_object->debug_log(2, 'located key of: ' . $key); }
+
+				if (isset($this->noise[$key]))
+				{
+					$text = substr($text, 0, $pos).$this->noise[$key].substr($text, $pos+16);
+				}
+				else
+				{
+					// do this to prevent an infinite loop.
+					$text = substr($text, 0, $pos).'UNDEFINED NOISE FOR KEY: '.$key . substr($text, $pos+16);
+				}
+			}
+			else
+			{
+				// There is no valid key being given back to us... We must get rid of the ___noise___ or we will have a problem.
+				$text = substr($text, 0, $pos).'NO NUMERIC NOISE KEY' . substr($text, $pos+11);
+			}
+		}
+		return $text;
+	}
+
+	// Sometimes we NEED one of the noise elements.
+	function search_noise($text)
+	{
+		global $debug_object;
+		if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
+
+		foreach($this->noise as $noiseElement)
+		{
+			if (strpos($noiseElement, $text)!==false)
+			{
+				return $noiseElement;
+			}
+		}
+	}
+	function __toString()
+	{
+		return $this->root->innertext();
+	}
+
+	function __get($name)
+	{
+		switch ($name)
+		{
+			case 'outertext':
+				return $this->root->innertext();
+			case 'innertext':
+				return $this->root->innertext();
+			case 'plaintext':
+				return $this->root->text();
+			case 'charset':
+				return $this->_charset;
+			case 'target_charset':
+				return $this->_target_charset;
+		}
+	}
+
+	// camel naming conventions
+	function childNodes($idx=-1) {return $this->root->childNodes($idx);}
+	function firstChild() {return $this->root->first_child();}
+	function lastChild() {return $this->root->last_child();}
+	function createElement($name, $value=null) {return @str_get_html("<$name>$value</$name>")->first_child();}
+	function createTextNode($value) {return @end(str_get_html($value)->nodes);}
+	function getElementById($id) {return $this->find("#$id", 0);}
+	function getElementsById($id, $idx=null) {return $this->find("#$id", $idx);}
+	function getElementByTagName($name) {return $this->find($name, 0);}
+	function getElementsByTagName($name, $idx=-1) {return $this->find($name, $idx);}
+	function loadFile() {$args = func_get_args();$this->load_file($args);}
+}
+
+?>
\ No newline at end of file
diff --git a/panels/mensaPlan/style.less b/panels/mensaPlan/style.less
index de83b79389833d1ee0e2c33a785d3e6a0a8d2570..329030adc9f7730d4bee3fdce1bfdbfd8814b132 100755
--- a/panels/mensaPlan/style.less
+++ b/panels/mensaPlan/style.less
@@ -15,1230 +15,4 @@
 
 #mensaPlanTitleBar {
 	text-align: center;
-}
-
-/*! jQuery UI - v1.11.4 - 2015-03-11
-* http://jqueryui.com
-* Includes: core.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, draggable.css, menu.css, progressbar.css, resizable.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css
-* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
-* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
-
-/* Layout helpers
-----------------------------------*/
-.ui-helper-hidden {
-	display: none;
-}
-.ui-helper-hidden-accessible {
-	border: 0;
-	clip: rect(0 0 0 0);
-	height: 1px;
-	margin: -1px;
-	overflow: hidden;
-	padding: 0;
-	position: absolute;
-	width: 1px;
-}
-.ui-helper-reset {
-	margin: 0;
-	padding: 0;
-	border: 0;
-	outline: 0;
-	line-height: 1.3;
-	text-decoration: none;
-	font-size: 100%;
-	list-style: none;
-}
-.ui-helper-clearfix:before,
-.ui-helper-clearfix:after {
-	content: "";
-	display: table;
-	border-collapse: collapse;
-}
-.ui-helper-clearfix:after {
-	clear: both;
-}
-.ui-helper-clearfix {
-	min-height: 0; /* support: IE7 */
-}
-.ui-helper-zfix {
-	width: 100%;
-	height: 100%;
-	top: 0;
-	left: 0;
-	position: absolute;
-	opacity: 0;
-	filter:Alpha(Opacity=0); /* support: IE8 */
-}
-
-.ui-front {
-	z-index: 100;
-}
-
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-disabled {
-	cursor: default !important;
-}
-
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon {
-	display: block;
-	text-indent: -99999px;
-	overflow: hidden;
-	background-repeat: no-repeat;
-}
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Overlays */
-.ui-widget-overlay {
-	position: fixed;
-	top: 0;
-	left: 0;
-	width: 100%;
-	height: 100%;
-}
-.ui-accordion .ui-accordion-header {
-	display: block;
-	cursor: pointer;
-	position: relative;
-	margin: 2px 0 0 0;
-	padding: .5em .5em .5em .7em;
-	min-height: 0; /* support: IE7 */
-	font-size: 100%;
-}
-.ui-accordion .ui-accordion-icons {
-	padding-left: 2.2em;
-}
-.ui-accordion .ui-accordion-icons .ui-accordion-icons {
-	padding-left: 2.2em;
-}
-.ui-accordion .ui-accordion-header .ui-accordion-header-icon {
-	position: absolute;
-	left: .5em;
-	top: 50%;
-	margin-top: -8px;
-}
-.ui-accordion .ui-accordion-content {
-	padding: 1em 2.2em;
-	border-top: 0;
-	overflow: auto;
-}
-.ui-autocomplete {
-	position: absolute;
-	top: 0;
-	left: 0;
-	cursor: default;
-}
-.ui-button {
-	display: inline-block;
-	position: relative;
-	padding: 0;
-	line-height: normal;
-	margin-right: .1em;
-	cursor: pointer;
-	vertical-align: middle;
-	text-align: center;
-	overflow: visible; /* removes extra width in IE */
-}
-.ui-button,
-.ui-button:link,
-.ui-button:visited,
-.ui-button:hover,
-.ui-button:active {
-	text-decoration: none;
-}
-/* to make room for the icon, a width needs to be set here */
-.ui-button-icon-only {
-	width: 2.2em;
-}
-/* button elements seem to need a little more width */
-button.ui-button-icon-only {
-	width: 2.4em;
-}
-.ui-button-icons-only {
-	width: 3.4em;
-}
-button.ui-button-icons-only {
-	width: 3.7em;
-}
-
-/* button text element */
-.ui-button .ui-button-text {
-	display: block;
-	line-height: normal;
-}
-.ui-button-text-only .ui-button-text {
-	padding: .4em 1em;
-}
-.ui-button-icon-only .ui-button-text,
-.ui-button-icons-only .ui-button-text {
-	padding: .4em;
-	text-indent: -9999999px;
-}
-.ui-button-text-icon-primary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
-	padding: .4em 1em .4em 2.1em;
-}
-.ui-button-text-icon-secondary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
-	padding: .4em 2.1em .4em 1em;
-}
-.ui-button-text-icons .ui-button-text {
-	padding-left: 2.1em;
-	padding-right: 2.1em;
-}
-/* no icon support for input elements, provide padding by default */
-input.ui-button {
-	padding: .4em 1em;
-}
-
-/* button icon element(s) */
-.ui-button-icon-only .ui-icon,
-.ui-button-text-icon-primary .ui-icon,
-.ui-button-text-icon-secondary .ui-icon,
-.ui-button-text-icons .ui-icon,
-.ui-button-icons-only .ui-icon {
-	position: absolute;
-	top: 50%;
-	margin-top: -8px;
-}
-.ui-button-icon-only .ui-icon {
-	left: 50%;
-	margin-left: -8px;
-}
-.ui-button-text-icon-primary .ui-button-icon-primary,
-.ui-button-text-icons .ui-button-icon-primary,
-.ui-button-icons-only .ui-button-icon-primary {
-	left: .5em;
-}
-.ui-button-text-icon-secondary .ui-button-icon-secondary,
-.ui-button-text-icons .ui-button-icon-secondary,
-.ui-button-icons-only .ui-button-icon-secondary {
-	right: .5em;
-}
-
-/* button sets */
-.ui-buttonset {
-	margin-right: 7px;
-}
-.ui-buttonset .ui-button {
-	margin-left: 0;
-	margin-right: -.3em;
-}
-
-/* workarounds */
-/* reset extra padding in Firefox, see h5bp.com/l */
-input.ui-button::-moz-focus-inner,
-button.ui-button::-moz-focus-inner {
-	border: 0;
-	padding: 0;
-}
-.ui-datepicker {
-	width: 17em;
-	padding: .2em .2em 0;
-	display: none;
-}
-.ui-datepicker .ui-datepicker-header {
-	position: relative;
-	padding: .2em 0;
-}
-.ui-datepicker .ui-datepicker-prev,
-.ui-datepicker .ui-datepicker-next {
-	position: absolute;
-	top: 2px;
-	width: 1.8em;
-	height: 1.8em;
-}
-.ui-datepicker .ui-datepicker-prev-hover,
-.ui-datepicker .ui-datepicker-next-hover {
-	top: 1px;
-}
-.ui-datepicker .ui-datepicker-prev {
-	left: 2px;
-}
-.ui-datepicker .ui-datepicker-next {
-	right: 2px;
-}
-.ui-datepicker .ui-datepicker-prev-hover {
-	left: 1px;
-}
-.ui-datepicker .ui-datepicker-next-hover {
-	right: 1px;
-}
-.ui-datepicker .ui-datepicker-prev span,
-.ui-datepicker .ui-datepicker-next span {
-	display: block;
-	position: absolute;
-	left: 50%;
-	margin-left: -8px;
-	top: 50%;
-	margin-top: -8px;
-}
-.ui-datepicker .ui-datepicker-title {
-	margin: 0 2.3em;
-	line-height: 1.8em;
-	text-align: center;
-}
-.ui-datepicker .ui-datepicker-title select {
-	font-size: 1em;
-	margin: 1px 0;
-}
-.ui-datepicker select.ui-datepicker-month,
-.ui-datepicker select.ui-datepicker-year {
-	width: 45%;
-}
-.ui-datepicker table {
-	width: 100%;
-	font-size: .9em;
-	border-collapse: collapse;
-	margin: 0 0 .4em;
-}
-.ui-datepicker th {
-	padding: .7em .3em;
-	text-align: center;
-	font-weight: bold;
-	border: 0;
-}
-.ui-datepicker td {
-	border: 0;
-	padding: 1px;
-}
-.ui-datepicker td span,
-.ui-datepicker td a {
-	display: block;
-	padding: .2em;
-	text-align: right;
-	text-decoration: none;
-}
-.ui-datepicker .ui-datepicker-buttonpane {
-	background-image: none;
-	margin: .7em 0 0 0;
-	padding: 0 .2em;
-	border-left: 0;
-	border-right: 0;
-	border-bottom: 0;
-}
-.ui-datepicker .ui-datepicker-buttonpane button {
-	float: right;
-	margin: .5em .2em .4em;
-	cursor: pointer;
-	padding: .2em .6em .3em .6em;
-	width: auto;
-	overflow: visible;
-}
-.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
-	float: left;
-}
-
-/* with multiple calendars */
-.ui-datepicker.ui-datepicker-multi {
-	width: auto;
-}
-.ui-datepicker-multi .ui-datepicker-group {
-	float: left;
-}
-.ui-datepicker-multi .ui-datepicker-group table {
-	width: 95%;
-	margin: 0 auto .4em;
-}
-.ui-datepicker-multi-2 .ui-datepicker-group {
-	width: 50%;
-}
-.ui-datepicker-multi-3 .ui-datepicker-group {
-	width: 33.3%;
-}
-.ui-datepicker-multi-4 .ui-datepicker-group {
-	width: 25%;
-}
-.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
-.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
-	border-left-width: 0;
-}
-.ui-datepicker-multi .ui-datepicker-buttonpane {
-	clear: left;
-}
-.ui-datepicker-row-break {
-	clear: both;
-	width: 100%;
-	font-size: 0;
-}
-
-/* RTL support */
-.ui-datepicker-rtl {
-	direction: rtl;
-}
-.ui-datepicker-rtl .ui-datepicker-prev {
-	right: 2px;
-	left: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-next {
-	left: 2px;
-	right: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-prev:hover {
-	right: 1px;
-	left: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-next:hover {
-	left: 1px;
-	right: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane {
-	clear: right;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane button {
-	float: left;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
-.ui-datepicker-rtl .ui-datepicker-group {
-	float: right;
-}
-.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
-.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
-	border-right-width: 0;
-	border-left-width: 1px;
-}
-.ui-dialog {
-	overflow: hidden;
-	position: absolute;
-	top: 0;
-	left: 0;
-	padding: .2em;
-	outline: 0;
-}
-.ui-dialog .ui-dialog-titlebar {
-	padding: .4em 1em;
-	position: relative;
-}
-.ui-dialog .ui-dialog-title {
-	float: left;
-	margin: .1em 0;
-	white-space: nowrap;
-	width: 90%;
-	overflow: hidden;
-	text-overflow: ellipsis;
-}
-.ui-dialog .ui-dialog-titlebar-close {
-	position: absolute;
-	right: .3em;
-	top: 50%;
-	width: 20px;
-	margin: -10px 0 0 0;
-	padding: 1px;
-	height: 20px;
-}
-.ui-dialog .ui-dialog-content {
-	position: relative;
-	border: 0;
-	padding: .5em 1em;
-	background: none;
-	overflow: auto;
-}
-.ui-dialog .ui-dialog-buttonpane {
-	text-align: left;
-	border-width: 1px 0 0 0;
-	background-image: none;
-	margin-top: .5em;
-	padding: .3em 1em .5em .4em;
-}
-.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
-	float: right;
-}
-.ui-dialog .ui-dialog-buttonpane button {
-	margin: .5em .4em .5em 0;
-	cursor: pointer;
-}
-.ui-dialog .ui-resizable-se {
-	width: 12px;
-	height: 12px;
-	right: -5px;
-	bottom: -5px;
-	background-position: 16px 16px;
-}
-.ui-draggable .ui-dialog-titlebar {
-	cursor: move;
-}
-.ui-draggable-handle {
-	-ms-touch-action: none;
-	touch-action: none;
-}
-.ui-menu {
-	list-style: none;
-	padding: 0;
-	margin: 0;
-	display: block;
-	outline: none;
-}
-.ui-menu .ui-menu {
-	position: absolute;
-}
-.ui-menu .ui-menu-item {
-	position: relative;
-	margin: 0;
-	padding: 3px 1em 3px .4em;
-	cursor: pointer;
-	min-height: 0; /* support: IE7 */
-	/* support: IE10, see #8844 */
-	list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
-}
-.ui-menu .ui-menu-divider {
-	margin: 5px 0;
-	height: 0;
-	font-size: 0;
-	line-height: 0;
-	border-width: 1px 0 0 0;
-}
-.ui-menu .ui-state-focus,
-.ui-menu .ui-state-active {
-	margin: -1px;
-}
-
-/* icon support */
-.ui-menu-icons {
-	position: relative;
-}
-.ui-menu-icons .ui-menu-item {
-	padding-left: 2em;
-}
-
-/* left-aligned */
-.ui-menu .ui-icon {
-	position: absolute;
-	top: 0;
-	bottom: 0;
-	left: .2em;
-	margin: auto 0;
-}
-
-/* right-aligned */
-.ui-menu .ui-menu-icon {
-	left: auto;
-	right: 0;
-}
-.ui-progressbar {
-	height: 2em;
-	text-align: left;
-	overflow: hidden;
-}
-.ui-progressbar .ui-progressbar-value {
-	margin: -1px;
-	height: 100%;
-}
-.ui-progressbar .ui-progressbar-overlay {
-	background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");
-	height: 100%;
-	filter: alpha(opacity=25); /* support: IE8 */
-	opacity: 0.25;
-}
-.ui-progressbar-indeterminate .ui-progressbar-value {
-	background-image: none;
-}
-.ui-resizable {
-	position: relative;
-}
-.ui-resizable-handle {
-	position: absolute;
-	font-size: 0.1px;
-	display: block;
-	-ms-touch-action: none;
-	touch-action: none;
-}
-.ui-resizable-disabled .ui-resizable-handle,
-.ui-resizable-autohide .ui-resizable-handle {
-	display: none;
-}
-.ui-resizable-n {
-	cursor: n-resize;
-	height: 7px;
-	width: 100%;
-	top: -5px;
-	left: 0;
-}
-.ui-resizable-s {
-	cursor: s-resize;
-	height: 7px;
-	width: 100%;
-	bottom: -5px;
-	left: 0;
-}
-.ui-resizable-e {
-	cursor: e-resize;
-	width: 7px;
-	right: -5px;
-	top: 0;
-	height: 100%;
-}
-.ui-resizable-w {
-	cursor: w-resize;
-	width: 7px;
-	left: -5px;
-	top: 0;
-	height: 100%;
-}
-.ui-resizable-se {
-	cursor: se-resize;
-	width: 12px;
-	height: 12px;
-	right: 1px;
-	bottom: 1px;
-}
-.ui-resizable-sw {
-	cursor: sw-resize;
-	width: 9px;
-	height: 9px;
-	left: -5px;
-	bottom: -5px;
-}
-.ui-resizable-nw {
-	cursor: nw-resize;
-	width: 9px;
-	height: 9px;
-	left: -5px;
-	top: -5px;
-}
-.ui-resizable-ne {
-	cursor: ne-resize;
-	width: 9px;
-	height: 9px;
-	right: -5px;
-	top: -5px;
-}
-.ui-selectable {
-	-ms-touch-action: none;
-	touch-action: none;
-}
-.ui-selectable-helper {
-	position: absolute;
-	z-index: 100;
-	border: 1px dotted black;
-}
-.ui-selectmenu-menu {
-	padding: 0;
-	margin: 0;
-	position: absolute;
-	top: 0;
-	left: 0;
-	display: none;
-}
-.ui-selectmenu-menu .ui-menu {
-	overflow: auto;
-	/* Support: IE7 */
-	overflow-x: hidden;
-	padding-bottom: 1px;
-}
-.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
-	font-size: 1em;
-	font-weight: bold;
-	line-height: 1.5;
-	padding: 2px 0.4em;
-	margin: 0.5em 0 0 0;
-	height: auto;
-	border: 0;
-}
-.ui-selectmenu-open {
-	display: block;
-}
-.ui-selectmenu-button {
-	display: inline-block;
-	overflow: hidden;
-	position: relative;
-	text-decoration: none;
-	cursor: pointer;
-}
-.ui-selectmenu-button span.ui-icon {
-	right: 0.5em;
-	left: auto;
-	margin-top: -8px;
-	position: absolute;
-	top: 50%;
-}
-.ui-selectmenu-button span.ui-selectmenu-text {
-	text-align: left;
-	padding: 0.4em 2.1em 0.4em 1em;
-	display: block;
-	line-height: 1.4;
-	overflow: hidden;
-	text-overflow: ellipsis;
-	white-space: nowrap;
-}
-.ui-slider {
-	position: relative;
-	text-align: left;
-}
-.ui-slider .ui-slider-handle {
-	position: absolute;
-	z-index: 2;
-	width: 1.2em;
-	height: 1.2em;
-	cursor: default;
-	-ms-touch-action: none;
-	touch-action: none;
-}
-.ui-slider .ui-slider-range {
-	position: absolute;
-	z-index: 1;
-	font-size: .7em;
-	display: block;
-	border: 0;
-	background-position: 0 0;
-}
-
-/* support: IE8 - See #6727 */
-.ui-slider.ui-state-disabled .ui-slider-handle,
-.ui-slider.ui-state-disabled .ui-slider-range {
-	filter: inherit;
-}
-
-.ui-slider-horizontal {
-	height: .8em;
-}
-.ui-slider-horizontal .ui-slider-handle {
-	top: -.3em;
-	margin-left: -.6em;
-}
-.ui-slider-horizontal .ui-slider-range {
-	top: 0;
-	height: 100%;
-}
-.ui-slider-horizontal .ui-slider-range-min {
-	left: 0;
-}
-.ui-slider-horizontal .ui-slider-range-max {
-	right: 0;
-}
-
-.ui-slider-vertical {
-	width: .8em;
-	height: 100px;
-}
-.ui-slider-vertical .ui-slider-handle {
-	left: -.3em;
-	margin-left: 0;
-	margin-bottom: -.6em;
-}
-.ui-slider-vertical .ui-slider-range {
-	left: 0;
-	width: 100%;
-}
-.ui-slider-vertical .ui-slider-range-min {
-	bottom: 0;
-}
-.ui-slider-vertical .ui-slider-range-max {
-	top: 0;
-}
-.ui-sortable-handle {
-	-ms-touch-action: none;
-	touch-action: none;
-}
-.ui-spinner {
-	position: relative;
-	display: inline-block;
-	overflow: hidden;
-	padding: 0;
-	vertical-align: middle;
-}
-.ui-spinner-input {
-	border: none;
-	background: none;
-	color: inherit;
-	padding: 0;
-	margin: .2em 0;
-	vertical-align: middle;
-	margin-left: .4em;
-	margin-right: 22px;
-}
-.ui-spinner-button {
-	width: 16px;
-	height: 50%;
-	font-size: .5em;
-	padding: 0;
-	margin: 0;
-	text-align: center;
-	position: absolute;
-	cursor: default;
-	display: block;
-	overflow: hidden;
-	right: 0;
-}
-/* more specificity required here to override default borders */
-.ui-spinner a.ui-spinner-button {
-	border-top: none;
-	border-bottom: none;
-	border-right: none;
-}
-/* vertically center icon */
-.ui-spinner .ui-icon {
-	position: absolute;
-	margin-top: -8px;
-	top: 50%;
-	left: 0;
-}
-.ui-spinner-up {
-	top: 0;
-}
-.ui-spinner-down {
-	bottom: 0;
-}
-
-/* TR overrides */
-.ui-spinner .ui-icon-triangle-1-s {
-	/* need to fix icons sprite */
-	background-position: -65px -16px;
-}
-.ui-tabs {
-	position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
-	padding: .2em;
-}
-.ui-tabs .ui-tabs-nav {
-	margin: 0;
-	padding: .2em .2em 0;
-}
-.ui-tabs .ui-tabs-nav li {
-	list-style: none;
-	float: left;
-	position: relative;
-	top: 0;
-	margin: 1px .2em 0 0;
-	border-bottom-width: 0;
-	padding: 0;
-	white-space: nowrap;
-}
-.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
-	float: left;
-	padding: .5em 1em;
-	text-decoration: none;
-}
-.ui-tabs .ui-tabs-nav li.ui-tabs-active {
-	margin-bottom: -1px;
-	padding-bottom: 1px;
-}
-.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
-.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
-.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
-	cursor: text;
-}
-.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
-	cursor: pointer;
-}
-.ui-tabs .ui-tabs-panel {
-	display: block;
-	border-width: 0;
-	padding: 1em 1.4em;
-	background: none;
-}
-.ui-tooltip {
-	padding: 8px;
-	position: absolute;
-	z-index: 9999;
-	max-width: 300px;
-	-webkit-box-shadow: 0 0 5px #aaa;
-	box-shadow: 0 0 5px #aaa;
-}
-body .ui-tooltip {
-	border-width: 2px;
-}
-
-/* Component containers
-----------------------------------*/
-.ui-widget {
-	font-family: Verdana,Arial,sans-serif;
-	font-size: 2.5em;
-}
-.ui-widget .ui-widget {
-	font-size: 1em;
-}
-.ui-widget input,
-.ui-widget select,
-.ui-widget textarea,
-.ui-widget button {
-	font-family: Verdana,Arial,sans-serif;
-	font-size: 1em;
-}
-.ui-widget-content {
-	border: 1px solid #aaaaaa;
-	background: #ffffff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x;
-	color: #222222;
-}
-.ui-widget-content a {
-	color: #222222;
-}
-.ui-widget-header {
-	border: 1px solid #aaaaaa;
-	background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;
-	color: #222222;
-	font-weight: bold;
-}
-.ui-widget-header a {
-	color: #222222;
-}
-
-/* Interaction states
-----------------------------------*/
-.ui-state-default,
-.ui-widget-content .ui-state-default,
-.ui-widget-header .ui-state-default {
-	border: 1px solid #d3d3d3;
-	background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
-	font-weight: normal;
-	color: #555555;
-}
-.ui-state-default a,
-.ui-state-default a:link,
-.ui-state-default a:visited {
-	color: #555555;
-	text-decoration: none;
-}
-.ui-state-hover,
-.ui-widget-content .ui-state-hover,
-.ui-widget-header .ui-state-hover,
-.ui-state-focus,
-.ui-widget-content .ui-state-focus,
-.ui-widget-header .ui-state-focus {
-	border: 1px solid #999999;
-	background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;
-	font-weight: normal;
-	color: #212121;
-}
-.ui-state-hover a,
-.ui-state-hover a:hover,
-.ui-state-hover a:link,
-.ui-state-hover a:visited,
-.ui-state-focus a,
-.ui-state-focus a:hover,
-.ui-state-focus a:link,
-.ui-state-focus a:visited {
-	color: #212121;
-	text-decoration: none;
-}
-.ui-state-active,
-.ui-widget-content .ui-state-active,
-.ui-widget-header .ui-state-active {
-	border: 1px solid #aaaaaa;
-	background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
-	font-weight: normal;
-	color: #212121;
-}
-.ui-state-active a,
-.ui-state-active a:link,
-.ui-state-active a:visited {
-	color: #212121;
-	text-decoration: none;
-}
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-highlight,
-.ui-widget-content .ui-state-highlight,
-.ui-widget-header .ui-state-highlight {
-	border: 1px solid #fcefa1;
-	background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;
-	color: #363636;
-}
-.ui-state-highlight a,
-.ui-widget-content .ui-state-highlight a,
-.ui-widget-header .ui-state-highlight a {
-	color: #363636;
-}
-.ui-state-error,
-.ui-widget-content .ui-state-error,
-.ui-widget-header .ui-state-error {
-	border: 1px solid #cd0a0a;
-	background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;
-	color: #cd0a0a;
-}
-.ui-state-error a,
-.ui-widget-content .ui-state-error a,
-.ui-widget-header .ui-state-error a {
-	color: #cd0a0a;
-}
-.ui-state-error-text,
-.ui-widget-content .ui-state-error-text,
-.ui-widget-header .ui-state-error-text {
-	color: #cd0a0a;
-}
-.ui-priority-primary,
-.ui-widget-content .ui-priority-primary,
-.ui-widget-header .ui-priority-primary {
-	font-weight: bold;
-}
-.ui-priority-secondary,
-.ui-widget-content .ui-priority-secondary,
-.ui-widget-header .ui-priority-secondary {
-	opacity: .7;
-	filter:Alpha(Opacity=70); /* support: IE8 */
-	font-weight: normal;
-}
-.ui-state-disabled,
-.ui-widget-content .ui-state-disabled,
-.ui-widget-header .ui-state-disabled {
-	opacity: .35;
-	filter:Alpha(Opacity=35); /* support: IE8 */
-	background-image: none;
-}
-.ui-state-disabled .ui-icon {
-	filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
-}
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon {
-	width: 16px;
-	height: 16px;
-}
-.ui-icon,
-.ui-widget-content .ui-icon {
-	background-image: url("images/ui-icons_222222_256x240.png");
-}
-.ui-widget-header .ui-icon {
-	background-image: url("images/ui-icons_222222_256x240.png");
-}
-.ui-state-default .ui-icon {
-	background-image: url("images/ui-icons_888888_256x240.png");
-}
-.ui-state-hover .ui-icon,
-.ui-state-focus .ui-icon {
-	background-image: url("images/ui-icons_454545_256x240.png");
-}
-.ui-state-active .ui-icon {
-	background-image: url("images/ui-icons_454545_256x240.png");
-}
-.ui-state-highlight .ui-icon {
-	background-image: url("images/ui-icons_2e83ff_256x240.png");
-}
-.ui-state-error .ui-icon,
-.ui-state-error-text .ui-icon {
-	background-image: url("images/ui-icons_cd0a0a_256x240.png");
-}
-
-/* positioning */
-.ui-icon-blank { background-position: 16px 16px; }
-.ui-icon-carat-1-n { background-position: 0 0; }
-.ui-icon-carat-1-ne { background-position: -16px 0; }
-.ui-icon-carat-1-e { background-position: -32px 0; }
-.ui-icon-carat-1-se { background-position: -48px 0; }
-.ui-icon-carat-1-s { background-position: -64px 0; }
-.ui-icon-carat-1-sw { background-position: -80px 0; }
-.ui-icon-carat-1-w { background-position: -96px 0; }
-.ui-icon-carat-1-nw { background-position: -112px 0; }
-.ui-icon-carat-2-n-s { background-position: -128px 0; }
-.ui-icon-carat-2-e-w { background-position: -144px 0; }
-.ui-icon-triangle-1-n { background-position: 0 -16px; }
-.ui-icon-triangle-1-ne { background-position: -16px -16px; }
-.ui-icon-triangle-1-e { background-position: -32px -16px; }
-.ui-icon-triangle-1-se { background-position: -48px -16px; }
-.ui-icon-triangle-1-s { background-position: -64px -16px; }
-.ui-icon-triangle-1-sw { background-position: -80px -16px; }
-.ui-icon-triangle-1-w { background-position: -96px -16px; }
-.ui-icon-triangle-1-nw { background-position: -112px -16px; }
-.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
-.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
-.ui-icon-arrow-1-n { background-position: 0 -32px; }
-.ui-icon-arrow-1-ne { background-position: -16px -32px; }
-.ui-icon-arrow-1-e { background-position: -32px -32px; }
-.ui-icon-arrow-1-se { background-position: -48px -32px; }
-.ui-icon-arrow-1-s { background-position: -64px -32px; }
-.ui-icon-arrow-1-sw { background-position: -80px -32px; }
-.ui-icon-arrow-1-w { background-position: -96px -32px; }
-.ui-icon-arrow-1-nw { background-position: -112px -32px; }
-.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
-.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
-.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
-.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
-.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
-.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
-.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
-.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
-.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
-.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
-.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
-.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
-.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
-.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
-.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
-.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
-.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
-.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
-.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
-.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
-.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
-.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
-.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
-.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
-.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
-.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
-.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
-.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
-.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
-.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
-.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
-.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
-.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
-.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
-.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
-.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
-.ui-icon-arrow-4 { background-position: 0 -80px; }
-.ui-icon-arrow-4-diag { background-position: -16px -80px; }
-.ui-icon-extlink { background-position: -32px -80px; }
-.ui-icon-newwin { background-position: -48px -80px; }
-.ui-icon-refresh { background-position: -64px -80px; }
-.ui-icon-shuffle { background-position: -80px -80px; }
-.ui-icon-transfer-e-w { background-position: -96px -80px; }
-.ui-icon-transferthick-e-w { background-position: -112px -80px; }
-.ui-icon-folder-collapsed { background-position: 0 -96px; }
-.ui-icon-folder-open { background-position: -16px -96px; }
-.ui-icon-document { background-position: -32px -96px; }
-.ui-icon-document-b { background-position: -48px -96px; }
-.ui-icon-note { background-position: -64px -96px; }
-.ui-icon-mail-closed { background-position: -80px -96px; }
-.ui-icon-mail-open { background-position: -96px -96px; }
-.ui-icon-suitcase { background-position: -112px -96px; }
-.ui-icon-comment { background-position: -128px -96px; }
-.ui-icon-person { background-position: -144px -96px; }
-.ui-icon-print { background-position: -160px -96px; }
-.ui-icon-trash { background-position: -176px -96px; }
-.ui-icon-locked { background-position: -192px -96px; }
-.ui-icon-unlocked { background-position: -208px -96px; }
-.ui-icon-bookmark { background-position: -224px -96px; }
-.ui-icon-tag { background-position: -240px -96px; }
-.ui-icon-home { background-position: 0 -112px; }
-.ui-icon-flag { background-position: -16px -112px; }
-.ui-icon-calendar { background-position: -32px -112px; }
-.ui-icon-cart { background-position: -48px -112px; }
-.ui-icon-pencil { background-position: -64px -112px; }
-.ui-icon-clock { background-position: -80px -112px; }
-.ui-icon-disk { background-position: -96px -112px; }
-.ui-icon-calculator { background-position: -112px -112px; }
-.ui-icon-zoomin { background-position: -128px -112px; }
-.ui-icon-zoomout { background-position: -144px -112px; }
-.ui-icon-search { background-position: -160px -112px; }
-.ui-icon-wrench { background-position: -176px -112px; }
-.ui-icon-gear { background-position: -192px -112px; }
-.ui-icon-heart { background-position: -208px -112px; }
-.ui-icon-star { background-position: -224px -112px; }
-.ui-icon-link { background-position: -240px -112px; }
-.ui-icon-cancel { background-position: 0 -128px; }
-.ui-icon-plus { background-position: -16px -128px; }
-.ui-icon-plusthick { background-position: -32px -128px; }
-.ui-icon-minus { background-position: -48px -128px; }
-.ui-icon-minusthick { background-position: -64px -128px; }
-.ui-icon-close { background-position: -80px -128px; }
-.ui-icon-closethick { background-position: -96px -128px; }
-.ui-icon-key { background-position: -112px -128px; }
-.ui-icon-lightbulb { background-position: -128px -128px; }
-.ui-icon-scissors { background-position: -144px -128px; }
-.ui-icon-clipboard { background-position: -160px -128px; }
-.ui-icon-copy { background-position: -176px -128px; }
-.ui-icon-contact { background-position: -192px -128px; }
-.ui-icon-image { background-position: -208px -128px; }
-.ui-icon-video { background-position: -224px -128px; }
-.ui-icon-script { background-position: -240px -128px; }
-.ui-icon-alert { background-position: 0 -144px; }
-.ui-icon-info { background-position: -16px -144px; }
-.ui-icon-notice { background-position: -32px -144px; }
-.ui-icon-help { background-position: -48px -144px; }
-.ui-icon-check { background-position: -64px -144px; }
-.ui-icon-bullet { background-position: -80px -144px; }
-.ui-icon-radio-on { background-position: -96px -144px; }
-.ui-icon-radio-off { background-position: -112px -144px; }
-.ui-icon-pin-w { background-position: -128px -144px; }
-.ui-icon-pin-s { background-position: -144px -144px; }
-.ui-icon-play { background-position: 0 -160px; }
-.ui-icon-pause { background-position: -16px -160px; }
-.ui-icon-seek-next { background-position: -32px -160px; }
-.ui-icon-seek-prev { background-position: -48px -160px; }
-.ui-icon-seek-end { background-position: -64px -160px; }
-.ui-icon-seek-start { background-position: -80px -160px; }
-/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
-.ui-icon-seek-first { background-position: -80px -160px; }
-.ui-icon-stop { background-position: -96px -160px; }
-.ui-icon-eject { background-position: -112px -160px; }
-.ui-icon-volume-off { background-position: -128px -160px; }
-.ui-icon-volume-on { background-position: -144px -160px; }
-.ui-icon-power { background-position: 0 -176px; }
-.ui-icon-signal-diag { background-position: -16px -176px; }
-.ui-icon-signal { background-position: -32px -176px; }
-.ui-icon-battery-0 { background-position: -48px -176px; }
-.ui-icon-battery-1 { background-position: -64px -176px; }
-.ui-icon-battery-2 { background-position: -80px -176px; }
-.ui-icon-battery-3 { background-position: -96px -176px; }
-.ui-icon-circle-plus { background-position: 0 -192px; }
-.ui-icon-circle-minus { background-position: -16px -192px; }
-.ui-icon-circle-close { background-position: -32px -192px; }
-.ui-icon-circle-triangle-e { background-position: -48px -192px; }
-.ui-icon-circle-triangle-s { background-position: -64px -192px; }
-.ui-icon-circle-triangle-w { background-position: -80px -192px; }
-.ui-icon-circle-triangle-n { background-position: -96px -192px; }
-.ui-icon-circle-arrow-e { background-position: -112px -192px; }
-.ui-icon-circle-arrow-s { background-position: -128px -192px; }
-.ui-icon-circle-arrow-w { background-position: -144px -192px; }
-.ui-icon-circle-arrow-n { background-position: -160px -192px; }
-.ui-icon-circle-zoomin { background-position: -176px -192px; }
-.ui-icon-circle-zoomout { background-position: -192px -192px; }
-.ui-icon-circle-check { background-position: -208px -192px; }
-.ui-icon-circlesmall-plus { background-position: 0 -208px; }
-.ui-icon-circlesmall-minus { background-position: -16px -208px; }
-.ui-icon-circlesmall-close { background-position: -32px -208px; }
-.ui-icon-squaresmall-plus { background-position: -48px -208px; }
-.ui-icon-squaresmall-minus { background-position: -64px -208px; }
-.ui-icon-squaresmall-close { background-position: -80px -208px; }
-.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
-.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
-.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
-.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
-.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
-.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Corner radius */
-.ui-corner-all,
-.ui-corner-top,
-.ui-corner-left,
-.ui-corner-tl {
-	border-top-left-radius: 4px;
-}
-.ui-corner-all,
-.ui-corner-top,
-.ui-corner-right,
-.ui-corner-tr {
-	border-top-right-radius: 4px;
-}
-.ui-corner-all,
-.ui-corner-bottom,
-.ui-corner-left,
-.ui-corner-bl {
-	border-bottom-left-radius: 4px;
-}
-.ui-corner-all,
-.ui-corner-bottom,
-.ui-corner-right,
-.ui-corner-br {
-	border-bottom-right-radius: 4px;
-}
-
-/* Overlays */
-.ui-widget-overlay {
-	background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
-	opacity: .3;
-	filter: Alpha(Opacity=30); /* support: IE8 */
-}
-.ui-widget-shadow {
-	margin: -8px 0 0 -8px;
-	padding: 8px;
-	background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
-	opacity: .3;
-	filter: Alpha(Opacity=30); /* support: IE8 */
-	border-radius: 8px;
 }
\ No newline at end of file
diff --git a/panels/mensaPlan/tag.php b/panels/mensaPlan/tag.php
new file mode 100644
index 0000000000000000000000000000000000000000..4bfc63ceae69d2a43475704343f93fc47396ce20
--- /dev/null
+++ b/panels/mensaPlan/tag.php
@@ -0,0 +1,89 @@
+<?php
+class TAG {
+	private $nr = 0;
+	private $name = 0;
+	private $gerichte = array ();
+	private $date = "";
+	function __construct($name, $date) {
+		$this->name = $name;
+		$this->date = $date;
+		switch ($name) {
+			case "montag" :
+				$this->nr = 1;
+				break;
+			case "dienstag" :
+				$this->nr = 2;
+				break;
+			case "mittwoch" :
+				$this->nr = 3;
+				break;
+			case "donnertag" :
+				$this->nr = 4;
+				break;
+			case "freitag" :
+				$this->nr = 5;
+				break;
+			case "samstag" :
+				$this->nr = 6;
+				break;
+			case "sonntag" :
+				$this->nr = 7;
+				breakM;
+		}
+	}
+	public function getNr() {
+		return $this->nr;
+	}
+	public function getName() {
+		return $this->name;
+	}
+	public function getGerichte() {
+		return $this->gerichte;
+	}
+	public function getDate() {
+		return $this->date;
+	}
+	public function setNr($nr) {
+		$this->nr = $nr;
+	}
+	public function setName($name) {
+		$this->name = $name;
+	}
+	public function setGerichte($gerichte) {
+		$this->gerichte = $gerichte;
+	}
+	public function setDate() {
+		$this->date = $date;
+	}
+	public function addGericht($gericht) {
+		array_push ( $this->gerichte, $gericht );
+	}
+	public function addGerichte($gerichte) {
+		foreach ( $gerichte as $gericht ) {
+			array_push ( $this->gerichte, $gericht );
+		}
+	}
+	public function toJson($inc_nr = true, $inc_original = true, $inc_short = true, $inc_art = true, $inc_kind = true, $inc_counter = true, $inc_stoffe = true, $inc_date = true) {
+		$kommata = false;
+		$json = '"' . $this->name . '":[';
+		foreach ( $this->gerichte as $gericht ) {
+			if ($kommata) {
+				$json .= ',';
+			} else {
+				$kommata = true;
+			}
+			$json .= $gericht->toJson ( $inc_nr,$inc_original, $inc_short, $inc_art, $inc_kind, $inc_counter, $inc_stoffe, $inc_date );
+		}
+		$json .= ']';
+		return $json;
+	}
+	public function __toString() {
+		$string = "Nr: " . $this->nr . ", Name: " . $this->name . ", Gerichte: ";
+		foreach ( $this->gerichte as $gericht ) {
+			$string .= $gericht;
+		}
+		$string .= ", Date: " . $this->date;
+		return $string;
+	}
+}
+?>
\ No newline at end of file
diff --git a/panels/topListe/script.js b/panels/topListe/script.js
index 7b19e190aa2337ad83cef3310cb3a752e88d296b..fef4259f784ee2c1ae72743ec5878762b2e8e819 100644
--- a/panels/topListe/script.js
+++ b/panels/topListe/script.js
@@ -1,8 +1,15 @@
 this.loaded = function(panel, config) {
+<<<<<<< HEAD
 
 $(function() {
     $( "#sortable" ).sortable();
     $( "#sortable" ).disableSelection();
   });
 
-}
\ No newline at end of file
+}
+=======
+	var $li = $("<li class='ui-state-default'/>").text("BLA");
+    $("#sortable").append($li);
+    $("#sortable").sortable('refresh');
+}
+>>>>>>> remotes/origin/dev
diff --git a/panels/topListe/template.html b/panels/topListe/template.html
index c277180063a7c6c23b9c3a641878efa86c6eaf5d..f9387a2d73a3cc92c6706d3ffacacdc79b8bc366 100644
--- a/panels/topListe/template.html
+++ b/panels/topListe/template.html
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
 <div id="topListe">
 <div id="currentTop">
 	<div id="topName">
@@ -17,4 +18,9 @@
 		<li class="ui-state-default">Item 6</li>
 		<li class="ui-state-default">Item 7</li>
 	</ol>
-</div>
\ No newline at end of file
+</div>
+=======
+<ul id="sortable">
+  <li class="ui-state-default">Item 1</li>
+</ul>
+>>>>>>> remotes/origin/dev
diff --git a/panels/topListe/tops.json b/panels/topListe/tops.json
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/style.php b/style.php
deleted file mode 100755
index 9e7f53ec9348abbc114f5331e1f98fad98743489..0000000000000000000000000000000000000000
--- a/style.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-//header("content-type:text/css;charset=utf8");
-
-require "lessc.php";
-$less = new lessc();
-$style = $_GET["style"];
-echo $style;
-$less_file = "panels/$style/style.less";
-$css_file = "tmp/$style.css";
-
-if (!file_exists($less_file)) {
-http_response_code(404);
-echo $less_file." not found";
-return;
-}
-
-//if ( !file_exists($css_file))
-//{
-$code =
- $less->compile(
-  "[data-template=$style] {" .
-  file_get_contents( $less_file ) .
-  "}"
-);
-//}
-
-file_put_contents("tmp/" . $style . ".css", $code);
-
-header("Location: tmp/" . $style . ".css" );
-?>